setup-dotnet/__tests__/installer.test.ts

493 lines
17 KiB
TypeScript
Raw Normal View History

import each from 'jest-each';
import semver from 'semver';
feat: Cache NuGet global-packages folder (#303) * feat: cache NuGet global-packages folder * fix: remove unused files * docs: fix incorrect action * ci: add e2e test for cache * docs: accept suggested changes on README * docs: add simple cache example * build: change main script path * fix: change relative path to install scripts * fix: change relative path to problem matcher * refactor: accept changes on cache-utils * fix: revert main script path changes * test: fix cache-utils unit test * test: fix cache-utils unit test * feat: add `cache-dependency-path` variables * build: change main script dist path * ci: add `cache-dependency-path` e2e test & missing lock file * fix: accept change suggestions * ci: copy NuGet lock file to root to pass "test-setup-with-cache" e2e test * docs: change README guide * fix: apply suggestions from code review Co-authored-by: Ivan <98037481+IvanZosimov@users.noreply.github.com> * test: fix some failed unit tests - fix `restoreCache()` test for 9703c8 - update installer script * build: rebuild dist * Update unit-tests - Additional unit test were added to setup-dotnet.test.ts * Update unit tests for unix systems * Format and lint unit tests * fix: avoid use '/' on `path.join` * fix: rebuild dist * fix: apply suggestions from code review Co-authored-by: Ivan <98037481+IvanZosimov@users.noreply.github.com> * build: add `DisableImplicitNuGetFallbackFolder` option also add guide on README * docs: highlight warnings and notes * docs: update note about handling NU1403 --------- Co-authored-by: Ivan <98037481+IvanZosimov@users.noreply.github.com> Co-authored-by: IvanZosimov <ivanzosimov@github.com>
2023-05-29 18:43:18 +08:00
import fs from 'fs';
import fspromises from 'fs/promises';
import * as exec from '@actions/exec';
import * as core from '@actions/core';
import * as io from '@actions/io';
import * as installer from '../src/installer';
import {IS_WINDOWS} from '../src/utils';
import {QualityOptions} from '../src/setup-dotnet';
describe('installer tests', () => {
const env = process.env;
beforeEach(() => {
jest.resetModules();
process.env = {...env};
});
describe('DotnetCoreInstaller tests', () => {
const getExecOutputSpy = jest.spyOn(exec, 'getExecOutput');
const warningSpy = jest.spyOn(core, 'warning');
const whichSpy = jest.spyOn(io, 'which');
const maxSatisfyingSpy = jest.spyOn(semver, 'maxSatisfying');
feat: Cache NuGet global-packages folder (#303) * feat: cache NuGet global-packages folder * fix: remove unused files * docs: fix incorrect action * ci: add e2e test for cache * docs: accept suggested changes on README * docs: add simple cache example * build: change main script path * fix: change relative path to install scripts * fix: change relative path to problem matcher * refactor: accept changes on cache-utils * fix: revert main script path changes * test: fix cache-utils unit test * test: fix cache-utils unit test * feat: add `cache-dependency-path` variables * build: change main script dist path * ci: add `cache-dependency-path` e2e test & missing lock file * fix: accept change suggestions * ci: copy NuGet lock file to root to pass "test-setup-with-cache" e2e test * docs: change README guide * fix: apply suggestions from code review Co-authored-by: Ivan <98037481+IvanZosimov@users.noreply.github.com> * test: fix some failed unit tests - fix `restoreCache()` test for 9703c8 - update installer script * build: rebuild dist * Update unit-tests - Additional unit test were added to setup-dotnet.test.ts * Update unit tests for unix systems * Format and lint unit tests * fix: avoid use '/' on `path.join` * fix: rebuild dist * fix: apply suggestions from code review Co-authored-by: Ivan <98037481+IvanZosimov@users.noreply.github.com> * build: add `DisableImplicitNuGetFallbackFolder` option also add guide on README * docs: highlight warnings and notes * docs: update note about handling NU1403 --------- Co-authored-by: Ivan <98037481+IvanZosimov@users.noreply.github.com> Co-authored-by: IvanZosimov <ivanzosimov@github.com>
2023-05-29 18:43:18 +08:00
const chmodSyncSpy = jest.spyOn(fs, 'chmodSync');
const readdirSpy = jest.spyOn(fspromises, 'readdir');
describe('installDotnet() tests', () => {
feat: Cache NuGet global-packages folder (#303) * feat: cache NuGet global-packages folder * fix: remove unused files * docs: fix incorrect action * ci: add e2e test for cache * docs: accept suggested changes on README * docs: add simple cache example * build: change main script path * fix: change relative path to install scripts * fix: change relative path to problem matcher * refactor: accept changes on cache-utils * fix: revert main script path changes * test: fix cache-utils unit test * test: fix cache-utils unit test * feat: add `cache-dependency-path` variables * build: change main script dist path * ci: add `cache-dependency-path` e2e test & missing lock file * fix: accept change suggestions * ci: copy NuGet lock file to root to pass "test-setup-with-cache" e2e test * docs: change README guide * fix: apply suggestions from code review Co-authored-by: Ivan <98037481+IvanZosimov@users.noreply.github.com> * test: fix some failed unit tests - fix `restoreCache()` test for 9703c8 - update installer script * build: rebuild dist * Update unit-tests - Additional unit test were added to setup-dotnet.test.ts * Update unit tests for unix systems * Format and lint unit tests * fix: avoid use '/' on `path.join` * fix: rebuild dist * fix: apply suggestions from code review Co-authored-by: Ivan <98037481+IvanZosimov@users.noreply.github.com> * build: add `DisableImplicitNuGetFallbackFolder` option also add guide on README * docs: highlight warnings and notes * docs: update note about handling NU1403 --------- Co-authored-by: Ivan <98037481+IvanZosimov@users.noreply.github.com> Co-authored-by: IvanZosimov <ivanzosimov@github.com>
2023-05-29 18:43:18 +08:00
beforeAll(() => {
whichSpy.mockImplementation(() => Promise.resolve('PathToShell'));
chmodSyncSpy.mockImplementation(() => {});
readdirSpy.mockImplementation(() => Promise.resolve([]));
});
afterAll(() => {
jest.resetAllMocks();
});
it('should throw the error in case of non-zero exit code of the installation script. The error message should contain logs.', async () => {
const inputVersion = '3.1.100';
const inputQuality = '' as QualityOptions;
const errorMessage = 'fictitious error message!';
feat: Cache NuGet global-packages folder (#303) * feat: cache NuGet global-packages folder * fix: remove unused files * docs: fix incorrect action * ci: add e2e test for cache * docs: accept suggested changes on README * docs: add simple cache example * build: change main script path * fix: change relative path to install scripts * fix: change relative path to problem matcher * refactor: accept changes on cache-utils * fix: revert main script path changes * test: fix cache-utils unit test * test: fix cache-utils unit test * feat: add `cache-dependency-path` variables * build: change main script dist path * ci: add `cache-dependency-path` e2e test & missing lock file * fix: accept change suggestions * ci: copy NuGet lock file to root to pass "test-setup-with-cache" e2e test * docs: change README guide * fix: apply suggestions from code review Co-authored-by: Ivan <98037481+IvanZosimov@users.noreply.github.com> * test: fix some failed unit tests - fix `restoreCache()` test for 9703c8 - update installer script * build: rebuild dist * Update unit-tests - Additional unit test were added to setup-dotnet.test.ts * Update unit tests for unix systems * Format and lint unit tests * fix: avoid use '/' on `path.join` * fix: rebuild dist * fix: apply suggestions from code review Co-authored-by: Ivan <98037481+IvanZosimov@users.noreply.github.com> * build: add `DisableImplicitNuGetFallbackFolder` option also add guide on README * docs: highlight warnings and notes * docs: update note about handling NU1403 --------- Co-authored-by: Ivan <98037481+IvanZosimov@users.noreply.github.com> Co-authored-by: IvanZosimov <ivanzosimov@github.com>
2023-05-29 18:43:18 +08:00
getExecOutputSpy.mockImplementation(() => {
return Promise.resolve({
exitCode: 1,
stdout: '',
stderr: errorMessage
});
});
feat: Cache NuGet global-packages folder (#303) * feat: cache NuGet global-packages folder * fix: remove unused files * docs: fix incorrect action * ci: add e2e test for cache * docs: accept suggested changes on README * docs: add simple cache example * build: change main script path * fix: change relative path to install scripts * fix: change relative path to problem matcher * refactor: accept changes on cache-utils * fix: revert main script path changes * test: fix cache-utils unit test * test: fix cache-utils unit test * feat: add `cache-dependency-path` variables * build: change main script dist path * ci: add `cache-dependency-path` e2e test & missing lock file * fix: accept change suggestions * ci: copy NuGet lock file to root to pass "test-setup-with-cache" e2e test * docs: change README guide * fix: apply suggestions from code review Co-authored-by: Ivan <98037481+IvanZosimov@users.noreply.github.com> * test: fix some failed unit tests - fix `restoreCache()` test for 9703c8 - update installer script * build: rebuild dist * Update unit-tests - Additional unit test were added to setup-dotnet.test.ts * Update unit tests for unix systems * Format and lint unit tests * fix: avoid use '/' on `path.join` * fix: rebuild dist * fix: apply suggestions from code review Co-authored-by: Ivan <98037481+IvanZosimov@users.noreply.github.com> * build: add `DisableImplicitNuGetFallbackFolder` option also add guide on README * docs: highlight warnings and notes * docs: update note about handling NU1403 --------- Co-authored-by: Ivan <98037481+IvanZosimov@users.noreply.github.com> Co-authored-by: IvanZosimov <ivanzosimov@github.com>
2023-05-29 18:43:18 +08:00
const dotnetInstaller = new installer.DotnetCoreInstaller(
inputVersion,
inputQuality
);
await expect(dotnetInstaller.installDotnet()).rejects.toThrow(
`Failed to install dotnet, exit code: 1. ${errorMessage}`
);
});
it('should return version of .NET SDK after installation complete', async () => {
const inputVersion = '3.1.100';
const inputQuality = '' as QualityOptions;
2023-05-15 20:24:28 +08:00
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
getExecOutputSpy.mockImplementation(() => {
2023-05-15 20:24:28 +08:00
return Promise.resolve({
exitCode: 0,
stdout: `${stdout}`,
stderr: ''
});
});
maxSatisfyingSpy.mockImplementation(() => inputVersion);
const dotnetInstaller = new installer.DotnetCoreInstaller(
inputVersion,
inputQuality
);
const installedVersion = await dotnetInstaller.installDotnet();
expect(installedVersion).toBe(inputVersion);
});
it(`should supply 'version' argument to the installation script if supplied version is in A.B.C syntax`, async () => {
const inputVersion = '6.0.300';
const inputQuality = '' as QualityOptions;
2023-05-15 20:24:28 +08:00
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
getExecOutputSpy.mockImplementation(() => {
2023-05-15 20:24:28 +08:00
return Promise.resolve({
exitCode: 0,
stdout: `${stdout}`,
stderr: ''
});
});
maxSatisfyingSpy.mockImplementation(() => inputVersion);
const dotnetInstaller = new installer.DotnetCoreInstaller(
inputVersion,
inputQuality
);
await dotnetInstaller.installDotnet();
2023-05-24 23:57:28 +08:00
/**
* First time script would be called to
* install runtime, here we checking only the
* second one that installs actual SDK. i.e. 1
*/
const callIndex = 1;
const scriptArguments = (
2023-05-24 23:57:28 +08:00
getExecOutputSpy.mock.calls[callIndex][1] as string[]
).join(' ');
const expectedArgument = IS_WINDOWS
? `-Version ${inputVersion}`
: `--version ${inputVersion}`;
expect(scriptArguments).toContain(expectedArgument);
});
it(`should warn if the 'quality' input is set and the supplied version is in A.B.C syntax`, async () => {
const inputVersion = '6.0.300';
const inputQuality = 'ga' as QualityOptions;
2023-05-15 20:24:28 +08:00
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
getExecOutputSpy.mockImplementation(() => {
2023-05-15 20:24:28 +08:00
return Promise.resolve({
exitCode: 0,
stdout: `${stdout}`,
stderr: ''
});
});
maxSatisfyingSpy.mockImplementation(() => inputVersion);
const dotnetInstaller = new installer.DotnetCoreInstaller(
inputVersion,
inputQuality
);
await dotnetInstaller.installDotnet();
expect(warningSpy).toHaveBeenCalledWith(
2023-05-18 18:39:22 +08:00
`The 'dotnet-quality' input can be used only with .NET SDK version in A.B, A.B.x, A, A.x and A.B.Cxx formats where the major tag is higher than 5. You specified: ${inputVersion}. 'dotnet-quality' input is ignored.`
);
});
it(`should warn if the 'quality' input is set and version isn't in A.B.C syntax but major tag is lower then 6`, async () => {
const inputVersion = '3.1';
const inputQuality = 'ga' as QualityOptions;
2023-05-15 20:24:28 +08:00
const stdout = `Fictitious dotnet version 3.1.100 is installed`;
getExecOutputSpy.mockImplementation(() => {
2023-05-15 20:24:28 +08:00
return Promise.resolve({
exitCode: 0,
stdout: `${stdout}`,
stderr: ''
});
});
maxSatisfyingSpy.mockImplementation(() => inputVersion);
const dotnetInstaller = new installer.DotnetCoreInstaller(
inputVersion,
inputQuality
);
await dotnetInstaller.installDotnet();
expect(warningSpy).toHaveBeenCalledWith(
2023-05-18 18:39:22 +08:00
`The 'dotnet-quality' input can be used only with .NET SDK version in A.B, A.B.x, A, A.x and A.B.Cxx formats where the major tag is higher than 5. You specified: ${inputVersion}. 'dotnet-quality' input is ignored.`
);
});
each(['6', '6.0', '6.0.x', '6.0.*', '6.0.X']).test(
`should supply 'quality' argument to the installation script if quality input is set and version (%s) is not in A.B.C syntax`,
async inputVersion => {
const inputQuality = 'ga' as QualityOptions;
const exitCode = 0;
2023-05-15 20:24:28 +08:00
const stdout = `Fictitious dotnet version 6.0.0 is installed`;
getExecOutputSpy.mockImplementation(() => {
return Promise.resolve({
exitCode: exitCode,
2023-05-15 20:24:28 +08:00
stdout: `${stdout}`,
stderr: ''
});
});
maxSatisfyingSpy.mockImplementation(() => inputVersion);
const dotnetInstaller = new installer.DotnetCoreInstaller(
inputVersion,
inputQuality
);
await dotnetInstaller.installDotnet();
2023-05-24 23:57:28 +08:00
/**
* First time script would be called to
* install runtime, here we checking only the
* second one that installs actual SDK. i.e. 1
*/
const callIndex = 1;
const scriptArguments = (
2023-05-24 23:57:28 +08:00
getExecOutputSpy.mock.calls[callIndex][1] as string[]
).join(' ');
const expectedArgument = IS_WINDOWS
? `-Quality ${inputQuality}`
: `--quality ${inputQuality}`;
expect(scriptArguments).toContain(expectedArgument);
}
2023-05-05 16:44:54 +08:00
);
each(['6', '6.0', '6.0.x', '6.0.*', '6.0.X']).test(
`should supply 'channel' argument to the installation script if version (%s) isn't in A.B.C syntax`,
async inputVersion => {
const inputQuality = '' as QualityOptions;
const exitCode = 0;
2023-05-15 20:24:28 +08:00
const stdout = `Fictitious dotnet version 6.0.0 is installed`;
getExecOutputSpy.mockImplementation(() => {
return Promise.resolve({
exitCode: exitCode,
2023-05-15 20:24:28 +08:00
stdout: `${stdout}`,
stderr: ''
});
});
maxSatisfyingSpy.mockImplementation(() => inputVersion);
const dotnetInstaller = new installer.DotnetCoreInstaller(
inputVersion,
inputQuality
);
await dotnetInstaller.installDotnet();
2023-05-24 23:57:28 +08:00
/**
* First time script would be called to
* install runtime, here we checking only the
* second one that installs actual SDK. i.e. 1
*/
const callIndex = 1;
const scriptArguments = (
2023-05-24 23:57:28 +08:00
getExecOutputSpy.mock.calls[callIndex][1] as string[]
).join(' ');
const expectedArgument = IS_WINDOWS
? `-Channel 6.0`
: `--channel 6.0`;
expect(scriptArguments).toContain(expectedArgument);
}
2023-05-05 16:44:54 +08:00
);
if (IS_WINDOWS) {
it(`should supply '-ProxyAddress' argument to the installation script if env.variable 'https_proxy' is set`, async () => {
process.env['https_proxy'] = 'https://proxy.com';
const inputVersion = '6.0.100';
const inputQuality = '' as QualityOptions;
2023-05-15 20:24:28 +08:00
const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
getExecOutputSpy.mockImplementation(() => {
2023-05-15 20:24:28 +08:00
return Promise.resolve({
exitCode: 0,
stdout: `${stdout}`,
stderr: ''
});
});
maxSatisfyingSpy.mockImplementation(() => inputVersion);
const dotnetInstaller = new installer.DotnetCoreInstaller(
inputVersion,
inputQuality
);
await dotnetInstaller.installDotnet();
2023-05-24 23:57:28 +08:00
/**
* First time script would be called to
* install runtime, here we checking only the
* second one that installs actual SDK. i.e. 1
*/
const callIndex = 1;
const scriptArguments = (
2023-05-24 23:57:28 +08:00
getExecOutputSpy.mock.calls[callIndex][1] as string[]
).join(' ');
expect(scriptArguments).toContain(
`-ProxyAddress ${process.env['https_proxy']}`
);
});
it(`should supply '-ProxyBypassList' argument to the installation script if env.variable 'no_proxy' is set`, async () => {
process.env['no_proxy'] = 'first.url,second.url';
const inputVersion = '6.0.100';
const inputQuality = '' as QualityOptions;
2023-05-15 20:24:28 +08:00
const stdout = `Fictitious dotnet version 6.0.0 is installed`;
getExecOutputSpy.mockImplementation(() => {
2023-05-15 20:24:28 +08:00
return Promise.resolve({
exitCode: 0,
stdout: `${stdout}`,
stderr: ''
});
});
maxSatisfyingSpy.mockImplementation(() => inputVersion);
const dotnetInstaller = new installer.DotnetCoreInstaller(
inputVersion,
inputQuality
);
await dotnetInstaller.installDotnet();
2023-05-24 23:57:28 +08:00
/**
* First time script would be called to
* install runtime, here we checking only the
* second one that installs actual SDK. i.e. 1
*/
const callIndex = 1;
const scriptArguments = (
2023-05-24 23:57:28 +08:00
getExecOutputSpy.mock.calls[callIndex][1] as string[]
).join(' ');
expect(scriptArguments).toContain(
`-ProxyBypassList ${process.env['no_proxy']}`
);
});
}
2020-01-26 14:37:54 +08:00
});
describe('addToPath() tests', () => {
it(`should export DOTNET_ROOT env.var with value from DOTNET_INSTALL_DIR env.var`, async () => {
process.env['DOTNET_INSTALL_DIR'] = 'fictitious/dotnet/install/dir';
2023-05-30 18:45:38 +08:00
installer.DotnetInstallDir.addToPath();
const dotnet_root = process.env['DOTNET_ROOT'];
expect(dotnet_root).toBe(process.env['DOTNET_INSTALL_DIR']);
});
it(`should export value from DOTNET_INSTALL_DIR env.var to the PATH`, async () => {
process.env['DOTNET_INSTALL_DIR'] = 'fictitious/dotnet/install/dir';
2023-05-30 18:45:38 +08:00
installer.DotnetInstallDir.addToPath();
const path = process.env['PATH'];
expect(path).toContain(process.env['DOTNET_INSTALL_DIR']);
});
});
});
describe('DotnetVersionResolver tests', () => {
2023-05-24 22:59:05 +08:00
describe('createDotnetVersion() tests', () => {
each([
'3.1',
'3.x',
'3.1.x',
'3.1.*',
'3.1.X',
'3.1.2',
2023-05-18 17:11:51 +08:00
'3.1.0-preview1',
'6.0.2xx'
]).test(
'if valid version is supplied (%s), it should return version object with some value',
async version => {
const dotnetVersionResolver = new installer.DotnetVersionResolver(
version
);
const versionObject =
2023-05-24 22:59:05 +08:00
await dotnetVersionResolver.createDotnetVersion();
expect(!!versionObject.value).toBe(true);
}
2023-05-05 16:44:54 +08:00
);
each([
'.',
'..',
' . ',
'. ',
' .',
' . . ',
' .. ',
' . ',
'-1.-1',
'-1',
'-1.-1.-1',
'..3',
'1..3',
'1..',
'.2.3',
'.2.x',
'*.',
'1.2.',
'1.2.-abc',
'a.b',
'a.b.c',
'a.b.c-preview',
' 0 . 1 . 2 ',
'invalid'
]).test(
'if invalid version is supplied (%s), it should throw',
async version => {
const dotnetVersionResolver = new installer.DotnetVersionResolver(
version
);
await expect(
2023-05-24 22:59:05 +08:00
async () => await dotnetVersionResolver.createDotnetVersion()
).rejects.toThrow();
}
);
2023-05-05 16:44:54 +08:00
each(['3', '3.1', '3.1.x', '3.1.*', '3.1.X', '6.0.2xx']).test(
"if version that can be resolved to 'channel' option is supplied (%s), it should set type to 'channel' in version object",
async version => {
const dotnetVersionResolver = new installer.DotnetVersionResolver(
version
);
const versionObject =
2023-05-24 22:59:05 +08:00
await dotnetVersionResolver.createDotnetVersion();
expect(versionObject.type.toLowerCase().includes('channel')).toBe(
true
);
}
2023-05-05 16:44:54 +08:00
);
each(['6.0', '6.0.x', '6.0.*', '6.0.X', '6.0.2xx']).test(
"if version that can be resolved to 'channel' option is supplied and its major tag is >= 6 (%s), it should set type to 'channel' and qualityFlag to 'true' in version object",
async version => {
const dotnetVersionResolver = new installer.DotnetVersionResolver(
version
);
const versionObject =
2023-05-24 22:59:05 +08:00
await dotnetVersionResolver.createDotnetVersion();
expect(versionObject.type.toLowerCase().includes('channel')).toBe(
true
);
expect(versionObject.qualityFlag).toBe(true);
}
2023-05-05 16:44:54 +08:00
);
each(['3.1.2', '3.1.0-preview1']).test(
"if version that can be resolved to 'version' option is supplied (%s), it should set quality flag to 'false' and type to 'version' in version object",
async version => {
const dotnetVersionResolver = new installer.DotnetVersionResolver(
version
);
const versionObject =
2023-05-24 22:59:05 +08:00
await dotnetVersionResolver.createDotnetVersion();
expect(versionObject.type.toLowerCase().includes('version')).toBe(
true
);
expect(versionObject.qualityFlag).toBe(false);
}
2023-05-05 16:44:54 +08:00
);
each(['3.1.2', '3.1']).test(
'it should create proper line arguments for powershell/bash installation scripts',
async version => {
const dotnetVersionResolver = new installer.DotnetVersionResolver(
version
);
const versionObject =
2023-05-24 22:59:05 +08:00
await dotnetVersionResolver.createDotnetVersion();
const windowsRegEx = new RegExp(/^-(Version|Channel)/);
const nonWindowsRegEx = new RegExp(/^--(version|channel)/);
if (IS_WINDOWS) {
expect(windowsRegEx.test(versionObject.type)).toBe(true);
expect(nonWindowsRegEx.test(versionObject.type)).toBe(false);
} else {
expect(nonWindowsRegEx.test(versionObject.type)).toBe(true);
expect(windowsRegEx.test(versionObject.type)).toBe(false);
}
}
);
2023-05-18 17:11:51 +08:00
it(`should throw if dotnet-version is supplied in A.B.Cxx syntax with major tag lower that 5`, async () => {
const version = '3.0.1xx';
const dotnetVersionResolver = new installer.DotnetVersionResolver(
version
);
await expect(
2023-05-24 22:59:05 +08:00
async () => await dotnetVersionResolver.createDotnetVersion()
2023-05-18 17:11:51 +08:00
).rejects.toThrow(
`'dotnet-version' was supplied in invalid format: ${version}! The A.B.Cxx syntax is available since the .NET 5.0 release.`
);
});
});
});
2023-05-15 20:24:28 +08:00
});