2022-05-25 12:07:29 +02:00
import * as exec from '@actions/exec' ;
import * as cache from '@actions/cache' ;
import * as core from '@actions/core' ;
import * as cacheUtils from '../src/cache-utils' ;
2023-02-01 13:10:38 +01:00
import {
getCurrentPackageManager ,
PackageManagerInfo
} from '../src/package-managers' ;
import fs , { Dirent , PathLike } from 'fs' ;
import { getPackageManagerInfo } from '../src/cache-utils' ;
import MockInstance = jest . MockInstance ;
2022-05-25 12:07:29 +02:00
describe ( 'getCommandOutput' , ( ) = > {
//Arrange
let getExecOutputSpy = jest . spyOn ( exec , 'getExecOutput' ) ;
it ( 'should return trimmed stdout in case of successful exit code' , async ( ) = > {
//Arrange
const stdoutResult = ' stdout ' ;
const trimmedStdout = stdoutResult . trim ( ) ;
getExecOutputSpy . mockImplementation ( ( commandLine : string ) = > {
return new Promise < exec.ExecOutput > ( resolve = > {
resolve ( { exitCode : 0 , stdout : stdoutResult , stderr : '' } ) ;
} ) ;
} ) ;
//Act + Assert
return cacheUtils
. getCommandOutput ( 'command' )
. then ( data = > expect ( data ) . toBe ( trimmedStdout ) ) ;
} ) ;
it ( 'should return error in case of unsuccessful exit code' , async ( ) = > {
//Arrange
const stderrResult = 'error message' ;
getExecOutputSpy . mockImplementation ( ( commandLine : string ) = > {
return new Promise < exec.ExecOutput > ( resolve = > {
resolve ( { exitCode : 10 , stdout : '' , stderr : stderrResult } ) ;
} ) ;
} ) ;
//Act + Assert
expect ( async ( ) = > {
await cacheUtils . getCommandOutput ( 'command' ) ;
} ) . rejects . toThrow ( ) ;
} ) ;
} ) ;
describe ( 'getPackageManagerInfo' , ( ) = > {
it ( 'should return package manager info in case of valid package manager name' , async ( ) = > {
//Arrange
const packageManagerName = 'default' ;
const expectedResult = {
dependencyFilePattern : 'go.sum' ,
cacheFolderCommandList : [ 'go env GOMODCACHE' , 'go env GOCACHE' ]
} ;
//Act + Assert
return cacheUtils
. getPackageManagerInfo ( packageManagerName )
. then ( data = > expect ( data ) . toEqual ( expectedResult ) ) ;
} ) ;
it ( 'should throw the error in case of invalid package manager name' , async ( ) = > {
//Arrange
const packageManagerName = 'invalidName' ;
//Act + Assert
expect ( async ( ) = > {
await cacheUtils . getPackageManagerInfo ( packageManagerName ) ;
} ) . rejects . toThrow ( ) ;
} ) ;
} ) ;
describe ( 'getCacheDirectoryPath' , ( ) = > {
//Arrange
let getExecOutputSpy = jest . spyOn ( exec , 'getExecOutput' ) ;
const validPackageManager : PackageManagerInfo = {
dependencyFilePattern : 'go.sum' ,
cacheFolderCommandList : [ 'go env GOMODCACHE' , 'go env GOCACHE' ]
} ;
it ( 'should return path to the cache folders which specified package manager uses' , async ( ) = > {
//Arrange
getExecOutputSpy . mockImplementation ( ( commandLine : string ) = > {
return new Promise < exec.ExecOutput > ( resolve = > {
resolve ( { exitCode : 0 , stdout : 'path/to/cache/folder' , stderr : '' } ) ;
} ) ;
} ) ;
const expectedResult = [ 'path/to/cache/folder' , 'path/to/cache/folder' ] ;
//Act + Assert
return cacheUtils
. getCacheDirectoryPath ( validPackageManager )
. then ( data = > expect ( data ) . toEqual ( expectedResult ) ) ;
} ) ;
2022-12-19 11:22:17 +01:00
it ( 'should return path to the cache folder if one command return empty str' , async ( ) = > {
//Arrange
getExecOutputSpy . mockImplementationOnce ( ( commandLine : string ) = > {
return new Promise < exec.ExecOutput > ( resolve = > {
resolve ( { exitCode : 0 , stdout : 'path/to/cache/folder' , stderr : '' } ) ;
} ) ;
} ) ;
getExecOutputSpy . mockImplementationOnce ( ( commandLine : string ) = > {
return new Promise < exec.ExecOutput > ( resolve = > {
resolve ( { exitCode : 0 , stdout : '' , stderr : '' } ) ;
} ) ;
} ) ;
const expectedResult = [ 'path/to/cache/folder' ] ;
//Act + Assert
return cacheUtils
. getCacheDirectoryPath ( validPackageManager )
. then ( data = > expect ( data ) . toEqual ( expectedResult ) ) ;
} ) ;
it ( 'should throw if the both commands return empty str' , async ( ) = > {
getExecOutputSpy . mockImplementation ( ( commandLine : string ) = > {
return new Promise < exec.ExecOutput > ( resolve = > {
resolve ( { exitCode : 10 , stdout : '' , stderr : '' } ) ;
} ) ;
} ) ;
//Act + Assert
expect ( async ( ) = > {
await cacheUtils . getCacheDirectoryPath ( validPackageManager ) ;
} ) . rejects . toThrow ( ) ;
} ) ;
2022-05-25 12:07:29 +02:00
it ( 'should throw if the specified package name is invalid' , async ( ) = > {
getExecOutputSpy . mockImplementation ( ( commandLine : string ) = > {
return new Promise < exec.ExecOutput > ( resolve = > {
resolve ( { exitCode : 10 , stdout : '' , stderr : 'Error message' } ) ;
} ) ;
} ) ;
//Act + Assert
expect ( async ( ) = > {
await cacheUtils . getCacheDirectoryPath ( validPackageManager ) ;
} ) . rejects . toThrow ( ) ;
} ) ;
} ) ;
describe ( 'isCacheFeatureAvailable' , ( ) = > {
//Arrange
let isFeatureAvailableSpy = jest . spyOn ( cache , 'isFeatureAvailable' ) ;
let warningSpy = jest . spyOn ( core , 'warning' ) ;
it ( 'should return true when cache feature is available' , ( ) = > {
//Arrange
isFeatureAvailableSpy . mockImplementation ( ( ) = > {
return true ;
} ) ;
let functionResult ;
//Act
functionResult = cacheUtils . isCacheFeatureAvailable ( ) ;
//Assert
expect ( functionResult ) . toBeTruthy ( ) ;
} ) ;
it ( 'should warn when cache feature is unavailable and GHES is not used ' , ( ) = > {
//Arrange
isFeatureAvailableSpy . mockImplementation ( ( ) = > {
return false ;
} ) ;
process . env [ 'GITHUB_SERVER_URL' ] = 'https://github.com' ;
let warningMessage =
'The runner was not able to contact the cache service. Caching will be skipped' ;
//Act
cacheUtils . isCacheFeatureAvailable ( ) ;
//Assert
expect ( warningSpy ) . toHaveBeenCalledWith ( warningMessage ) ;
} ) ;
it ( 'should return false when cache feature is unavailable' , ( ) = > {
//Arrange
isFeatureAvailableSpy . mockImplementation ( ( ) = > {
return false ;
} ) ;
process . env [ 'GITHUB_SERVER_URL' ] = 'https://github.com' ;
let functionResult ;
//Act
functionResult = cacheUtils . isCacheFeatureAvailable ( ) ;
//Assert
expect ( functionResult ) . toBeFalsy ( ) ;
} ) ;
2022-12-16 23:05:54 +09:00
it ( 'should warn when cache feature is unavailable and GHES is used' , ( ) = > {
2022-05-25 12:07:29 +02:00
//Arrange
isFeatureAvailableSpy . mockImplementation ( ( ) = > {
return false ;
} ) ;
process . env [ 'GITHUB_SERVER_URL' ] = 'https://nongithub.com' ;
2022-12-16 23:05:54 +09:00
let warningMessage =
2022-05-25 12:07:29 +02:00
'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.' ;
//Act + Assert
2022-12-16 23:05:54 +09:00
expect ( cacheUtils . isCacheFeatureAvailable ( ) ) . toBeFalsy ( ) ;
expect ( warningSpy ) . toHaveBeenCalledWith ( warningMessage ) ;
2022-05-25 12:07:29 +02:00
} ) ;
} ) ;
2023-02-01 13:10:38 +01:00
describe ( 'isCacheEnabled' , ( ) = > {
let inputs = { } as any ;
const inSpy = jest . spyOn ( core , 'getInput' ) ;
const getBooleanInputSpy = jest . spyOn ( core , 'getBooleanInput' ) ;
const readdirSyncSpy = ( jest . spyOn (
fs ,
'readdirSync'
) as unknown ) as MockInstance < string [ ] , any [ ] > ;
beforeAll ( async ( ) = > {
inSpy . mockImplementation ( name = > inputs [ name ] || '' ) ;
getBooleanInputSpy . mockImplementation ( ( name , options ) = > {
const trueValue = [ 'true' , 'True' , 'TRUE' ] ;
const falseValue = [ 'false' , 'False' , 'FALSE' ] ;
const val = core . getInput ( name , options ) ;
if ( trueValue . includes ( val ) ) return true ;
if ( falseValue . includes ( val ) ) return false ;
throw new TypeError (
` Input does not meet YAML 1.2 "Core Schema" specification: ${ name } \ n ` +
` Support boolean input list: \` true | True | TRUE | false | False | FALSE \` `
) ;
} ) ;
} ) ;
afterEach ( ( ) = > {
jest . clearAllMocks ( ) ;
inputs = { } ;
} ) ;
afterAll ( async ( ) = > {
jest . restoreAllMocks ( ) ;
} , 100000 ) ;
it ( 'should return false if `cache` input set to false' , async ( ) = > {
inputs = { cache : 'false' } ;
const cacheEnabled = await cacheUtils . isCacheEnabled ( ) ;
expect ( cacheEnabled ) . toBeFalsy ( ) ;
} ) ;
it ( 'should return false if `cache` input set to true' , async ( ) = > {
inputs = { cache : 'true' } ;
const cacheEnabled = await cacheUtils . isCacheEnabled ( ) ;
expect ( cacheEnabled ) . toBeTruthy ( ) ;
} ) ;
it ( 'should returns false if `cache` input unset and no dependencies file' , async ( ) = > {
inputs = { } ;
process . env [ 'GITHUB_WORKSPACE' ] = '/tmp' ;
const packageManager = getCurrentPackageManager ( ) ;
const packageManagerInfo = await getPackageManagerInfo ( packageManager ) ;
readdirSyncSpy . mockImplementation ( ( ) = > [
packageManagerInfo . dependencyFilePattern
] ) ;
await expect ( cacheUtils . isCacheEnabled ( ) ) . resolves . toBeTruthy ( ) ;
} ) ;
} ) ;