Files
setup-node/__tests__/main.test.ts
v-mahabaleshwarsandmahabaleshwars 680d1e489b
e2e-cache / Test npm (Node 22, ubuntu-latest) (push) Failing after 32s
e2e-cache / Test npm (Node 24, ubuntu-latest) (push) Failing after 17m5s
e2e-cache / Test npm (Node 26, ubuntu-latest) (push) Successful in 10m9s
e2e-cache / Test pnpm (Node 22, ubuntu-latest) (push) Failing after 5m40s
e2e-cache / Test pnpm (Node 24, ubuntu-latest) (push) Failing after 5m34s
e2e-cache / Test pnpm (Node 26, ubuntu-latest) (push) Failing after 6m1s
e2e-cache / Test yarn 1 (Node 22, ubuntu-latest) (push) Failing after 11s
e2e-cache / Test yarn 1 (Node 24, ubuntu-latest) (push) Failing after 7s
e2e-cache / Test yarn 1 (Node 26, ubuntu-latest) (push) Failing after 7s
e2e-cache / Test yarn 3 (Node 22, ubuntu-latest) (push) Failing after 6s
e2e-cache / Test yarn 3 (Node 24, ubuntu-latest) (push) Failing after 7s
e2e-cache / Test yarn 3 (Node 26, ubuntu-latest) (push) Failing after 7s
e2e-cache / Test yarn subprojects (22) (push) Failing after 7s
e2e-cache / Test yarn subprojects (24) (push) Failing after 8s
e2e-cache / Test yarn subprojects (26) (push) Failing after 7s
e2e-cache / Test yarn subprojects all locally managed (22) (push) Failing after 7s
e2e-cache / Test yarn subprojects all locally managed (24) (push) Failing after 7s
e2e-cache / Test yarn subprojects all locally managed (26) (push) Failing after 7s
e2e-cache / Test yarn subprojects some locally managed (22) (push) Failing after 6s
e2e-cache / Test yarn subprojects some locally managed (24) (push) Failing after 7s
e2e-cache / Test yarn subprojects some locally managed (26) (push) Failing after 7s
e2e-cache / Test yarn subprojects managed by git (22) (push) Failing after 7s
e2e-cache / Test yarn subprojects managed by git (24) (push) Failing after 8s
e2e-cache / Test yarn subprojects managed by git (26) (push) Failing after 7s
e2e-cache / Test auto cache with top-level packageManager (22, ubuntu-latest) (push) Successful in 9m32s
e2e-cache / Test auto cache with top-level packageManager (24, ubuntu-latest) (push) Successful in 9m38s
e2e-cache / Test auto cache with top-level packageManager (26, ubuntu-latest) (push) Successful in 9m37s
e2e-cache / Test auto cache with devEngines.packageManager (22, ubuntu-latest) (push) Successful in 9m41s
e2e-cache / Test auto cache with devEngines.packageManager (24, ubuntu-latest) (push) Successful in 9m38s
e2e-cache / Test auto cache with devEngines.packageManager (26, ubuntu-latest) (push) Successful in 9m39s
proxy / test-proxy (push) Failing after 1s
proxy / test-bypass-proxy (push) Failing after 40s
versions / local-cache (22, ubuntu-latest) (push) Successful in 21s
versions / local-cache (24, ubuntu-latest) (push) Successful in 17s
versions / local-cache (26, ubuntu-latest) (push) Successful in 16s
versions / lts-syntax (lts/*, ubuntu-latest) (push) Failing after 20s
versions / lts-syntax (lts/-1, ubuntu-latest) (push) Failing after 19s
versions / v8-canary-syntax (26-v8-canary, ubuntu-latest) (push) Successful in 20s
versions / v8-canary-syntax (26.0.0-v8-canary, ubuntu-latest) (push) Successful in 16s
versions / v8-canary-syntax (26.0.0-v8-canary20251016054584e5cf, ubuntu-latest) (push) Successful in 35s
versions / nightly-syntax (24.0.0-nightly, ubuntu-latest) (push) Successful in 38s
versions / nightly-syntax (25-nightly, ubuntu-latest) (push) Failing after 30s
versions / nightly-syntax (26-nightly, ubuntu-latest) (push) Failing after 30s
versions / rc-syntax (22.14.0-rc.1, ubuntu-latest) (push) Failing after 30s
versions / rc-syntax (24.0.0-rc.4, ubuntu-latest) (push) Failing after 31s
versions / rc-syntax (26.0.0-rc.1, ubuntu-latest) (push) Failing after 1m35s
versions / manifest (22.0.0, ubuntu-latest) (push) Failing after 31s
versions / manifest (24.9.0, ubuntu-latest) (push) Failing after 31s
versions / manifest (26.5.0, ubuntu-latest) (push) Failing after 31s
versions / check-latest (22, ubuntu-latest) (push) Successful in 42s
versions / check-latest (24, ubuntu-latest) (push) Successful in 26s
versions / check-latest (26, ubuntu-latest) (push) Successful in 26s
versions / version-file (.nvmrc, ubuntu-latest) (push) Successful in 16s
versions / version-file (.tool-versions, ubuntu-latest) (push) Successful in 16s
versions / version-file (.tool-versions-node, ubuntu-latest) (push) Successful in 17s
versions / version-file (mise.toml, ubuntu-latest) (push) Successful in 16s
versions / version-file (package.json, ubuntu-latest) (push) Successful in 17s
versions / version-file-dev-engines (ubuntu-latest) (push) Successful in 16s
versions / version-file-volta (ubuntu-latest) (push) Successful in 16s
versions / version-file-volta-extends (ubuntu-latest) (push) Successful in 16s
versions / node-dist (21, ubuntu-latest) (push) Successful in 16s
versions / node-dist (23, ubuntu-latest) (push) Successful in 17s
versions / old-versions (ubuntu-latest) (push) Successful in 7s
versions / node-latest-aliases (current, ubuntu-latest) (push) Successful in 18s
versions / node-latest-aliases (latest, ubuntu-latest) (push) Successful in 19s
versions / node-latest-aliases (node, ubuntu-latest) (push) Successful in 19s
e2e-cache / Test npm (Node 22, macos-15-intel) (push) Canceled after 0s
e2e-cache / Test npm (Node 22, macos-latest) (push) Canceled after 0s
e2e-cache / Test npm (Node 22, windows-latest) (push) Canceled after 0s
e2e-cache / Test npm (Node 24, macos-15-intel) (push) Canceled after 0s
e2e-cache / Test npm (Node 24, macos-latest) (push) Canceled after 0s
e2e-cache / Test npm (Node 24, windows-latest) (push) Canceled after 0s
e2e-cache / Test npm (Node 26, macos-15-intel) (push) Canceled after 0s
e2e-cache / Test npm (Node 26, macos-latest) (push) Canceled after 0s
e2e-cache / Test npm (Node 26, windows-latest) (push) Canceled after 0s
e2e-cache / Test pnpm (Node 22, macos-15-intel) (push) Canceled after 0s
e2e-cache / Test pnpm (Node 22, macos-latest) (push) Canceled after 0s
e2e-cache / Test pnpm (Node 22, windows-latest) (push) Canceled after 0s
e2e-cache / Test pnpm (Node 24, macos-15-intel) (push) Canceled after 0s
e2e-cache / Test pnpm (Node 24, macos-latest) (push) Canceled after 0s
e2e-cache / Test pnpm (Node 24, windows-latest) (push) Canceled after 0s
e2e-cache / Test pnpm (Node 26, macos-15-intel) (push) Canceled after 0s
e2e-cache / Test pnpm (Node 26, macos-latest) (push) Canceled after 0s
e2e-cache / Test pnpm (Node 26, windows-latest) (push) Canceled after 0s
e2e-cache / Test yarn 1 (Node 22, macos-15-intel) (push) Canceled after 0s
e2e-cache / Test yarn 1 (Node 22, macos-latest) (push) Canceled after 0s
e2e-cache / Test yarn 1 (Node 22, windows-latest) (push) Canceled after 0s
e2e-cache / Test yarn 1 (Node 24, macos-15-intel) (push) Canceled after 0s
e2e-cache / Test yarn 1 (Node 24, macos-latest) (push) Canceled after 0s
e2e-cache / Test yarn 1 (Node 24, windows-latest) (push) Canceled after 0s
e2e-cache / Test yarn 1 (Node 26, macos-15-intel) (push) Canceled after 0s
e2e-cache / Test yarn 1 (Node 26, macos-latest) (push) Canceled after 0s
e2e-cache / Test yarn 1 (Node 26, windows-latest) (push) Canceled after 0s
e2e-cache / Test yarn 3 (Node 22, macos-15-intel) (push) Canceled after 0s
e2e-cache / Test yarn 3 (Node 22, macos-latest) (push) Canceled after 0s
e2e-cache / Test yarn 3 (Node 22, windows-latest) (push) Canceled after 0s
e2e-cache / Test yarn 3 (Node 24, macos-15-intel) (push) Canceled after 0s
e2e-cache / Test yarn 3 (Node 24, macos-latest) (push) Canceled after 0s
e2e-cache / Test yarn 3 (Node 24, windows-latest) (push) Canceled after 0s
e2e-cache / Test yarn 3 (Node 26, macos-15-intel) (push) Canceled after 0s
e2e-cache / Test yarn 3 (Node 26, macos-latest) (push) Canceled after 0s
e2e-cache / Test yarn 3 (Node 26, windows-latest) (push) Canceled after 0s
e2e-cache / Test auto cache with top-level packageManager (22, macos-15-intel) (push) Canceled after 0s
e2e-cache / Test auto cache with top-level packageManager (22, macos-latest) (push) Canceled after 0s
e2e-cache / Test auto cache with top-level packageManager (22, windows-latest) (push) Canceled after 0s
e2e-cache / Test auto cache with top-level packageManager (24, macos-15-intel) (push) Canceled after 0s
e2e-cache / Test auto cache with top-level packageManager (24, macos-latest) (push) Canceled after 0s
e2e-cache / Test auto cache with top-level packageManager (24, windows-latest) (push) Canceled after 0s
e2e-cache / Test auto cache with top-level packageManager (26, macos-15-intel) (push) Canceled after 0s
e2e-cache / Test auto cache with top-level packageManager (26, macos-latest) (push) Canceled after 0s
e2e-cache / Test auto cache with top-level packageManager (26, windows-latest) (push) Canceled after 0s
e2e-cache / Test auto cache with devEngines.packageManager (22, macos-15-intel) (push) Canceled after 0s
e2e-cache / Test auto cache with devEngines.packageManager (22, macos-latest) (push) Canceled after 0s
e2e-cache / Test auto cache with devEngines.packageManager (22, windows-latest) (push) Canceled after 0s
e2e-cache / Test auto cache with devEngines.packageManager (24, macos-15-intel) (push) Canceled after 0s
e2e-cache / Test auto cache with devEngines.packageManager (24, macos-latest) (push) Canceled after 0s
e2e-cache / Test auto cache with devEngines.packageManager (24, windows-latest) (push) Canceled after 0s
e2e-cache / Test auto cache with devEngines.packageManager (26, macos-15-intel) (push) Canceled after 0s
e2e-cache / Test auto cache with devEngines.packageManager (26, macos-latest) (push) Canceled after 0s
e2e-cache / Test auto cache with devEngines.packageManager (26, windows-latest) (push) Canceled after 0s
versions / local-cache (22, macos-15-intel) (push) Canceled after 0s
versions / local-cache (22, macos-latest) (push) Canceled after 0s
versions / local-cache (22, windows-latest) (push) Canceled after 0s
versions / local-cache (24, macos-15-intel) (push) Canceled after 0s
versions / local-cache (24, macos-latest) (push) Canceled after 0s
versions / local-cache (24, windows-latest) (push) Canceled after 0s
versions / local-cache (26, macos-15-intel) (push) Canceled after 0s
versions / local-cache (26, macos-latest) (push) Canceled after 0s
versions / local-cache (26, windows-latest) (push) Canceled after 0s
versions / lts-syntax (lts/*, macos-15-intel) (push) Canceled after 0s
versions / lts-syntax (lts/*, windows-latest) (push) Canceled after 0s
versions / lts-syntax (lts/-1, macos-15-intel) (push) Canceled after 0s
versions / lts-syntax (lts/-1, windows-latest) (push) Canceled after 0s
versions / v8-canary-syntax (26-v8-canary, macos-15-intel) (push) Canceled after 0s
versions / v8-canary-syntax (26-v8-canary, macos-latest) (push) Canceled after 0s
versions / v8-canary-syntax (26-v8-canary, windows-latest) (push) Canceled after 0s
versions / v8-canary-syntax (26.0.0-v8-canary, macos-15-intel) (push) Canceled after 0s
versions / v8-canary-syntax (26.0.0-v8-canary, macos-latest) (push) Canceled after 0s
versions / v8-canary-syntax (26.0.0-v8-canary, windows-latest) (push) Canceled after 0s
versions / v8-canary-syntax (26.0.0-v8-canary20251016054584e5cf, macos-15-intel) (push) Canceled after 0s
versions / v8-canary-syntax (26.0.0-v8-canary20251016054584e5cf, macos-latest) (push) Canceled after 0s
versions / v8-canary-syntax (26.0.0-v8-canary20251016054584e5cf, windows-latest) (push) Canceled after 0s
versions / nightly-syntax (24.0.0-nightly, macos-15-intel) (push) Canceled after 0s
versions / nightly-syntax (24.0.0-nightly, macos-latest) (push) Canceled after 0s
versions / nightly-syntax (24.0.0-nightly, windows-latest) (push) Canceled after 0s
versions / nightly-syntax (25-nightly, macos-15-intel) (push) Canceled after 0s
versions / nightly-syntax (25-nightly, macos-latest) (push) Canceled after 0s
versions / nightly-syntax (25-nightly, windows-latest) (push) Canceled after 0s
versions / nightly-syntax (26-nightly, macos-15-intel) (push) Canceled after 0s
versions / nightly-syntax (26-nightly, macos-latest) (push) Canceled after 0s
versions / nightly-syntax (26-nightly, windows-latest) (push) Canceled after 0s
versions / rc-syntax (22.14.0-rc.1, macos-15-intel) (push) Canceled after 0s
versions / rc-syntax (22.14.0-rc.1, macos-latest) (push) Canceled after 0s
versions / rc-syntax (22.14.0-rc.1, windows-latest) (push) Canceled after 0s
versions / rc-syntax (24.0.0-rc.4, macos-15-intel) (push) Canceled after 0s
versions / rc-syntax (24.0.0-rc.4, macos-latest) (push) Canceled after 0s
versions / rc-syntax (24.0.0-rc.4, windows-latest) (push) Canceled after 0s
versions / rc-syntax (26.0.0-rc.1, macos-15-intel) (push) Canceled after 0s
versions / rc-syntax (26.0.0-rc.1, macos-latest) (push) Canceled after 0s
versions / rc-syntax (26.0.0-rc.1, windows-latest) (push) Canceled after 0s
versions / manifest (22.0.0, macos-15-intel) (push) Canceled after 0s
versions / manifest (22.0.0, macos-latest) (push) Canceled after 0s
versions / manifest (22.0.0, windows-latest) (push) Canceled after 0s
versions / manifest (24.9.0, macos-15-intel) (push) Canceled after 0s
versions / manifest (24.9.0, macos-latest) (push) Canceled after 0s
versions / manifest (24.9.0, windows-latest) (push) Canceled after 0s
versions / manifest (26.5.0, macos-15-intel) (push) Canceled after 0s
versions / manifest (26.5.0, macos-latest) (push) Canceled after 0s
versions / manifest (26.5.0, windows-latest) (push) Canceled after 0s
versions / check-latest (22, macos-15-intel) (push) Canceled after 0s
versions / check-latest (22, macos-latest) (push) Canceled after 0s
versions / check-latest (22, windows-latest) (push) Canceled after 0s
versions / check-latest (24, macos-15-intel) (push) Canceled after 0s
versions / check-latest (24, macos-latest) (push) Canceled after 0s
versions / check-latest (24, windows-latest) (push) Canceled after 0s
versions / check-latest (26, macos-15-intel) (push) Canceled after 0s
versions / check-latest (26, macos-latest) (push) Canceled after 0s
versions / check-latest (26, windows-latest) (push) Canceled after 0s
versions / version-file (.nvmrc, macos-15-intel) (push) Canceled after 0s
versions / version-file (.nvmrc, macos-latest) (push) Canceled after 0s
versions / version-file (.nvmrc, windows-latest) (push) Canceled after 0s
versions / version-file (.tool-versions, macos-15-intel) (push) Canceled after 0s
versions / version-file (.tool-versions, macos-latest) (push) Canceled after 0s
versions / version-file (.tool-versions, windows-latest) (push) Canceled after 0s
versions / version-file (.tool-versions-node, macos-15-intel) (push) Canceled after 0s
versions / version-file (.tool-versions-node, macos-latest) (push) Canceled after 0s
versions / version-file (.tool-versions-node, windows-latest) (push) Canceled after 0s
versions / version-file (mise.toml, macos-15-intel) (push) Canceled after 0s
versions / version-file (mise.toml, macos-latest) (push) Canceled after 0s
versions / version-file (mise.toml, windows-latest) (push) Canceled after 0s
versions / version-file (package.json, macos-15-intel) (push) Canceled after 0s
versions / version-file (package.json, macos-latest) (push) Canceled after 0s
versions / version-file (package.json, windows-latest) (push) Canceled after 0s
versions / version-file-dev-engines (macos-latest) (push) Canceled after 0s
versions / version-file-dev-engines (windows-latest) (push) Canceled after 0s
versions / version-file-volta (macos-15-intel) (push) Canceled after 0s
versions / version-file-volta (macos-latest) (push) Canceled after 0s
versions / version-file-volta (windows-latest) (push) Canceled after 0s
versions / version-file-volta-extends (macos-15-intel) (push) Canceled after 0s
versions / version-file-volta-extends (macos-latest) (push) Canceled after 0s
versions / version-file-volta-extends (windows-latest) (push) Canceled after 0s
versions / node-dist (21, macos-15-intel) (push) Canceled after 0s
versions / node-dist (21, macos-latest) (push) Canceled after 0s
versions / node-dist (21, windows-latest) (push) Canceled after 0s
versions / node-dist (23, macos-15-intel) (push) Canceled after 0s
versions / node-dist (23, macos-latest) (push) Canceled after 0s
versions / node-dist (23, windows-latest) (push) Canceled after 0s
versions / old-versions (macos-15-intel) (push) Canceled after 0s
versions / old-versions (windows-latest) (push) Canceled after 0s
versions / arch (push) Canceled after 0s
versions / node-latest-aliases (current, macos-15-intel) (push) Canceled after 0s
versions / node-latest-aliases (current, macos-latest) (push) Canceled after 0s
versions / node-latest-aliases (current, windows-latest) (push) Canceled after 0s
versions / node-latest-aliases (latest, macos-15-intel) (push) Canceled after 0s
versions / node-latest-aliases (latest, macos-latest) (push) Canceled after 0s
versions / node-latest-aliases (latest, windows-latest) (push) Canceled after 0s
versions / node-latest-aliases (node, macos-15-intel) (push) Canceled after 0s
versions / node-latest-aliases (node, macos-latest) (push) Canceled after 0s
versions / node-latest-aliases (node, windows-latest) (push) Canceled after 0s
Support absolute paths in node-version-file (#1633)
* path.resolve for composite actions

* log and documentation update

---------

Co-authored-by: mahabaleshwars <147705296+mahabaleshwars@users.noreply.github.com>
2026-09-21 15:25:01 -05:00

562 lines
19 KiB
TypeScript

import {
afterAll,
afterEach,
beforeEach,
describe,
expect,
it,
jest
} from '@jest/globals';
import fs from 'fs';
import path from 'path';
import {fileURLToPath} from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
// Mock @actions modules before importing anything that depends on them
jest.unstable_mockModule('@actions/core', () => ({
info: jest.fn(),
warning: jest.fn(),
debug: jest.fn(),
error: jest.fn(),
notice: jest.fn(),
setFailed: jest.fn(),
setOutput: jest.fn(),
getInput: jest.fn(),
getBooleanInput: jest.fn(),
getMultilineInput: jest.fn(),
addPath: jest.fn(),
exportVariable: jest.fn(),
saveState: jest.fn(),
getState: jest.fn(),
setSecret: jest.fn(),
isDebug: jest.fn(() => false),
startGroup: jest.fn(),
endGroup: jest.fn(),
group: jest.fn((_name: string, fn: () => Promise<unknown>) => fn()),
toPlatformPath: jest.fn((p: string) => p),
toWin32Path: jest.fn((p: string) => p),
toPosixPath: jest.fn((p: string) => p)
}));
jest.unstable_mockModule('@actions/exec', () => ({
exec: jest.fn(),
getExecOutput: jest.fn()
}));
jest.unstable_mockModule('@actions/tool-cache', () => ({
find: jest.fn(),
findAllVersions: jest.fn(),
downloadTool: jest.fn(),
extractTar: jest.fn(),
extractZip: jest.fn(),
extractXar: jest.fn(),
extract7z: jest.fn(),
cacheDir: jest.fn(),
cacheFile: jest.fn(),
getManifestFromRepo: jest.fn(),
findFromManifest: jest.fn()
}));
jest.unstable_mockModule('@actions/cache', () => ({
saveCache: jest.fn(),
restoreCache: jest.fn(),
isFeatureAvailable: jest.fn()
}));
jest.unstable_mockModule('@actions/io', () => ({
which: jest.fn(),
mkdirP: jest.fn(),
rmRF: jest.fn(),
mv: jest.fn(),
cp: jest.fn()
}));
// Pre-import real util before mocking so we can spread it
const realUtil = await import('../src/util.js');
jest.unstable_mockModule('../src/util.js', () => ({
...realUtil,
getNodeVersionFromFile: jest.fn(realUtil.getNodeVersionFromFile)
}));
// Dynamic imports after mocking
const core = await import('@actions/core');
const exec = await import('@actions/exec');
const tc = await import('@actions/tool-cache');
const cache = await import('@actions/cache');
const io = await import('@actions/io');
const main = await import('../src/main.js');
const util = await import('../src/util.js');
const {default: OfficialBuilds} =
await import('../src/distributions/official_builds/official_builds.js');
import each from 'jest-each';
describe('main tests', () => {
let inputs = {} as any;
let os = {} as any;
let infoSpy: jest.Mock;
let warningSpy: jest.Mock;
let saveStateSpy: jest.Mock;
let inSpy: jest.Mock;
let setOutputSpy: jest.Mock;
let startGroupSpy: jest.Mock;
let endGroupSpy: jest.Mock;
let whichSpy: jest.Mock;
let existsSpy: jest.Mock;
let getExecOutputSpy: jest.Mock;
let getNodeVersionFromFileSpy: jest.Mock;
let cnSpy: jest.SpiedFunction<typeof process.stdout.write>;
let findSpy: jest.Mock;
let isCacheActionAvailable: jest.Mock;
let setupNodeJsSpy: jest.SpiedFunction<
typeof OfficialBuilds.prototype.setupNodeJs
>;
beforeEach(() => {
inputs = {};
// node
os = {};
console.log('::stop-commands::stoptoken');
process.env['GITHUB_WORKSPACE'] = path.join(__dirname, 'data');
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 = core.info as jest.Mock;
infoSpy.mockImplementation(() => {});
setOutputSpy = core.setOutput as jest.Mock;
setOutputSpy.mockImplementation(() => {});
warningSpy = core.warning as jest.Mock;
warningSpy.mockImplementation(() => {});
saveStateSpy = core.saveState as jest.Mock;
saveStateSpy.mockImplementation(() => {});
startGroupSpy = core.startGroup as jest.Mock;
startGroupSpy.mockImplementation(() => {});
endGroupSpy = core.endGroup as jest.Mock;
endGroupSpy.mockImplementation(() => {});
inSpy = core.getInput as jest.Mock;
inSpy.mockImplementation((name: any) => inputs[name]);
whichSpy = io.which as jest.Mock;
getExecOutputSpy = exec.getExecOutput as jest.Mock;
findSpy = tc.find as jest.Mock;
isCacheActionAvailable = cache.isFeatureAvailable as jest.Mock;
cnSpy = jest.spyOn(process.stdout, 'write');
cnSpy.mockImplementation(() => true);
setupNodeJsSpy = jest.spyOn(OfficialBuilds.prototype, 'setupNodeJs');
setupNodeJsSpy.mockImplementation(async () => {});
});
afterEach(() => {
jest.resetAllMocks();
jest.clearAllMocks();
//jest.restoreAllMocks();
});
afterAll(async () => {
console.log('::stoptoken::');
jest.restoreAllMocks();
}, 100000);
describe('getNodeVersionFromFile', () => {
beforeEach(() => {
(util.getNodeVersionFromFile as jest.Mock).mockImplementation(
realUtil.getNodeVersionFromFile as any
);
});
afterEach(() => {
jest.restoreAllMocks();
});
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'}
${'{}'} | ${null}
${'{"volta": {"node": ">=14.0.0 <=17.0.0"}}'} | ${'>=14.0.0 <=17.0.0'}
${'{"volta": {"extends": "./package.json"}}'} | ${'18.0.0'}
${'{"engines": {"node": "17.0.0"}}'} | ${'17.0.0'}
${'{"devEngines": {"runtime": {"name": "node", "version": "22.0.0"}}}'} | ${'22.0.0'}
${'{"devEngines": {"runtime": [{"name": "bun"}, {"name": "node", "version": "22.0.0"}]}}'} | ${'22.0.0'}
${'[tools]\ngo="latest"\nnode = "24.10"'} | ${'24.10'}
${'[tools]\nnode = "22.12"'} | ${'22.12'}
${'[tools]\ngo="latest"\nnode = "24.10"'} | ${'24.10'}
${'[tools]\nnode = { version = "22.20" }'} | ${'22.20'}
${'[tools]\nnode = { postinstall = "corepack enable" }'} | ${null}
`.it('parses "$contents"', ({contents, expected}: any) => {
const existsSpy = jest.spyOn(fs, 'existsSync');
existsSpy.mockImplementation(() => true);
const readFileSpy = jest.spyOn(fs, 'readFileSync');
readFileSpy.mockImplementation((filePath: any) => {
if (
typeof filePath === 'string' &&
path.basename(filePath) === 'package.json'
) {
// Special case for volta.extends
return '{"volta": {"node": "18.0.0"}}';
}
return contents;
});
expect(util.getNodeVersionFromFile('file')).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: any) => {
(
getExecOutputSpy as jest.Mock<typeof exec.getExecOutput>
).mockImplementation(async (command: string) => {
if (Reflect.has(obj, command) && !obj[command]) {
return {
stdout: '',
stderr: `${command} does not exist`,
exitCode: 1
};
}
return {stdout: obj[command], stderr: '', exitCode: 0};
});
whichSpy.mockImplementation((cmd: any) => {
return `some/${cmd}/path`;
});
await util.printEnvDetailsAndSetOutput();
expect(setOutputSpy).toHaveBeenCalledWith('node-version', obj['node']);
Object.getOwnPropertyNames(obj).forEach((name: any) => {
if (!obj[name]) {
expect(infoSpy).toHaveBeenCalledWith(
`[warning]${name} does not exist`
);
}
expect(infoSpy).toHaveBeenCalledWith(`${name}: ${obj[name]}`);
});
});
});
describe('node-version-file flag', () => {
beforeEach(() => {
delete inputs['node-version'];
inputs['node-version-file'] = '.nvmrc';
getNodeVersionFromFileSpy = util.getNodeVersionFromFile as jest.Mock;
getNodeVersionFromFileSpy.mockImplementation(
realUtil.getNodeVersionFromFile as any
);
});
afterEach(() => {
getNodeVersionFromFileSpy.mockImplementation(
realUtil.getNodeVersionFromFile as any
);
});
it('does not read node-version-file if node-version is provided', async () => {
// Arrange
inputs['node-version'] = '12';
// Act
await main.run();
// Assert
expect(inputs['node-version']).toBeDefined();
expect(inputs['node-version-file']).toBeDefined();
expect(getNodeVersionFromFileSpy).not.toHaveBeenCalled();
expect(warningSpy).toHaveBeenCalledWith(
'Both node-version and node-version-file inputs are specified, only node-version will be used'
);
});
it('does not read node-version-file if node-version-file is not provided', async () => {
// Arrange
delete inputs['node-version-file'];
// Act
await main.run();
// Assert
expect(getNodeVersionFromFileSpy).not.toHaveBeenCalled();
});
it('reads node-version-file', async () => {
// Arrange
const expectedVersionSpec = '14';
getNodeVersionFromFileSpy.mockImplementation(() => expectedVersionSpec);
// Act
await main.run();
// Assert
expect(getNodeVersionFromFileSpy).toHaveBeenCalled();
// A relative input is still resolved against the workspace.
expect(getNodeVersionFromFileSpy).toHaveBeenCalledWith(
path.join(process.env['GITHUB_WORKSPACE']!, '.nvmrc')
);
expect(infoSpy).toHaveBeenCalledWith(
`Resolved ${inputs['node-version-file']} as ${expectedVersionSpec}`
);
}, 10000);
it('reads node-version-file given as an absolute path outside the workspace', async () => {
// Arrange: a composite action passes `${{ github.action_path }}/.nvmrc`,
// which is absolute and may sit outside GITHUB_WORKSPACE.
// The workspace deliberately points at a different existing directory,
// so the absolute version file lies outside it.
const workspace = path.join(__dirname, 'mock');
process.env['GITHUB_WORKSPACE'] = workspace;
const versionFilePath = path.join(__dirname, 'data', '.nvmrc');
// Guard the premise: the version file lives outside the workspace.
expect(path.relative(workspace, versionFilePath).startsWith('..')).toBe(
true
);
inputs['node-version-file'] = versionFilePath;
// Act
await main.run();
// Assert: the path is used as provided and the real file is read.
// The expected `24` comes from `__tests__/data/.nvmrc` (`v24`).
expect(getNodeVersionFromFileSpy).toHaveBeenCalledWith(versionFilePath);
expect(infoSpy).toHaveBeenCalledWith(`Resolved ${versionFilePath} as 24`);
expect(core.setFailed as jest.Mock).not.toHaveBeenCalled();
}, 10000);
it('should throw an error if node-version-file is not accessible', async () => {
// Arrange
inputs['node-version-file'] = 'non-existing-file';
const versionFilePath = path.join(
__dirname,
'data',
inputs['node-version-file']
);
// Act
await main.run();
// Assert
expect(getNodeVersionFromFileSpy).toHaveBeenCalled();
expect(core.setFailed as jest.Mock).toHaveBeenCalledWith(
`The specified node version file at: ${versionFilePath} does not exist`
);
});
});
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: any) => inputs[name]);
const toolPath = path.normalize('/cache/node/12.16.1/x64');
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: any) => inputs[name]);
const toolPath = path.normalize('/cache/node/12.16.1/x64');
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'
);
});
});
describe('cache feature tests', () => {
it('Should enable caching when packageManager is npm and cache input is not provided', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = '';
isCacheActionAvailable.mockImplementation(() => true);
inSpy.mockImplementation((name: any) => inputs[name]);
const readFileSpy = jest.spyOn(fs, 'readFileSync');
readFileSpy.mockImplementation(() =>
JSON.stringify({
packageManager: 'npm@10.8.2'
})
);
await main.run();
expect(saveStateSpy).toHaveBeenCalledWith(expect.anything(), 'npm');
});
it('Should enable caching when devEngines.packageManager.name is "npm" and cache input is not provided', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = '';
isCacheActionAvailable.mockImplementation(() => true);
inSpy.mockImplementation((name: any) => inputs[name]);
const readFileSpy = jest.spyOn(fs, 'readFileSync');
readFileSpy.mockImplementation(() =>
JSON.stringify({
devEngines: {
packageManager: {name: 'npm'}
}
})
);
await main.run();
expect(saveStateSpy).toHaveBeenCalledWith(expect.anything(), 'npm');
});
it('Should enable caching when devEngines.packageManager is array and one entry has name "npm"', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = '';
isCacheActionAvailable.mockImplementation(() => true);
inSpy.mockImplementation((name: any) => inputs[name]);
const readFileSpy = jest.spyOn(fs, 'readFileSync');
readFileSpy.mockImplementation(() =>
JSON.stringify({
devEngines: {
packageManager: [{name: 'pnpm'}, {name: 'npm'}]
}
})
);
await main.run();
expect(saveStateSpy).toHaveBeenCalledWith(expect.anything(), 'npm');
});
it('Should not enable caching if packageManager is "pnpm@8.0.0" and cache input is not provided', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = '';
inSpy.mockImplementation((name: any) => inputs[name]);
const readFileSpy = jest.spyOn(fs, 'readFileSync');
readFileSpy.mockImplementation(() =>
JSON.stringify({
packageManager: 'pnpm@8.0.0'
})
);
await main.run();
expect(saveStateSpy).not.toHaveBeenCalled();
});
it('Should not enable caching if devEngines.packageManager.name is "pnpm"', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = '';
inSpy.mockImplementation((name: any) => inputs[name]);
const readFileSpy = jest.spyOn(fs, 'readFileSync');
readFileSpy.mockImplementation(() =>
JSON.stringify({
devEngines: {
packageManager: {name: 'pnpm'}
}
})
);
await main.run();
expect(saveStateSpy).not.toHaveBeenCalled();
});
it('Should not enable caching if devEngines.packageManager is array without "npm"', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = '';
inSpy.mockImplementation((name: any) => inputs[name]);
const readFileSpy = jest.spyOn(fs, 'readFileSync');
readFileSpy.mockImplementation(() =>
JSON.stringify({
devEngines: {
packageManager: [{name: 'pnpm'}, {name: 'yarn'}]
}
})
);
await main.run();
expect(saveStateSpy).not.toHaveBeenCalled();
});
it('Should not enable caching if packageManager field is missing in package.json and cache input is not provided', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = '';
inSpy.mockImplementation((name: any) => inputs[name]);
const readFileSpy = jest.spyOn(fs, 'readFileSync');
readFileSpy.mockImplementation(() =>
JSON.stringify({
// packageManager field is not present
})
);
await main.run();
expect(saveStateSpy).not.toHaveBeenCalled();
});
it('Should skip caching when package-manager-cache is false', async () => {
inputs['package-manager-cache'] = 'false';
inputs['cache'] = '';
inSpy.mockImplementation((name: any) => inputs[name]);
await main.run();
expect(saveStateSpy).not.toHaveBeenCalled();
});
it('Should enable caching with cache input explicitly provided', async () => {
inputs['package-manager-cache'] = 'true';
inputs['cache'] = 'npm';
inSpy.mockImplementation((name: any) => inputs[name]);
isCacheActionAvailable.mockImplementation(() => true);
await main.run();
expect(saveStateSpy).toHaveBeenCalledWith(expect.anything(), 'npm');
});
});
});