mirror of
				https://gitea.com/actions/setup-node.git
				synced 2025-11-04 13:49:03 +08:00 
			
		
		
		
	Handle globs in cacheDependencyPath
This commit is contained in:
		@@ -210,97 +210,4 @@ describe('authutil tests', () => {
 | 
			
		||||
      `@otherscope:registry=MMM${os.EOL}//registry.npmjs.org/:_authToken=\${NODE_AUTH_TOKEN}${os.EOL}@myscope:registry=https://registry.npmjs.org/${os.EOL}always-auth=true`
 | 
			
		||||
    );
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('getPackageManagerWorkingDir', () => {
 | 
			
		||||
    let existsSpy: jest.SpyInstance;
 | 
			
		||||
    let lstatSpy: jest.SpyInstance;
 | 
			
		||||
 | 
			
		||||
    beforeEach(() => {
 | 
			
		||||
      existsSpy = jest.spyOn(fs, 'existsSync');
 | 
			
		||||
      existsSpy.mockImplementation(() => true);
 | 
			
		||||
 | 
			
		||||
      lstatSpy = jest.spyOn(fs, 'lstatSync');
 | 
			
		||||
      lstatSpy.mockImplementation(arg => ({
 | 
			
		||||
        isDirectory: () => true
 | 
			
		||||
      }));
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    afterEach(() => {
 | 
			
		||||
      existsSpy.mockRestore();
 | 
			
		||||
      lstatSpy.mockRestore();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('getPackageManagerWorkingDir should return null for not yarn', async () => {
 | 
			
		||||
      process.env['INPUT_CACHE'] = 'some';
 | 
			
		||||
      delete process.env['INPUT_CACHE-DEPENDENCY-PATH'];
 | 
			
		||||
      const dir = cacheUtils.getPackageManagerWorkingDir();
 | 
			
		||||
      expect(dir).toBeNull();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('getPackageManagerWorkingDir should return null for not yarn with cache-dependency-path', async () => {
 | 
			
		||||
      process.env['INPUT_CACHE'] = 'some';
 | 
			
		||||
      process.env['INPUT_CACHE-DEPENDENCY-PATH'] = '/foo/bar';
 | 
			
		||||
      const dir = cacheUtils.getPackageManagerWorkingDir();
 | 
			
		||||
      expect(dir).toBeNull();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('getPackageManagerWorkingDir should return null for yarn but without cache-dependency-path', async () => {
 | 
			
		||||
      process.env['INPUT_CACHE'] = 'yarn';
 | 
			
		||||
      delete process.env['INPUT_CACHE-DEPENDENCY-PATH'];
 | 
			
		||||
      const dir = cacheUtils.getPackageManagerWorkingDir();
 | 
			
		||||
      expect(dir).toBeNull();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('getPackageManagerWorkingDir should return null for yarn with cache-dependency-path for not-existing directory', async () => {
 | 
			
		||||
      process.env['INPUT_CACHE'] = 'yarn';
 | 
			
		||||
      const cachePath = '/foo/bar';
 | 
			
		||||
      process.env['INPUT_CACHE-DEPENDENCY-PATH'] = cachePath;
 | 
			
		||||
      lstatSpy.mockImplementation(arg => ({
 | 
			
		||||
        isDirectory: () => false
 | 
			
		||||
      }));
 | 
			
		||||
      const dir = cacheUtils.getPackageManagerWorkingDir();
 | 
			
		||||
      expect(dir).toBeNull();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('getPackageManagerWorkingDir should return path for yarn with cache-dependency-path', async () => {
 | 
			
		||||
      process.env['INPUT_CACHE'] = 'yarn';
 | 
			
		||||
      const cachePath = '/foo/bar';
 | 
			
		||||
      process.env['INPUT_CACHE-DEPENDENCY-PATH'] = cachePath;
 | 
			
		||||
      const dir = cacheUtils.getPackageManagerWorkingDir();
 | 
			
		||||
      expect(dir).toEqual(path.dirname(cachePath));
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('getCommandOutput(getPackageManagerVersion) should be called from  with getPackageManagerWorkingDir result', async () => {
 | 
			
		||||
      process.env['INPUT_CACHE'] = 'yarn';
 | 
			
		||||
      const cachePath = '/foo/bar';
 | 
			
		||||
      process.env['INPUT_CACHE-DEPENDENCY-PATH'] = cachePath;
 | 
			
		||||
      const getCommandOutputSpy = jest
 | 
			
		||||
        .spyOn(cacheUtils, 'getCommandOutput')
 | 
			
		||||
        .mockReturnValue(Promise.resolve('baz'));
 | 
			
		||||
 | 
			
		||||
      const version = await cacheUtils.getPackageManagerVersion('foo', 'bar');
 | 
			
		||||
      expect(getCommandOutputSpy).toHaveBeenCalledWith(
 | 
			
		||||
        `foo bar`,
 | 
			
		||||
        path.dirname(cachePath)
 | 
			
		||||
      );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('getCommandOutput(getCacheDirectoryPath) should be called from  with getPackageManagerWorkingDir result', async () => {
 | 
			
		||||
      process.env['INPUT_CACHE'] = 'yarn';
 | 
			
		||||
      const cachePath = '/foo/bar';
 | 
			
		||||
      process.env['INPUT_CACHE-DEPENDENCY-PATH'] = cachePath;
 | 
			
		||||
      const getCommandOutputSpy = jest
 | 
			
		||||
        .spyOn(cacheUtils, 'getCommandOutput')
 | 
			
		||||
        .mockReturnValue(Promise.resolve('baz'));
 | 
			
		||||
 | 
			
		||||
      const version = await cacheUtils.getCacheDirectoryPath(
 | 
			
		||||
        {lockFilePatterns: [], getCacheFolderCommand: 'quz'},
 | 
			
		||||
        ''
 | 
			
		||||
      );
 | 
			
		||||
      expect(getCommandOutputSpy).toHaveBeenCalledWith(
 | 
			
		||||
        `quz`,
 | 
			
		||||
        path.dirname(cachePath)
 | 
			
		||||
      );
 | 
			
		||||
    });
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -32,13 +32,13 @@ describe('cache-restore', () => {
 | 
			
		||||
 | 
			
		||||
  function findCacheFolder(command: string) {
 | 
			
		||||
    switch (command) {
 | 
			
		||||
      case utils.supportedPackageManagers.npm.getCacheFolderCommand:
 | 
			
		||||
      case utils.npmGetCacheFolderCommand:
 | 
			
		||||
        return npmCachePath;
 | 
			
		||||
      case utils.supportedPackageManagers.pnpm.getCacheFolderCommand:
 | 
			
		||||
      case utils.pnpmGetCacheFolderCommand:
 | 
			
		||||
        return pnpmCachePath;
 | 
			
		||||
      case utils.supportedPackageManagers.yarn1.getCacheFolderCommand:
 | 
			
		||||
      case utils.yarn1GetCacheFolderCommand:
 | 
			
		||||
        return yarn1CachePath;
 | 
			
		||||
      case utils.supportedPackageManagers.yarn2.getCacheFolderCommand:
 | 
			
		||||
      case utils.yarn2GetCacheFolderCommand:
 | 
			
		||||
        return yarn2CachePath;
 | 
			
		||||
      default:
 | 
			
		||||
        return 'packge/not/found';
 | 
			
		||||
@@ -108,7 +108,7 @@ describe('cache-restore', () => {
 | 
			
		||||
    it.each([['npm7'], ['npm6'], ['pnpm6'], ['yarn1'], ['yarn2'], ['random']])(
 | 
			
		||||
      'Throw an error because %s is not supported',
 | 
			
		||||
      async packageManager => {
 | 
			
		||||
        await expect(restoreCache(packageManager)).rejects.toThrow(
 | 
			
		||||
        await expect(restoreCache(packageManager, '')).rejects.toThrow(
 | 
			
		||||
          `Caching for '${packageManager}' is not supported`
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
@@ -132,7 +132,7 @@ describe('cache-restore', () => {
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        await restoreCache(packageManager);
 | 
			
		||||
        await restoreCache(packageManager, '');
 | 
			
		||||
        expect(hashFilesSpy).toHaveBeenCalled();
 | 
			
		||||
        expect(infoSpy).toHaveBeenCalledWith(
 | 
			
		||||
          `Cache restored from key: node-cache-${platform}-${packageManager}-v2-${fileHash}`
 | 
			
		||||
@@ -163,7 +163,7 @@ describe('cache-restore', () => {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        restoreCacheSpy.mockImplementationOnce(() => undefined);
 | 
			
		||||
        await restoreCache(packageManager);
 | 
			
		||||
        await restoreCache(packageManager, '');
 | 
			
		||||
        expect(hashFilesSpy).toHaveBeenCalled();
 | 
			
		||||
        expect(infoSpy).toHaveBeenCalledWith(
 | 
			
		||||
          `${packageManager} cache is not found`
 | 
			
		||||
 
 | 
			
		||||
@@ -117,7 +117,9 @@ describe('run', () => {
 | 
			
		||||
      expect(getInputSpy).toHaveBeenCalled();
 | 
			
		||||
      expect(getStateSpy).toHaveBeenCalledTimes(2);
 | 
			
		||||
      expect(getCommandOutputSpy).toHaveBeenCalledTimes(2);
 | 
			
		||||
      expect(debugSpy).toHaveBeenCalledWith(`yarn path is ${commonPath}/yarn1`);
 | 
			
		||||
      expect(debugSpy).toHaveBeenCalledWith(
 | 
			
		||||
        'yarn path is /some/random/path/yarn1 (derived from cache-dependency-path: "")'
 | 
			
		||||
      );
 | 
			
		||||
      expect(debugSpy).toHaveBeenCalledWith('Consumed yarn version is 1.2.3');
 | 
			
		||||
      expect(infoSpy).toHaveBeenCalledWith(
 | 
			
		||||
        `Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
 | 
			
		||||
@@ -137,7 +139,9 @@ describe('run', () => {
 | 
			
		||||
      expect(getInputSpy).toHaveBeenCalled();
 | 
			
		||||
      expect(getStateSpy).toHaveBeenCalledTimes(2);
 | 
			
		||||
      expect(getCommandOutputSpy).toHaveBeenCalledTimes(2);
 | 
			
		||||
      expect(debugSpy).toHaveBeenCalledWith(`yarn path is ${commonPath}/yarn2`);
 | 
			
		||||
      expect(debugSpy).toHaveBeenCalledWith(
 | 
			
		||||
        'yarn path is /some/random/path/yarn2 (derived from cache-dependency-path: "")'
 | 
			
		||||
      );
 | 
			
		||||
      expect(debugSpy).toHaveBeenCalledWith('Consumed yarn version is 2.2.3');
 | 
			
		||||
      expect(infoSpy).toHaveBeenCalledWith(
 | 
			
		||||
        `Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
 | 
			
		||||
@@ -199,7 +203,9 @@ describe('run', () => {
 | 
			
		||||
      expect(getInputSpy).toHaveBeenCalled();
 | 
			
		||||
      expect(getStateSpy).toHaveBeenCalledTimes(2);
 | 
			
		||||
      expect(getCommandOutputSpy).toHaveBeenCalledTimes(2);
 | 
			
		||||
      expect(debugSpy).toHaveBeenCalledWith(`yarn path is ${commonPath}/yarn1`);
 | 
			
		||||
      expect(debugSpy).toHaveBeenCalledWith(
 | 
			
		||||
        'yarn path is /some/random/path/yarn1 (derived from cache-dependency-path: "")'
 | 
			
		||||
      );
 | 
			
		||||
      expect(debugSpy).toHaveBeenCalledWith('Consumed yarn version is 1.2.3');
 | 
			
		||||
      expect(infoSpy).not.toHaveBeenCalledWith(
 | 
			
		||||
        `Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
 | 
			
		||||
@@ -229,7 +235,9 @@ describe('run', () => {
 | 
			
		||||
      expect(getInputSpy).toHaveBeenCalled();
 | 
			
		||||
      expect(getStateSpy).toHaveBeenCalledTimes(2);
 | 
			
		||||
      expect(getCommandOutputSpy).toHaveBeenCalledTimes(2);
 | 
			
		||||
      expect(debugSpy).toHaveBeenCalledWith(`yarn path is ${commonPath}/yarn2`);
 | 
			
		||||
      expect(debugSpy).toHaveBeenCalledWith(
 | 
			
		||||
        'yarn path is /some/random/path/yarn2 (derived from cache-dependency-path: "")'
 | 
			
		||||
      );
 | 
			
		||||
      expect(debugSpy).toHaveBeenCalledWith('Consumed yarn version is 2.2.3');
 | 
			
		||||
      expect(infoSpy).not.toHaveBeenCalledWith(
 | 
			
		||||
        `Cache hit occurred on the primary key ${yarnFileHash}, not saving cache.`
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,18 @@ import * as core from '@actions/core';
 | 
			
		||||
import * as cache from '@actions/cache';
 | 
			
		||||
import path from 'path';
 | 
			
		||||
import * as utils from '../src/cache-utils';
 | 
			
		||||
import {PackageManagerInfo, isCacheFeatureAvailable} from '../src/cache-utils';
 | 
			
		||||
import {
 | 
			
		||||
  PackageManagerInfo,
 | 
			
		||||
  isCacheFeatureAvailable,
 | 
			
		||||
  supportedPackageManagers,
 | 
			
		||||
  getCommandOutput,
 | 
			
		||||
  expandCacheDependencyPath
 | 
			
		||||
} from '../src/cache-utils';
 | 
			
		||||
import fs from 'fs';
 | 
			
		||||
import * as cacheUtils from '../src/cache-utils';
 | 
			
		||||
import * as glob from '@actions/glob';
 | 
			
		||||
import {Globber} from '@actions/glob';
 | 
			
		||||
import {MockGlobber} from './mock/glob-mock';
 | 
			
		||||
 | 
			
		||||
describe('cache-utils', () => {
 | 
			
		||||
  const versionYarn1 = '1.2.3';
 | 
			
		||||
@@ -30,7 +41,7 @@ describe('cache-utils', () => {
 | 
			
		||||
    it.each<[string, PackageManagerInfo | null]>([
 | 
			
		||||
      ['npm', utils.supportedPackageManagers.npm],
 | 
			
		||||
      ['pnpm', utils.supportedPackageManagers.pnpm],
 | 
			
		||||
      ['yarn', utils.supportedPackageManagers.yarn1],
 | 
			
		||||
      ['yarn', utils.supportedPackageManagers.yarn],
 | 
			
		||||
      ['yarn1', null],
 | 
			
		||||
      ['yarn2', null],
 | 
			
		||||
      ['npm7', null]
 | 
			
		||||
@@ -72,4 +83,284 @@ describe('cache-utils', () => {
 | 
			
		||||
    jest.resetAllMocks();
 | 
			
		||||
    jest.clearAllMocks();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  describe('getCacheDirectoriesPaths', () => {
 | 
			
		||||
    let existsSpy: jest.SpyInstance;
 | 
			
		||||
    let lstatSpy: jest.SpyInstance;
 | 
			
		||||
    let globCreateSpy: jest.SpyInstance;
 | 
			
		||||
 | 
			
		||||
    beforeEach(() => {
 | 
			
		||||
      existsSpy = jest.spyOn(fs, 'existsSync');
 | 
			
		||||
      existsSpy.mockImplementation(() => true);
 | 
			
		||||
 | 
			
		||||
      lstatSpy = jest.spyOn(fs, 'lstatSync');
 | 
			
		||||
      lstatSpy.mockImplementation(arg => ({
 | 
			
		||||
        isDirectory: () => true
 | 
			
		||||
      }));
 | 
			
		||||
 | 
			
		||||
      globCreateSpy = jest.spyOn(glob, 'create');
 | 
			
		||||
 | 
			
		||||
      globCreateSpy.mockImplementation(
 | 
			
		||||
        (pattern: string): Promise<Globber> =>
 | 
			
		||||
          MockGlobber.create(['/foo', '/bar'])
 | 
			
		||||
      );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    afterEach(() => {
 | 
			
		||||
      existsSpy.mockRestore();
 | 
			
		||||
      lstatSpy.mockRestore();
 | 
			
		||||
      globCreateSpy.mockRestore();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('expandCacheDependencyPath should handle one line', async () => {
 | 
			
		||||
      expect(await expandCacheDependencyPath('one')).toEqual(['one']);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('expandCacheDependencyPath should handle one line glob', async () => {
 | 
			
		||||
      globCreateSpy.mockImplementation(
 | 
			
		||||
        (pattern: string): Promise<Globber> =>
 | 
			
		||||
          MockGlobber.create(['one', 'two'])
 | 
			
		||||
      );
 | 
			
		||||
      expect(await expandCacheDependencyPath('**')).toEqual(['one', 'two']);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('expandCacheDependencyPath should handle multiple lines', async () => {
 | 
			
		||||
      const lines = `
 | 
			
		||||
          one
 | 
			
		||||
two
 | 
			
		||||
 | 
			
		||||
          `;
 | 
			
		||||
      expect(await expandCacheDependencyPath(lines)).toEqual(['one', 'two']);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('expandCacheDependencyPath should handle multiple globs', async () => {
 | 
			
		||||
      const lines = `
 | 
			
		||||
          one
 | 
			
		||||
**
 | 
			
		||||
 | 
			
		||||
          `;
 | 
			
		||||
      globCreateSpy.mockImplementation(
 | 
			
		||||
        (pattern: string): Promise<Globber> =>
 | 
			
		||||
          MockGlobber.create(['two', 'three'])
 | 
			
		||||
      );
 | 
			
		||||
      expect(await expandCacheDependencyPath(lines)).toEqual([
 | 
			
		||||
        'one',
 | 
			
		||||
        'two',
 | 
			
		||||
        'three'
 | 
			
		||||
      ]);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it.each([
 | 
			
		||||
      [supportedPackageManagers.npm, ''],
 | 
			
		||||
      [supportedPackageManagers.npm, '/dir/file.lock'],
 | 
			
		||||
      [supportedPackageManagers.npm, '/**/file.lock'],
 | 
			
		||||
      [supportedPackageManagers.pnpm, ''],
 | 
			
		||||
      [supportedPackageManagers.pnpm, '/dir/file.lock'],
 | 
			
		||||
      [supportedPackageManagers.pnpm, '/**/file.lock']
 | 
			
		||||
    ])(
 | 
			
		||||
      'getCacheDirectoriesPaths should return one dir for non yarn',
 | 
			
		||||
      async (packageManagerInfo, cacheDependency) => {
 | 
			
		||||
        getCommandOutputSpy.mockImplementation(() => 'foo');
 | 
			
		||||
 | 
			
		||||
        const dirs = await cacheUtils.getCacheDirectoriesPaths(
 | 
			
		||||
          packageManagerInfo,
 | 
			
		||||
          cacheDependency
 | 
			
		||||
        );
 | 
			
		||||
        expect(dirs).toEqual(['foo']);
 | 
			
		||||
        // to do not call for a version
 | 
			
		||||
        // call once for get cache folder
 | 
			
		||||
        expect(getCommandOutputSpy).toHaveBeenCalledTimes(1);
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    it('getCacheDirectoriesPaths should return one dir for yarn without cacheDependency', async () => {
 | 
			
		||||
      getCommandOutputSpy.mockImplementation(() => 'foo');
 | 
			
		||||
 | 
			
		||||
      const dirs = await cacheUtils.getCacheDirectoriesPaths(
 | 
			
		||||
        supportedPackageManagers.yarn,
 | 
			
		||||
        ''
 | 
			
		||||
      );
 | 
			
		||||
      expect(dirs).toEqual(['foo']);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it.each([
 | 
			
		||||
      [supportedPackageManagers.npm, ''],
 | 
			
		||||
      [supportedPackageManagers.npm, '/dir/file.lock'],
 | 
			
		||||
      [supportedPackageManagers.npm, '/**/file.lock'],
 | 
			
		||||
      [supportedPackageManagers.pnpm, ''],
 | 
			
		||||
      [supportedPackageManagers.pnpm, '/dir/file.lock'],
 | 
			
		||||
      [supportedPackageManagers.pnpm, '/**/file.lock'],
 | 
			
		||||
      [supportedPackageManagers.yarn, ''],
 | 
			
		||||
      [supportedPackageManagers.yarn, '/dir/file.lock'],
 | 
			
		||||
      [supportedPackageManagers.yarn, '/**/file.lock']
 | 
			
		||||
    ])(
 | 
			
		||||
      'getCacheDirectoriesPaths should return empty array of folder in case of error',
 | 
			
		||||
      async (packageManagerInfo, cacheDependency) => {
 | 
			
		||||
        getCommandOutputSpy.mockImplementation((command: string) =>
 | 
			
		||||
          // return empty string to indicate getCacheFolderPath failed
 | 
			
		||||
          //        --version still works
 | 
			
		||||
          command.includes('version') ? '1.' : ''
 | 
			
		||||
        );
 | 
			
		||||
        lstatSpy.mockImplementation(arg => ({
 | 
			
		||||
          isDirectory: () => false
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        await expect(
 | 
			
		||||
          cacheUtils.getCacheDirectoriesPaths(
 | 
			
		||||
            packageManagerInfo,
 | 
			
		||||
            cacheDependency
 | 
			
		||||
          )
 | 
			
		||||
        ).rejects.toThrow(); //'Could not get cache folder path for /dir');
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    it.each(['1.1.1', '2.2.2'])(
 | 
			
		||||
      'getCacheDirectoriesPaths yarn v%s should return one dir without cacheDependency',
 | 
			
		||||
      async version => {
 | 
			
		||||
        getCommandOutputSpy.mockImplementationOnce(() => version);
 | 
			
		||||
        getCommandOutputSpy.mockImplementationOnce(() => `foo${version}`);
 | 
			
		||||
 | 
			
		||||
        const dirs = await cacheUtils.getCacheDirectoriesPaths(
 | 
			
		||||
          supportedPackageManagers.yarn,
 | 
			
		||||
          ''
 | 
			
		||||
        );
 | 
			
		||||
        expect(dirs).toEqual([`foo${version}`]);
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    it.each(['1.1.1', '2.2.2'])(
 | 
			
		||||
      'getCacheDirectoriesPaths yarn v%s should return 2 dirs with globbed cacheDependency',
 | 
			
		||||
      async version => {
 | 
			
		||||
        let dirNo = 1;
 | 
			
		||||
        getCommandOutputSpy.mockImplementation((command: string) =>
 | 
			
		||||
          command.includes('version') ? version : `file_${version}_${dirNo++}`
 | 
			
		||||
        );
 | 
			
		||||
        globCreateSpy.mockImplementation(
 | 
			
		||||
          (pattern: string): Promise<Globber> =>
 | 
			
		||||
            MockGlobber.create(['/tmp/dir1/file', '/tmp/dir2/file'])
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        const dirs = await cacheUtils.getCacheDirectoriesPaths(
 | 
			
		||||
          supportedPackageManagers.yarn,
 | 
			
		||||
          '/tmp/**/file'
 | 
			
		||||
        );
 | 
			
		||||
        expect(dirs).toEqual([`file_${version}_1`, `file_${version}_2`]);
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // TODO: by design - glob is not expected to return duplicates so 3 patterns do not collapse to 2
 | 
			
		||||
    it.each(['1.1.1', '2.2.2'])(
 | 
			
		||||
      'getCacheDirectoriesPaths yarn v%s should return 3 dirs  with globbed cacheDependency expanding to duplicates',
 | 
			
		||||
      async version => {
 | 
			
		||||
        let dirNo = 1;
 | 
			
		||||
        getCommandOutputSpy.mockImplementation((command: string) =>
 | 
			
		||||
          command.includes('version') ? version : `file_${version}_${dirNo++}`
 | 
			
		||||
        );
 | 
			
		||||
        globCreateSpy.mockImplementation(
 | 
			
		||||
          (pattern: string): Promise<Globber> =>
 | 
			
		||||
            MockGlobber.create([
 | 
			
		||||
              '/tmp/dir1/file',
 | 
			
		||||
              '/tmp/dir2/file',
 | 
			
		||||
              '/tmp/dir1/file'
 | 
			
		||||
            ])
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        const dirs = await cacheUtils.getCacheDirectoriesPaths(
 | 
			
		||||
          supportedPackageManagers.yarn,
 | 
			
		||||
          '/tmp/**/file'
 | 
			
		||||
        );
 | 
			
		||||
        expect(dirs).toEqual([
 | 
			
		||||
          `file_${version}_1`,
 | 
			
		||||
          `file_${version}_2`,
 | 
			
		||||
          `file_${version}_3`
 | 
			
		||||
        ]);
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    it.each(['1.1.1', '2.2.2'])(
 | 
			
		||||
      'getCacheDirectoriesPaths yarn v%s should return 2 uniq dirs despite duplicate cache directories',
 | 
			
		||||
      async version => {
 | 
			
		||||
        let dirNo = 1;
 | 
			
		||||
        getCommandOutputSpy.mockImplementation((command: string) =>
 | 
			
		||||
          command.includes('version')
 | 
			
		||||
            ? version
 | 
			
		||||
            : `file_${version}_${dirNo++ % 2}`
 | 
			
		||||
        );
 | 
			
		||||
        globCreateSpy.mockImplementation(
 | 
			
		||||
          (pattern: string): Promise<Globber> =>
 | 
			
		||||
            MockGlobber.create([
 | 
			
		||||
              '/tmp/dir1/file',
 | 
			
		||||
              '/tmp/dir2/file',
 | 
			
		||||
              '/tmp/dir3/file'
 | 
			
		||||
            ])
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        const dirs = await cacheUtils.getCacheDirectoriesPaths(
 | 
			
		||||
          supportedPackageManagers.yarn,
 | 
			
		||||
          '/tmp/**/file'
 | 
			
		||||
        );
 | 
			
		||||
        expect(dirs).toEqual([`file_${version}_1`, `file_${version}_0`]);
 | 
			
		||||
        expect(getCommandOutputSpy).toHaveBeenCalledTimes(6);
 | 
			
		||||
        expect(getCommandOutputSpy).toHaveBeenCalledWith(
 | 
			
		||||
          'yarn --version',
 | 
			
		||||
          '/tmp/dir1'
 | 
			
		||||
        );
 | 
			
		||||
        expect(getCommandOutputSpy).toHaveBeenCalledWith(
 | 
			
		||||
          'yarn --version',
 | 
			
		||||
          '/tmp/dir2'
 | 
			
		||||
        );
 | 
			
		||||
        expect(getCommandOutputSpy).toHaveBeenCalledWith(
 | 
			
		||||
          'yarn --version',
 | 
			
		||||
          '/tmp/dir3'
 | 
			
		||||
        );
 | 
			
		||||
        expect(getCommandOutputSpy).toHaveBeenCalledWith(
 | 
			
		||||
          version.startsWith('1.')
 | 
			
		||||
            ? 'yarn cache dir'
 | 
			
		||||
            : 'yarn config get cacheFolder',
 | 
			
		||||
          '/tmp/dir1'
 | 
			
		||||
        );
 | 
			
		||||
        expect(getCommandOutputSpy).toHaveBeenCalledWith(
 | 
			
		||||
          version.startsWith('1.')
 | 
			
		||||
            ? 'yarn cache dir'
 | 
			
		||||
            : 'yarn config get cacheFolder',
 | 
			
		||||
          '/tmp/dir2'
 | 
			
		||||
        );
 | 
			
		||||
        expect(getCommandOutputSpy).toHaveBeenCalledWith(
 | 
			
		||||
          version.startsWith('1.')
 | 
			
		||||
            ? 'yarn cache dir'
 | 
			
		||||
            : 'yarn config get cacheFolder',
 | 
			
		||||
          '/tmp/dir3'
 | 
			
		||||
        );
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    it.each(['1.1.1', '2.2.2'])(
 | 
			
		||||
      'getCacheDirectoriesPaths yarn v%s should return 4 dirs with multiple globs',
 | 
			
		||||
      async version => {
 | 
			
		||||
        // simulate wrong indents
 | 
			
		||||
        const cacheDependencyPath = `/tmp/dir1/file
 | 
			
		||||
          /tmp/dir2/file
 | 
			
		||||
/tmp/**/file
 | 
			
		||||
          `;
 | 
			
		||||
        globCreateSpy.mockImplementation(
 | 
			
		||||
          (pattern: string): Promise<Globber> =>
 | 
			
		||||
            MockGlobber.create(['/tmp/dir3/file', '/tmp/dir4/file'])
 | 
			
		||||
        );
 | 
			
		||||
        let dirNo = 1;
 | 
			
		||||
        getCommandOutputSpy.mockImplementation((command: string) =>
 | 
			
		||||
          command.includes('version') ? version : `file_${version}_${dirNo++}`
 | 
			
		||||
        );
 | 
			
		||||
        const dirs = await cacheUtils.getCacheDirectoriesPaths(
 | 
			
		||||
          supportedPackageManagers.yarn,
 | 
			
		||||
          cacheDependencyPath
 | 
			
		||||
        );
 | 
			
		||||
        expect(dirs).toEqual([
 | 
			
		||||
          `file_${version}_1`,
 | 
			
		||||
          `file_${version}_2`,
 | 
			
		||||
          `file_${version}_3`,
 | 
			
		||||
          `file_${version}_4`
 | 
			
		||||
        ]);
 | 
			
		||||
      }
 | 
			
		||||
    );
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										18
									
								
								__tests__/mock/glob-mock.test.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								__tests__/mock/glob-mock.test.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
import {MockGlobber} from './glob-mock';
 | 
			
		||||
 | 
			
		||||
describe('mocked globber tests', () => {
 | 
			
		||||
  it('globber should return generator', async () => {
 | 
			
		||||
    const globber = new MockGlobber(['aaa', 'bbb', 'ccc']);
 | 
			
		||||
    const generator = globber.globGenerator();
 | 
			
		||||
    const result: string[] = [];
 | 
			
		||||
    for await (const itemPath of generator) {
 | 
			
		||||
      result.push(itemPath);
 | 
			
		||||
    }
 | 
			
		||||
    expect(result).toEqual(['aaa', 'bbb', 'ccc']);
 | 
			
		||||
  });
 | 
			
		||||
  it('globber should return glob', async () => {
 | 
			
		||||
    const globber = new MockGlobber(['aaa', 'bbb', 'ccc']);
 | 
			
		||||
    const result: string[] = await globber.glob();
 | 
			
		||||
    expect(result).toEqual(['aaa', 'bbb', 'ccc']);
 | 
			
		||||
  });
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										29
									
								
								__tests__/mock/glob-mock.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								__tests__/mock/glob-mock.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
			
		||||
import {Globber} from '@actions/glob';
 | 
			
		||||
 | 
			
		||||
export class MockGlobber implements Globber {
 | 
			
		||||
  private readonly expected: string[];
 | 
			
		||||
  constructor(expected: string[]) {
 | 
			
		||||
    this.expected = expected;
 | 
			
		||||
  }
 | 
			
		||||
  getSearchPaths(): string[] {
 | 
			
		||||
    return this.expected.slice();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async glob(): Promise<string[]> {
 | 
			
		||||
    const result: string[] = [];
 | 
			
		||||
    for await (const itemPath of this.globGenerator()) {
 | 
			
		||||
      result.push(itemPath);
 | 
			
		||||
    }
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async *globGenerator(): AsyncGenerator<string, void> {
 | 
			
		||||
    for (const e of this.expected) {
 | 
			
		||||
      yield e;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static async create(expected: string[]): Promise<MockGlobber> {
 | 
			
		||||
    return new MockGlobber(expected);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user