@ -1,17 +1,98 @@
import * as core from '@actions/core' ;
import {
import * as io from '@actions/io' ;
jest ,
import * as tc from '@actions/tool-cache' ;
describe ,
it ,
expect ,
beforeAll ,
beforeEach ,
afterEach ,
afterAll
} from '@jest/globals' ;
import fs from 'fs' ;
import fs from 'fs' ;
import cp from 'child_process' ;
import cp from 'child_process' ;
import osm , { type } from 'os' ;
import path from 'path' ;
import goJsonData from './data/golang-dl.json' with { type : 'json' } ;
import * as main from '../src/main' ;
import matchers from '../matchers.json' with { type : 'json' } ;
import * as im from '../src/installer' ;
import goTestManifest from './data/versions-manifest.json' with { type : 'json' } ;
import * as httpm from '@actions/http-client' ;
import type { IGoVersion } from '../src/installer.js' ;
import goJsonData from './data/golang-dl.json' ;
import type { IToolRelease } from '@actions/tool-cache' ;
import matchers from '../matchers.json' ;
import goTestManifest from './data/versions-manifest.json' ;
const httpClientGetJson = jest . fn ( ) ;
const realCore = await import ( '@actions/core' ) ;
jest . unstable_mockModule ( '@actions/core' , ( ) = > ( {
. . . realCore ,
getInput : jest.fn ( ) ,
getBooleanInput : jest.fn ( ) ,
info : jest.fn ( ) ,
debug : jest.fn ( ) ,
exportVariable : jest.fn ( )
} ) ) ;
const realOs = ( await import ( 'os' ) ) . default ;
const osPlatformMock = jest . fn ( ) ;
const osArchMock = jest . fn ( ) ;
const osExports = {
. . . realOs ,
platform : osPlatformMock ,
arch : osArchMock
} ;
jest . unstable_mockModule ( 'os' , ( ) = > ( { . . . osExports , default : osExports } ) ) ;
const realPath = ( await import ( 'path' ) ) . default ;
const pathJoinMock = jest . fn ( ) ;
const pathExports = {
. . . realPath ,
join : pathJoinMock
} ;
jest . unstable_mockModule ( 'path' , ( ) = > ( {
. . . pathExports ,
default : pathExports
} ) ) ;
jest . unstable_mockModule ( '@actions/io' , ( ) = > ( {
which : jest.fn ( ) ,
mkdirP : jest.fn ( ) ,
rmRF : jest.fn ( ) ,
mv : jest.fn ( ) ,
cp : jest.fn ( )
} ) ) ;
const realTc = await import ( '@actions/tool-cache' ) ;
jest . unstable_mockModule ( '@actions/tool-cache' , ( ) = > ( {
. . . realTc ,
find : jest.fn ( ) ,
downloadTool : jest.fn ( ) ,
extractTar : jest.fn ( ) ,
extractZip : jest.fn ( ) ,
cacheDir : jest.fn ( ) ,
getManifestFromRepo : jest.fn ( )
} ) ) ;
const realHttp = await import ( '@actions/http-client' ) ;
jest . unstable_mockModule ( '@actions/http-client' , ( ) = > ( {
. . . realHttp ,
HttpClient : jest.fn ( ) . mockImplementation ( ( ) = > ( {
getJson : httpClientGetJson
} ) )
} ) ) ;
jest . unstable_mockModule ( '../src/go-version-fetch.js' , ( ) = > ( {
getVersionsDist : jest.fn ( )
} ) ) ;
const core = await import ( '@actions/core' ) ;
const io = await import ( '@actions/io' ) ;
const tc = await import ( '@actions/tool-cache' ) ;
const vf = await import ( '../src/go-version-fetch.js' ) ;
const main = await import ( '../src/main.js' ) ;
const im = await import ( '../src/installer.js' ) ;
const osm = ( await import ( 'os' ) ) . default ;
const path = ( await import ( 'path' ) ) . default ;
const matcherPattern = matchers . problemMatcher [ 0 ] . pattern [ 0 ] ;
const matcherPattern = matchers . problemMatcher [ 0 ] . pattern [ 0 ] ;
const matcherRegExp = new RegExp ( matcherPattern . regexp ) ;
const matcherRegExp = new RegExp ( matcherPattern . regexp ) ;
const win32Join = path . win32 . join ;
const win32Join = path . win32 . join ;
@ -23,32 +104,31 @@ describe('setup-go', () => {
let inputs = { } as any ;
let inputs = { } as any ;
let os = { } as any ;
let os = { } as any ;
let inSpy : jest.SpyInstance ;
let inSpy : jest.Mock < typeof core.getInput > ;
let getBooleanInputSpy : jest.SpyInstance ;
let getBooleanInputSpy : jest.Mock < typeof core.getBooleanInput > ;
let exportVarSpy : jest.SpyInstance ;
let exportVarSpy : jest.Mock < typeof core.exportVariable > ;
let findSpy : jest.SpyInstance ;
let findSpy : jest.Mock ;
let cnSpy : jest.SpyInstance ;
let cnSpy : jest.SpiedFunction < typeof process.stdout.write > ;
let logSpy : jest.SpyInstance ;
let logSpy : jest.Mock ;
let getSpy : jest.SpyInstance ;
let getSpy : jest.Mock ;
let platSpy : jest.SpyInstance ;
let platSpy : jest.Mock ;
let archSpy : jest.SpyInstance ;
let archSpy : jest.Mock ;
let joinSpy : jest.SpyInstance ;
let joinSpy : jest.Mock < typeof path.join > ;
let dlSpy : jest.SpyInstance ;
let dlSpy : jest.Mock ;
let extractTarSpy : jest.SpyInstance ;
let extractTarSpy : jest.Mock ;
let extractZipSpy : jest.SpyInstance ;
let extractZipSpy : jest.Mock ;
let cacheSpy : jest.SpyInstance ;
let cacheSpy : jest.Mock ;
let dbgSpy : jest.SpyInstance ;
let dbgSpy : jest.Mock ;
let whichSpy : jest.SpyInstance ;
let whichSpy : jest.Mock ;
let existsSpy : jest.SpyInstance ;
let existsSpy : jest.SpiedFunction < typeof fs.existsSync > ;
let readFileSpy : jest.SpyInstance ;
let readFileSpy : jest.SpiedFunction < typeof fs.readFileSync > ;
let mkdirpSpy : jest.SpyInstance ;
let mkdirpSpy : jest.Mock ;
let mkdirSpy : jest.SpyInstance ;
let mkdirSpy : jest.SpiedFunction < typeof fs.mkdir > ;
let symlinkSpy : jest.SpyInstance ;
let symlinkSpy : jest.SpiedFunction < typeof fs.symlinkSync > ;
let execSpy : jest.SpyInstance ;
let execSpy : jest.SpiedFunction < typeof cp.execSync > ;
let execFileSpy : jest.SpyInstance ;
let execFileSpy : jest.SpiedFunction < typeof cp.execFileSync > ;
let getManifestSpy : jest.SpyInstance ;
let getManifestSpy : jest.Mock ;
let getAllVersionsSpy : jest.SpyInstance ;
let httpmGetJsonSpy : jest.Mock ;
let httpmGetJsonSpy : jest.SpyInstance ;
beforeAll ( async ( ) = > {
beforeAll ( async ( ) = > {
process . env [ 'GITHUB_ENV' ] = '' ; // Stub out Environment file functionality so we can verify it writes to standard out (toolkit is backwards compatible)
process . env [ 'GITHUB_ENV' ] = '' ; // Stub out Environment file functionality so we can verify it writes to standard out (toolkit is backwards compatible)
@ -59,17 +139,19 @@ describe('setup-go', () => {
// @actions/core
// @actions/core
inputs = { } ;
inputs = { } ;
inSpy = jest. spyOn ( core , 'getInput' ) ;
inSpy = core. getInput as jest . Mock < typeof core.getInput > ;
inSpy . mockImplementation ( name = > inputs [ name ] ) ;
inSpy . mockImplementation ( name = > inputs [ name ] ) ;
getBooleanInputSpy = jest . spyOn ( core , 'getBooleanInput' ) ;
getBooleanInputSpy = core . getBooleanInput as jest . Mock <
typeof core . getBooleanInput
> ;
getBooleanInputSpy . mockImplementation ( name = > inputs [ name ] ) ;
getBooleanInputSpy . mockImplementation ( name = > inputs [ name ] ) ;
exportVarSpy = jest . spyOn ( core , 'exportVariable' ) ;
exportVarSpy = core. exportVariable as jest . Mock < typeof core.exportVariable > ;
// node
// node
os = { } ;
os = { } ;
platSpy = jest. spyOn ( osm , 'platform' ) ;
platSpy = osm. platform as jest . Mock ;
platSpy . mockImplementation ( ( ) = > os [ 'platform' ] ) ;
platSpy . mockImplementation ( ( ) = > os [ 'platform' ] ) ;
archSpy = jest. spyOn ( osm , 'arch' ) ;
archSpy = osm. arch as jest . Mock ;
archSpy . mockImplementation ( ( ) = > os [ 'arch' ] ) ;
archSpy . mockImplementation ( ( ) = > os [ 'arch' ] ) ;
execSpy = jest . spyOn ( cp , 'execSync' ) ;
execSpy = jest . spyOn ( cp , 'execSync' ) ;
execFileSpy = jest . spyOn ( cp , 'execFileSync' ) ;
execFileSpy = jest . spyOn ( cp , 'execFileSync' ) ;
@ -78,7 +160,7 @@ describe('setup-go', () => {
} ) ;
} ) ;
// switch path join behaviour based on set os.platform
// switch path join behaviour based on set os.platform
joinSpy = jest. spyOn ( path , 'join' ) ;
joinSpy = path. join as jest . Mock < typeof path.join > ;
joinSpy . mockImplementation ( ( . . . paths : string [ ] ) : string = > {
joinSpy . mockImplementation ( ( . . . paths : string [ ] ) : string = > {
if ( os [ 'platform' ] == 'win32' ) {
if ( os [ 'platform' ] == 'win32' ) {
return win32Join ( . . . paths ) ;
return win32Join ( . . . paths ) ;
@ -88,23 +170,22 @@ describe('setup-go', () => {
} ) ;
} ) ;
// @actions/tool-cache
// @actions/tool-cache
findSpy = jest . spyOn ( tc , 'find' ) ;
findSpy = tc . find as jest . Mock ;
dlSpy = jest . spyOn ( tc , 'downloadTool' ) ;
dlSpy = tc . downloadTool as jest . Mock ;
extractTarSpy = jest . spyOn ( tc , 'extractTar' ) ;
extractTarSpy = tc . extractTar as jest . Mock ;
extractZipSpy = jest . spyOn ( tc , 'extractZip' ) ;
extractZipSpy = tc . extractZip as jest . Mock ;
cacheSpy = jest . spyOn ( tc , 'cacheDir' ) ;
cacheSpy = tc . cacheDir as jest . Mock ;
getSpy = jest . spyOn ( im , 'getVersionsDist' ) ;
getSpy = vf . getVersionsDist as jest . Mock ;
getManifestSpy = jest . spyOn ( tc , 'getManifestFromRepo' ) ;
getManifestSpy = tc . getManifestFromRepo as jest . Mock ;
getAllVersionsSpy = jest . spyOn ( im , 'getManifest' ) ;
// httm
// httm
httpmGetJsonSpy = jest. spyOn ( httpm . HttpClient . prototype , 'getJson' ) ;
httpmGetJsonSpy = httpClientGetJson ;
// io
// io
whichSpy = jest. spyOn ( io , 'which' ) ;
whichSpy = io. which as jest . Mock ;
existsSpy = jest . spyOn ( fs , 'existsSync' ) ;
existsSpy = jest . spyOn ( fs , 'existsSync' ) ;
readFileSpy = jest . spyOn ( fs , 'readFileSync' ) ;
readFileSpy = jest . spyOn ( fs , 'readFileSync' ) ;
mkdirpSpy = jest. spyOn ( io , 'mkdirP' ) ;
mkdirpSpy = io. mkdirP as jest . Mock ;
// fs
// fs
mkdirSpy = jest . spyOn ( fs , 'mkdir' ) ;
mkdirSpy = jest . spyOn ( fs , 'mkdir' ) ;
@ -112,25 +193,16 @@ describe('setup-go', () => {
symlinkSpy . mockImplementation ( ( ) = > { } ) ;
symlinkSpy . mockImplementation ( ( ) = > { } ) ;
// gets
// gets
getManifestSpy . mockImplementation ( ( ) = > < tc.IToolRelease [ ] > goTestManifest ) ;
getManifestSpy . mockImplementation ( ( ) = > goTestManifest as IToolRelease [ ] ) ;
// writes
// writes
cnSpy = jest . spyOn ( process . stdout , 'write' ) ;
cnSpy = jest . spyOn ( process . stdout , 'write' ) ;
logSpy = jest . spyOn ( core , 'info' ) ;
logSpy = core . info as jest . Mock ;
dbgSpy = jest . spyOn ( core , 'debug' ) ;
dbgSpy = core . debug as jest . Mock ;
getSpy . mockImplementation ( ( ) = > < im.IGoVersion [ ] | null > goJsonData ) ;
getSpy . mockImplementation ( ( ) = > goJsonData as IGoVersion [ ] | null ) ;
cnSpy . mockImplementation ( line = > {
cnSpy . mockImplementation ( ( ) = > true ) ;
// uncomment to debug
logSpy . mockImplementation ( ( ) = > { } ) ;
// process.stderr.write('write:' + line + '\n');
dbgSpy . mockImplementation ( ( ) = > { } ) ;
} ) ;
logSpy . mockImplementation ( line = > {
// uncomment to debug
//process.stderr.write('log:' + line + '\n');
} ) ;
dbgSpy . mockImplementation ( msg = > {
// uncomment to see debug output
// process.stderr.write(msg + '\n');
} ) ;
} ) ;
} ) ;
afterEach ( ( ) = > {
afterEach ( ( ) = > {
@ -138,6 +210,10 @@ describe('setup-go', () => {
delete process . env [ im . GOTOOLCHAIN_ENV_VAR ] ;
delete process . env [ im . GOTOOLCHAIN_ENV_VAR ] ;
delete process . env [ 'GO_DOWNLOAD_BASE_URL' ] ;
delete process . env [ 'GO_DOWNLOAD_BASE_URL' ] ;
// reset the exit code that core.setFailed sets on the error-path tests so
// that a passing run does not leak a non-zero process exit code
process . exitCode = 0 ;
//jest.resetAllMocks();
//jest.resetAllMocks();
jest . clearAllMocks ( ) ;
jest . clearAllMocks ( ) ;
//jest.restoreAllMocks();
//jest.restoreAllMocks();
@ -171,8 +247,10 @@ describe('setup-go', () => {
} ) ;
} ) ;
it ( 'should return manifest from raw URL if repo fetch fails' , async ( ) = > {
it ( 'should return manifest from raw URL if repo fetch fails' , async ( ) = > {
getManifestSpy . mockRejectedValue ( new Error ( 'Fetch failed' ) ) ;
( getManifestSpy as jest . Mock < any > ) . mockRejectedValue (
httpmGetJsonSpy . mockResolvedValue ( {
new Error ( 'Fetch failed' )
) ;
( httpmGetJsonSpy as jest . Mock < any > ) . mockResolvedValue ( {
result : goTestManifest
result : goTestManifest
} ) ;
} ) ;
const manifest = await im . getManifest ( undefined ) ;
const manifest = await im . getManifest ( undefined ) ;
@ -211,7 +289,7 @@ describe('setup-go', () => {
os . arch = 'x64' ;
os . arch = 'x64' ;
// spec: 1.13.0 => 1.13
// spec: 1.13.0 => 1.13
const match : im. IGoVersion | undefined = await im . findMatch ( '1.13.0' ) ;
const match : IGoVersion | undefined = await im . findMatch ( '1.13.0' ) ;
expect ( match ) . toBeDefined ( ) ;
expect ( match ) . toBeDefined ( ) ;
const version : string = match ? match . version : '' ;
const version : string = match ? match . version : '' ;
expect ( version ) . toBe ( 'go1.13' ) ;
expect ( version ) . toBe ( 'go1.13' ) ;
@ -224,7 +302,7 @@ describe('setup-go', () => {
os . arch = 'x64' ;
os . arch = 'x64' ;
// spec: 1.13 => 1.13.7 (latest)
// spec: 1.13 => 1.13.7 (latest)
const match : im. IGoVersion | undefined = await im . findMatch ( '1.13' ) ;
const match : IGoVersion | undefined = await im . findMatch ( '1.13' ) ;
expect ( match ) . toBeDefined ( ) ;
expect ( match ) . toBeDefined ( ) ;
const version : string = match ? match . version : '' ;
const version : string = match ? match . version : '' ;
expect ( version ) . toBe ( 'go1.13.7' ) ;
expect ( version ) . toBe ( 'go1.13.7' ) ;
@ -237,7 +315,7 @@ describe('setup-go', () => {
os . arch = 'x64' ;
os . arch = 'x64' ;
// spec: ^1.13.6 => 1.13.7
// spec: ^1.13.6 => 1.13.7
const match : im. IGoVersion | undefined = await im . findMatch ( '^1.13.6' ) ;
const match : IGoVersion | undefined = await im . findMatch ( '^1.13.6' ) ;
expect ( match ) . toBeDefined ( ) ;
expect ( match ) . toBeDefined ( ) ;
const version : string = match ? match . version : '' ;
const version : string = match ? match . version : '' ;
expect ( version ) . toBe ( 'go1.13.7' ) ;
expect ( version ) . toBe ( 'go1.13.7' ) ;
@ -250,7 +328,7 @@ describe('setup-go', () => {
os . arch = 'x32' ;
os . arch = 'x32' ;
// spec: 1 => 1.13.7 (latest)
// spec: 1 => 1.13.7 (latest)
const match : im. IGoVersion | undefined = await im . findMatch ( '1' ) ;
const match : IGoVersion | undefined = await im . findMatch ( '1' ) ;
expect ( match ) . toBeDefined ( ) ;
expect ( match ) . toBeDefined ( ) ;
const version : string = match ? match . version : '' ;
const version : string = match ? match . version : '' ;
expect ( version ) . toBe ( 'go1.13.7' ) ;
expect ( version ) . toBe ( 'go1.13.7' ) ;
@ -263,7 +341,7 @@ describe('setup-go', () => {
os . arch = 'x64' ;
os . arch = 'x64' ;
// spec: 1.14, stable=false => go1.14rc1
// spec: 1.14, stable=false => go1.14rc1
const match : im. IGoVersion | undefined = await im . findMatch ( '1.14.0-rc.1' ) ;
const match : IGoVersion | undefined = await im . findMatch ( '1.14.0-rc.1' ) ;
expect ( match ) . toBeDefined ( ) ;
expect ( match ) . toBeDefined ( ) ;
const version : string = match ? match . version : '' ;
const version : string = match ? match . version : '' ;
expect ( version ) . toBe ( 'go1.14rc1' ) ;
expect ( version ) . toBe ( 'go1.14rc1' ) ;
@ -817,10 +895,9 @@ describe('setup-go', () => {
getManifestSpy . mockImplementation ( ( ) = > {
getManifestSpy . mockImplementation ( ( ) = > {
throw new Error ( 'Unable to download manifest' ) ;
throw new Error ( 'Unable to download manifest' ) ;
} ) ;
} ) ;
httpmGetJsonSpy . mockRejectedValue (
( httpmGetJsonSpy as jest . Mock < any > ) . mockRejectedValue (
new Error ( 'Unable to download manifest from raw URL' )
new Error ( 'Unable to download manifest from raw URL' )
) ;
) ;
getAllVersionsSpy . mockImplementationOnce ( ( ) = > undefined ) ;
dlSpy . mockImplementation ( async ( ) = > '/some/temp/path' ) ;
dlSpy . mockImplementation ( async ( ) = > '/some/temp/path' ) ;
const toolPath = path . normalize ( '/cache/go/1.13.7/x64' ) ;
const toolPath = path . normalize ( '/cache/go/1.13.7/x64' ) ;