2023-01-05 20:16:21 +08:00
import * as core from '@actions/core' ;
import * as exec from '@actions/exec' ;
import * as tc from '@actions/tool-cache' ;
import * as cache from '@actions/cache' ;
import fs from 'fs' ;
import path from 'path' ;
import osm from 'os' ;
import each from 'jest-each' ;
import * as main from '../src/main' ;
import * as util from '../src/util' ;
import OfficialBuilds from '../src/distributions/official_builds/official_builds' ;
describe ( 'main tests' , ( ) = > {
let inputs = { } as any ;
let os = { } as any ;
let infoSpy : jest.SpyInstance ;
let warningSpy : jest.SpyInstance ;
let inSpy : jest.SpyInstance ;
let setOutputSpy : jest.SpyInstance ;
let startGroupSpy : jest.SpyInstance ;
let endGroupSpy : jest.SpyInstance ;
let existsSpy : jest.SpyInstance ;
let getExecOutputSpy : jest.SpyInstance ;
let parseNodeVersionSpy : jest.SpyInstance ;
let cnSpy : jest.SpyInstance ;
let findSpy : jest.SpyInstance ;
let isCacheActionAvailable : jest.SpyInstance ;
let setupNodeJsSpy : jest.SpyInstance ;
2023-11-27 23:06:28 +08:00
let processExitSpy : jest.SpyInstance ;
2023-01-05 20:16:21 +08:00
beforeEach ( ( ) = > {
inputs = { } ;
// node
os = { } ;
console . log ( '::stop-commands::stoptoken' ) ;
process . env [ 'GITHUB_PATH' ] = '' ; // Stub out ENV file functionality so we can verify it writes to standard out
process . env [ 'GITHUB_OUTPUT' ] = '' ; // Stub out ENV file functionality so we can verify it writes to standard out
infoSpy = jest . spyOn ( core , 'info' ) ;
infoSpy . mockImplementation ( ( ) = > { } ) ;
setOutputSpy = jest . spyOn ( core , 'setOutput' ) ;
setOutputSpy . mockImplementation ( ( ) = > { } ) ;
warningSpy = jest . spyOn ( core , 'warning' ) ;
warningSpy . mockImplementation ( ( ) = > { } ) ;
startGroupSpy = jest . spyOn ( core , 'startGroup' ) ;
startGroupSpy . mockImplementation ( ( ) = > { } ) ;
endGroupSpy = jest . spyOn ( core , 'endGroup' ) ;
endGroupSpy . mockImplementation ( ( ) = > { } ) ;
inSpy = jest . spyOn ( core , 'getInput' ) ;
inSpy . mockImplementation ( name = > inputs [ name ] ) ;
getExecOutputSpy = jest . spyOn ( exec , 'getExecOutput' ) ;
findSpy = jest . spyOn ( tc , 'find' ) ;
isCacheActionAvailable = jest . spyOn ( cache , 'isFeatureAvailable' ) ;
existsSpy = jest . spyOn ( fs , 'existsSync' ) ;
cnSpy = jest . spyOn ( process . stdout , 'write' ) ;
cnSpy . mockImplementation ( line = > {
// uncomment to debug
// process.stderr.write('write:' + line + '\n');
} ) ;
setupNodeJsSpy = jest . spyOn ( OfficialBuilds . prototype , 'setupNodeJs' ) ;
setupNodeJsSpy . mockImplementation ( ( ) = > { } ) ;
2023-11-27 23:06:28 +08:00
processExitSpy = jest
. spyOn ( process , 'exit' )
. mockImplementation ( ( ( ) = > { } ) as ( ) = > never ) ;
2023-01-05 20:16:21 +08:00
} ) ;
afterEach ( ( ) = > {
jest . resetAllMocks ( ) ;
jest . clearAllMocks ( ) ;
//jest.restoreAllMocks();
} ) ;
afterAll ( async ( ) = > {
console . log ( '::stoptoken::' ) ;
jest . restoreAllMocks ( ) ;
} , 100000 ) ;
describe ( 'parseNodeVersionFile' , ( ) = > {
each `
contents | expected
$ { '12' } | $ { '12' }
$ { '12.3' } | $ { '12.3' }
$ { '12.3.4' } | $ { '12.3.4' }
$ { 'v12.3.4' } | $ { '12.3.4' }
$ { 'lts/erbium' } | $ { 'lts/erbium' }
$ { 'lts/*' } | $ { 'lts/*' }
$ { 'nodejs 12.3.4' } | $ { '12.3.4' }
$ { 'ruby 2.3.4\nnodejs 12.3.4\npython 3.4.5' } | $ { '12.3.4' }
$ { '' } | $ { '' }
$ { 'unknown format' } | $ { 'unknown format' }
$ { ' 14.1.0 ' } | $ { '14.1.0' }
$ { '{"volta": {"node": ">=14.0.0 <=17.0.0"}}' } | $ { '>=14.0.0 <=17.0.0' }
$ { '{"engines": {"node": "17.0.0"}}' } | $ { '17.0.0' }
` .it('parses " $ contents"', ({contents, expected}) => {
expect ( util . parseNodeVersionFile ( contents ) ) . toBe ( expected ) ;
} ) ;
} ) ;
describe ( 'printEnvDetailsAndSetOutput' , ( ) = > {
it . each ( [
[ { node : '12.0.2' , npm : '6.3.3' , yarn : '1.22.11' } ] ,
[ { node : '16.0.2' , npm : '7.3.3' , yarn : '2.22.11' } ] ,
[ { node : '14.0.1' , npm : '8.1.0' , yarn : '3.2.1' } ] ,
[ { node : '17.0.2' , npm : '6.3.3' , yarn : '' } ]
] ) ( 'Tools versions %p' , async obj = > {
getExecOutputSpy . mockImplementation ( async command = > {
if ( Reflect . has ( obj , command ) && ! obj [ command ] ) {
return {
stdout : '' ,
stderr : ` ${ command } does not exist ` ,
exitCode : 1
} ;
}
return { stdout : obj [ command ] , stderr : '' , exitCode : 0 } ;
} ) ;
await util . printEnvDetailsAndSetOutput ( ) ;
expect ( setOutputSpy ) . toHaveBeenCalledWith ( 'node-version' , obj [ 'node' ] ) ;
Object . getOwnPropertyNames ( obj ) . forEach ( name = > {
if ( ! obj [ name ] ) {
expect ( infoSpy ) . toHaveBeenCalledWith (
` [warning] ${ name } does not exist `
) ;
}
expect ( infoSpy ) . toHaveBeenCalledWith ( ` ${ name } : ${ obj [ name ] } ` ) ;
} ) ;
} ) ;
} ) ;
describe ( 'node-version-file flag' , ( ) = > {
beforeEach ( ( ) = > {
parseNodeVersionSpy = jest . spyOn ( util , 'parseNodeVersionFile' ) ;
} ) ;
it ( 'not used if node-version is provided' , async ( ) = > {
// Arrange
inputs [ 'node-version' ] = '12' ;
// Act
await main . run ( ) ;
// Assert
expect ( parseNodeVersionSpy ) . toHaveBeenCalledTimes ( 0 ) ;
} , 10000 ) ;
it ( 'not used if node-version-file not provided' , async ( ) = > {
// Act
await main . run ( ) ;
// Assert
expect ( parseNodeVersionSpy ) . toHaveBeenCalledTimes ( 0 ) ;
} ) ;
it ( 'reads node-version-file if provided' , async ( ) = > {
// Arrange
const versionSpec = 'v14' ;
const versionFile = '.nvmrc' ;
const expectedVersionSpec = '14' ;
process . env [ 'GITHUB_WORKSPACE' ] = path . join ( __dirname , 'data' ) ;
inputs [ 'node-version-file' ] = versionFile ;
parseNodeVersionSpy . mockImplementation ( ( ) = > expectedVersionSpec ) ;
existsSpy . mockImplementationOnce (
input = > input === path . join ( __dirname , 'data' , versionFile )
) ;
// Act
await main . run ( ) ;
// Assert
expect ( existsSpy ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( existsSpy ) . toHaveReturnedWith ( true ) ;
expect ( parseNodeVersionSpy ) . toHaveBeenCalledWith ( versionSpec ) ;
expect ( infoSpy ) . toHaveBeenCalledWith (
` Resolved ${ versionFile } as ${ expectedVersionSpec } `
) ;
} , 10000 ) ;
it ( 'reads package.json as node-version-file if provided' , async ( ) = > {
// Arrange
const versionSpec = fs . readFileSync (
path . join ( __dirname , 'data/package.json' ) ,
'utf-8'
) ;
const versionFile = 'package.json' ;
const expectedVersionSpec = '14' ;
process . env [ 'GITHUB_WORKSPACE' ] = path . join ( __dirname , 'data' ) ;
inputs [ 'node-version-file' ] = versionFile ;
parseNodeVersionSpy . mockImplementation ( ( ) = > expectedVersionSpec ) ;
existsSpy . mockImplementationOnce (
input = > input === path . join ( __dirname , 'data' , versionFile )
) ;
// Act
await main . run ( ) ;
// Assert
expect ( existsSpy ) . toHaveBeenCalledTimes ( 1 ) ;
expect ( existsSpy ) . toHaveReturnedWith ( true ) ;
expect ( parseNodeVersionSpy ) . toHaveBeenCalledWith ( versionSpec ) ;
expect ( infoSpy ) . toHaveBeenCalledWith (
` Resolved ${ versionFile } as ${ expectedVersionSpec } `
) ;
} , 10000 ) ;
it ( 'both node-version-file and node-version are provided' , async ( ) = > {
inputs [ 'node-version' ] = '12' ;
const versionSpec = 'v14' ;
const versionFile = '.nvmrc' ;
const expectedVersionSpec = '14' ;
process . env [ 'GITHUB_WORKSPACE' ] = path . join ( __dirname , '..' ) ;
inputs [ 'node-version-file' ] = versionFile ;
parseNodeVersionSpy . mockImplementation ( ( ) = > expectedVersionSpec ) ;
// Act
await main . run ( ) ;
// Assert
expect ( existsSpy ) . toHaveBeenCalledTimes ( 0 ) ;
expect ( parseNodeVersionSpy ) . not . toHaveBeenCalled ( ) ;
expect ( warningSpy ) . toHaveBeenCalledWith (
'Both node-version and node-version-file inputs are specified, only node-version will be used'
) ;
} ) ;
it ( 'should throw an error if node-version-file is not found' , async ( ) = > {
const versionFile = '.nvmrc' ;
const versionFilePath = path . join ( __dirname , '..' , versionFile ) ;
inputs [ 'node-version-file' ] = versionFile ;
inSpy . mockImplementation ( name = > inputs [ name ] ) ;
existsSpy . mockImplementationOnce (
input = > input === path . join ( __dirname , 'data' , versionFile )
) ;
// Act
await main . run ( ) ;
// Assert
expect ( existsSpy ) . toHaveBeenCalled ( ) ;
expect ( existsSpy ) . toHaveReturnedWith ( false ) ;
expect ( parseNodeVersionSpy ) . not . toHaveBeenCalled ( ) ;
expect ( cnSpy ) . toHaveBeenCalledWith (
` ::error::The specified node version file at: ${ versionFilePath } does not exist ${ osm . EOL } `
) ;
} ) ;
2023-11-27 23:06:28 +08:00
it ( 'should call process.exit() explicitly after running' , async ( ) = > {
await main . run ( ) ;
expect ( processExitSpy ) . toHaveBeenCalled ( ) ;
} ) ;
2023-01-05 20:16:21 +08:00
} ) ;
describe ( 'cache on GHES' , ( ) = > {
it ( 'Should throw an error, because cache is not supported' , async ( ) = > {
inputs [ 'node-version' ] = '12' ;
inputs [ 'cache' ] = 'npm' ;
inSpy . mockImplementation ( name = > inputs [ name ] ) ;
2023-03-08 16:47:38 +08:00
const toolPath = path . normalize ( '/cache/node/12.16.1/x64' ) ;
2023-01-05 20:16:21 +08:00
findSpy . mockImplementation ( ( ) = > toolPath ) ;
// expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`);
process . env [ 'GITHUB_SERVER_URL' ] = 'https://www.test.com' ;
isCacheActionAvailable . mockImplementation ( ( ) = > false ) ;
await main . run ( ) ;
expect ( warningSpy ) . toHaveBeenCalledWith (
` Cache action is only supported on GHES version >= 3.5. If you are on version >=3.5 Please check with GHES admin if Actions cache service is enabled or not. `
) ;
} ) ;
it ( 'Should throw an internal error' , async ( ) = > {
inputs [ 'node-version' ] = '12' ;
inputs [ 'cache' ] = 'npm' ;
inSpy . mockImplementation ( name = > inputs [ name ] ) ;
2023-03-08 16:47:38 +08:00
const toolPath = path . normalize ( '/cache/node/12.16.1/x64' ) ;
2023-01-05 20:16:21 +08:00
findSpy . mockImplementation ( ( ) = > toolPath ) ;
// expect(logSpy).toHaveBeenCalledWith(`Found in cache @ ${toolPath}`);
process . env [ 'GITHUB_SERVER_URL' ] = '' ;
isCacheActionAvailable . mockImplementation ( ( ) = > false ) ;
await main . run ( ) ;
expect ( warningSpy ) . toHaveBeenCalledWith (
'The runner was not able to contact the cache service. Caching will be skipped'
) ;
} ) ;
} ) ;
} ) ;