mirror of
				https://github.com/actions/setup-dotnet.git
				synced 2025-10-31 23:13:45 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			493 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			493 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import each from 'jest-each';
 | |
| import semver from 'semver';
 | |
| 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');
 | |
|     const chmodSyncSpy = jest.spyOn(fs, 'chmodSync');
 | |
|     const readdirSpy = jest.spyOn(fspromises, 'readdir');
 | |
| 
 | |
|     describe('installDotnet() tests', () => {
 | |
|       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!';
 | |
| 
 | |
|         getExecOutputSpy.mockImplementation(() => {
 | |
|           return Promise.resolve({
 | |
|             exitCode: 1,
 | |
|             stdout: '',
 | |
|             stderr: errorMessage
 | |
|           });
 | |
|         });
 | |
| 
 | |
|         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;
 | |
|         const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
 | |
|         getExecOutputSpy.mockImplementation(() => {
 | |
|           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;
 | |
|         const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
 | |
| 
 | |
|         getExecOutputSpy.mockImplementation(() => {
 | |
|           return Promise.resolve({
 | |
|             exitCode: 0,
 | |
|             stdout: `${stdout}`,
 | |
|             stderr: ''
 | |
|           });
 | |
|         });
 | |
|         maxSatisfyingSpy.mockImplementation(() => inputVersion);
 | |
| 
 | |
|         const dotnetInstaller = new installer.DotnetCoreInstaller(
 | |
|           inputVersion,
 | |
|           inputQuality
 | |
|         );
 | |
| 
 | |
|         await dotnetInstaller.installDotnet();
 | |
| 
 | |
|         /**
 | |
|          * 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 = (
 | |
|           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;
 | |
|         const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
 | |
|         getExecOutputSpy.mockImplementation(() => {
 | |
|           return Promise.resolve({
 | |
|             exitCode: 0,
 | |
|             stdout: `${stdout}`,
 | |
|             stderr: ''
 | |
|           });
 | |
|         });
 | |
|         maxSatisfyingSpy.mockImplementation(() => inputVersion);
 | |
| 
 | |
|         const dotnetInstaller = new installer.DotnetCoreInstaller(
 | |
|           inputVersion,
 | |
|           inputQuality
 | |
|         );
 | |
| 
 | |
|         await dotnetInstaller.installDotnet();
 | |
| 
 | |
|         expect(warningSpy).toHaveBeenCalledWith(
 | |
|           `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;
 | |
|         const stdout = `Fictitious dotnet version 3.1.100 is installed`;
 | |
| 
 | |
|         getExecOutputSpy.mockImplementation(() => {
 | |
|           return Promise.resolve({
 | |
|             exitCode: 0,
 | |
|             stdout: `${stdout}`,
 | |
|             stderr: ''
 | |
|           });
 | |
|         });
 | |
|         maxSatisfyingSpy.mockImplementation(() => inputVersion);
 | |
| 
 | |
|         const dotnetInstaller = new installer.DotnetCoreInstaller(
 | |
|           inputVersion,
 | |
|           inputQuality
 | |
|         );
 | |
| 
 | |
|         await dotnetInstaller.installDotnet();
 | |
| 
 | |
|         expect(warningSpy).toHaveBeenCalledWith(
 | |
|           `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;
 | |
|           const stdout = `Fictitious dotnet version 6.0.0 is installed`;
 | |
|           getExecOutputSpy.mockImplementation(() => {
 | |
|             return Promise.resolve({
 | |
|               exitCode: exitCode,
 | |
|               stdout: `${stdout}`,
 | |
|               stderr: ''
 | |
|             });
 | |
|           });
 | |
|           maxSatisfyingSpy.mockImplementation(() => inputVersion);
 | |
| 
 | |
|           const dotnetInstaller = new installer.DotnetCoreInstaller(
 | |
|             inputVersion,
 | |
|             inputQuality
 | |
|           );
 | |
| 
 | |
|           await dotnetInstaller.installDotnet();
 | |
| 
 | |
|           /**
 | |
|            * 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 = (
 | |
|             getExecOutputSpy.mock.calls[callIndex][1] as string[]
 | |
|           ).join(' ');
 | |
|           const expectedArgument = IS_WINDOWS
 | |
|             ? `-Quality ${inputQuality}`
 | |
|             : `--quality ${inputQuality}`;
 | |
| 
 | |
|           expect(scriptArguments).toContain(expectedArgument);
 | |
|         }
 | |
|       );
 | |
| 
 | |
|       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;
 | |
|           const stdout = `Fictitious dotnet version 6.0.0 is installed`;
 | |
|           getExecOutputSpy.mockImplementation(() => {
 | |
|             return Promise.resolve({
 | |
|               exitCode: exitCode,
 | |
|               stdout: `${stdout}`,
 | |
|               stderr: ''
 | |
|             });
 | |
|           });
 | |
|           maxSatisfyingSpy.mockImplementation(() => inputVersion);
 | |
| 
 | |
|           const dotnetInstaller = new installer.DotnetCoreInstaller(
 | |
|             inputVersion,
 | |
|             inputQuality
 | |
|           );
 | |
| 
 | |
|           await dotnetInstaller.installDotnet();
 | |
| 
 | |
|           /**
 | |
|            * 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 = (
 | |
|             getExecOutputSpy.mock.calls[callIndex][1] as string[]
 | |
|           ).join(' ');
 | |
|           const expectedArgument = IS_WINDOWS
 | |
|             ? `-Channel 6.0`
 | |
|             : `--channel 6.0`;
 | |
| 
 | |
|           expect(scriptArguments).toContain(expectedArgument);
 | |
|         }
 | |
|       );
 | |
| 
 | |
|       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;
 | |
|           const stdout = `Fictitious dotnet version ${inputVersion} is installed`;
 | |
| 
 | |
|           getExecOutputSpy.mockImplementation(() => {
 | |
|             return Promise.resolve({
 | |
|               exitCode: 0,
 | |
|               stdout: `${stdout}`,
 | |
|               stderr: ''
 | |
|             });
 | |
|           });
 | |
|           maxSatisfyingSpy.mockImplementation(() => inputVersion);
 | |
| 
 | |
|           const dotnetInstaller = new installer.DotnetCoreInstaller(
 | |
|             inputVersion,
 | |
|             inputQuality
 | |
|           );
 | |
| 
 | |
|           await dotnetInstaller.installDotnet();
 | |
| 
 | |
|           /**
 | |
|            * 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 = (
 | |
|             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;
 | |
|           const stdout = `Fictitious dotnet version 6.0.0 is installed`;
 | |
| 
 | |
|           getExecOutputSpy.mockImplementation(() => {
 | |
|             return Promise.resolve({
 | |
|               exitCode: 0,
 | |
|               stdout: `${stdout}`,
 | |
|               stderr: ''
 | |
|             });
 | |
|           });
 | |
|           maxSatisfyingSpy.mockImplementation(() => inputVersion);
 | |
| 
 | |
|           const dotnetInstaller = new installer.DotnetCoreInstaller(
 | |
|             inputVersion,
 | |
|             inputQuality
 | |
|           );
 | |
| 
 | |
|           await dotnetInstaller.installDotnet();
 | |
| 
 | |
|           /**
 | |
|            * 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 = (
 | |
|             getExecOutputSpy.mock.calls[callIndex][1] as string[]
 | |
|           ).join(' ');
 | |
| 
 | |
|           expect(scriptArguments).toContain(
 | |
|             `-ProxyBypassList ${process.env['no_proxy']}`
 | |
|           );
 | |
|         });
 | |
|       }
 | |
|     });
 | |
| 
 | |
|     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';
 | |
|         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';
 | |
|         installer.DotnetInstallDir.addToPath();
 | |
|         const path = process.env['PATH'];
 | |
|         expect(path).toContain(process.env['DOTNET_INSTALL_DIR']);
 | |
|       });
 | |
|     });
 | |
|   });
 | |
| 
 | |
|   describe('DotnetVersionResolver tests', () => {
 | |
|     describe('createDotnetVersion() tests', () => {
 | |
|       each([
 | |
|         '3.1',
 | |
|         '3.x',
 | |
|         '3.1.x',
 | |
|         '3.1.*',
 | |
|         '3.1.X',
 | |
|         '3.1.2',
 | |
|         '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 =
 | |
|             await dotnetVersionResolver.createDotnetVersion();
 | |
| 
 | |
|           expect(!!versionObject.value).toBe(true);
 | |
|         }
 | |
|       );
 | |
| 
 | |
|       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(
 | |
|             async () => await dotnetVersionResolver.createDotnetVersion()
 | |
|           ).rejects.toThrow();
 | |
|         }
 | |
|       );
 | |
| 
 | |
|       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 =
 | |
|             await dotnetVersionResolver.createDotnetVersion();
 | |
| 
 | |
|           expect(versionObject.type.toLowerCase().includes('channel')).toBe(
 | |
|             true
 | |
|           );
 | |
|         }
 | |
|       );
 | |
| 
 | |
|       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 =
 | |
|             await dotnetVersionResolver.createDotnetVersion();
 | |
| 
 | |
|           expect(versionObject.type.toLowerCase().includes('channel')).toBe(
 | |
|             true
 | |
|           );
 | |
|           expect(versionObject.qualityFlag).toBe(true);
 | |
|         }
 | |
|       );
 | |
| 
 | |
|       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 =
 | |
|             await dotnetVersionResolver.createDotnetVersion();
 | |
| 
 | |
|           expect(versionObject.type.toLowerCase().includes('version')).toBe(
 | |
|             true
 | |
|           );
 | |
|           expect(versionObject.qualityFlag).toBe(false);
 | |
|         }
 | |
|       );
 | |
| 
 | |
|       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 =
 | |
|             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);
 | |
|           }
 | |
|         }
 | |
|       );
 | |
| 
 | |
|       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(
 | |
|           async () => await dotnetVersionResolver.createDotnetVersion()
 | |
|         ).rejects.toThrow(
 | |
|           `'dotnet-version' was supplied in invalid format: ${version}! The A.B.Cxx syntax is available since the .NET 5.0 release.`
 | |
|         );
 | |
|       });
 | |
|     });
 | |
|   });
 | |
| });
 |