angular/aio/scripts/deploy-to-firebase/utils.spec.mjs
Derek Cormier 6948f0f0f3 build(bazel): fix AIO deployment script (#48188)
Don't run the script under Bazel, except for the tests. Configure a
Bazel flag to select the AIO build configuration.

PR Close #48188
2022-11-23 14:00:03 +00:00

299 lines
12 KiB
JavaScript

import fs from 'fs';
import sh from 'shelljs';
import u from './utils.mjs';
describe('deploy-to-firebase/utils:', () => {
beforeEach(() => {
// Clear the `getRemoteRefs()` cache before each test to prevent previous executions from
// affecting subsequent tests.
u._GIT_REMOTE_REFS_CACHE.clear();
});
describe('computeMajorVersion()', () => {
it('should extract the major version from a branch name', () => {
expect(u.computeMajorVersion('1.2.3')).toBe(1);
expect(u.computeMajorVersion('4.5.6-rc.7')).toBe(4);
expect(u.computeMajorVersion('89.0')).toBe(89);
});
});
describe('getDirname()', () => {
it('should return the directory path given a file URL', () => {
expect(u.getDirname(import.meta.url)).toMatch(/aio[\\/]scripts[\\/]deploy-to-firebase$/);
expect(u.getDirname('file:///C:/foo/bar/baz.ext'))
.toBe((process.platform === 'win32') ? 'C:\\foo\\bar' : '/C:/foo/bar');
});
});
describe('getLatestCommit()', () => {
let getRemoteRefsSpy;
beforeEach(() => {
getRemoteRefsSpy = spyOn(u, 'getRemoteRefs').and.returnValue([
'1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa40 refs/heads/3.0.x',
]);
});
it('should return the latest commit of a branch', () => {
expect(u.getLatestCommit('3.0.x')).toBe('1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa40');
expect(getRemoteRefsSpy).toHaveBeenCalledWith('3.0.x', undefined);
});
it('should pass any options to `getRemoteRefs()`', () => {
const opts = {custom: true};
expect(u.getLatestCommit('3.0.x', opts)).toBe('1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa40');
expect(getRemoteRefsSpy).toHaveBeenCalledWith('3.0.x', opts);
});
});
describe('getMostRecentMinorBranch()', () => {
let getRemoteRefsSpy;
beforeEach(() => {
const mockRefs3 = [
'1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa40 refs/heads/3.1.x',
'1ccccccccccccccccccccccccccccccccccccc40 refs/heads/3.3.x',
'1bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb40 refs/heads/3.2.x',
];
const mockRefs4 = [
'1ddddddddddddddddddddddddddddddddddddd40 refs/heads/4.5.x',
'1eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee40 refs/heads/4.6.x',
];
const mockRefsAll = [
...mockRefs3,
...mockRefs4,
'1fffffffffffffffffffffffffffffffffffff40 refs/heads/5.0.x',
];
getRemoteRefsSpy = spyOn(u, 'getRemoteRefs')
.withArgs('refs/heads/3.*.x', undefined).and.returnValue(mockRefs3)
.withArgs('refs/heads/3.*.x', jasmine.anything()).and.returnValue(mockRefs3)
.withArgs('refs/heads/4.*.x', undefined).and.returnValue(mockRefs4)
.withArgs('refs/heads/4.*.x', jasmine.anything()).and.returnValue(mockRefs4)
.withArgs('refs/heads/*.*.x', undefined).and.returnValue(mockRefsAll)
.withArgs('refs/heads/*.*.x', jasmine.anything()).and.returnValue(mockRefsAll);
});
it('should get all minor branches for the specified major version', () => {
u.getMostRecentMinorBranch('3');
expect(getRemoteRefsSpy).toHaveBeenCalledWith('refs/heads/3.*.x', undefined);
u.getMostRecentMinorBranch('4');
expect(getRemoteRefsSpy).toHaveBeenCalledWith('refs/heads/4.*.x', undefined);
});
it('should get all minor branches when no major version is specified', () => {
u.getMostRecentMinorBranch();
expect(getRemoteRefsSpy).toHaveBeenCalledWith('refs/heads/*.*.x', undefined);
u.getMostRecentMinorBranch(undefined);
expect(getRemoteRefsSpy).toHaveBeenCalledWith('refs/heads/*.*.x', undefined);
});
it('should pass any options to `getRemoteRefs()`', () => {
u.getMostRecentMinorBranch();
expect(getRemoteRefsSpy).toHaveBeenCalledWith('refs/heads/*.*.x', undefined);
u.getMostRecentMinorBranch('3');
expect(getRemoteRefsSpy).toHaveBeenCalledWith('refs/heads/3.*.x', undefined);
u.getMostRecentMinorBranch(undefined, {custom: 1});
expect(getRemoteRefsSpy).toHaveBeenCalledWith('refs/heads/*.*.x', {custom: 1});
u.getMostRecentMinorBranch('4', {custom: 2});
expect(getRemoteRefsSpy).toHaveBeenCalledWith('refs/heads/4.*.x', {custom: 2});
});
it('should return the most recent branch', () => {
expect(u.getMostRecentMinorBranch('3')).toBe('3.3.x');
expect(u.getMostRecentMinorBranch('4')).toBe('4.6.x');
expect(u.getMostRecentMinorBranch()).toBe('5.0.x');
});
it('should ignore branches that do not match the expected pattern', () => {
getRemoteRefsSpy.withArgs('refs/heads/*.*.x', undefined).and.returnValue([
'1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa40 refs/heads/6.0.x',
'1bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb40 refs/heads/6.1.x',
'1ccccccccccccccccccccccccccccccccccccc40 refs/heads/6.2.z',
'1ddddddddddddddddddddddddddddddddddddd40 refs/heads/7.3.x-rc.0',
]);
expect(u.getMostRecentMinorBranch()).toBe('6.1.x');
});
});
describe('getRemoteRefs()', () => {
let execSpy;
beforeEach(() => {
execSpy = spyOn(sh, 'exec').and.callFake(() => ([
' ',
'1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa40 refs/heads/3.1.x',
'1ccccccccccccccccccccccccccccccccccccc40 refs/heads/3.3.x',
'1bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb40 refs/heads/3.2.x',
'1ddddddddddddddddddddddddddddddddddddd40 refs/heads/4.5.x',
'1eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee40 refs/heads/4.6.x',
'1fffffffffffffffffffffffffffffffffffff40 refs/heads/5.0.x',
' ',
].join('\n')));
});
it('should retrieve the remote refs based on the speficied pattern/remote', () => {
u.getRemoteRefs('some-pattern', {remote: 'https://example.com/repo.git'});
expect(execSpy).toHaveBeenCalledWith(
'git ls-remote https://example.com/repo.git some-pattern', jasmine.anything());
});
it('should use the `angular/angular` repo if not remote is specified', () => {
u.getRemoteRefs('some-pattern');
expect(execSpy).toHaveBeenCalledWith(
`git ls-remote ${u.NG_REMOTE_URL} some-pattern`, jasmine.anything());
u.getRemoteRefs('other-pattern', {other: 'option'});
expect(execSpy).toHaveBeenCalledWith(
`git ls-remote ${u.NG_REMOTE_URL} other-pattern`, jasmine.anything());
});
it('should run the git command in silent mode', () => {
u.getRemoteRefs('some-pattern');
expect(execSpy).toHaveBeenCalledWith(jasmine.any(String), {silent: true});
});
it('should return a list of refs', () => {
expect(u.getRemoteRefs('some-pattern')).toEqual([
'1aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa40 refs/heads/3.1.x',
'1ccccccccccccccccccccccccccccccccccccc40 refs/heads/3.3.x',
'1bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb40 refs/heads/3.2.x',
'1ddddddddddddddddddddddddddddddddddddd40 refs/heads/4.5.x',
'1eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee40 refs/heads/4.6.x',
'1fffffffffffffffffffffffffffffffffffff40 refs/heads/5.0.x',
]);
});
it('should retrieve results from the cache (if available)', () => {
// Initially, retrieve results by executing the command.
const results1 = u.getRemoteRefs('some-pattern');
expect(execSpy).toHaveBeenCalledTimes(1);
// On subsequent calls with the same command, retrieve results from the cache.
expect(u.getRemoteRefs('some-pattern')).toBe(results1);
expect(u.getRemoteRefs('some-pattern', {remote: u.NG_REMOTE_URL})).toBe(results1);
expect(execSpy).toHaveBeenCalledTimes(1);
// Retrieve results for different command (different remote) by executing the command.
const results2 = u.getRemoteRefs('some-pattern', {remote: 'other-remote'});
expect(results2).not.toBe(results1);
expect(execSpy).toHaveBeenCalledTimes(2);
// Retrieve results for different command (different pattern) by executing the command.
const results3 = u.getRemoteRefs('other-pattern');
expect(results3).not.toBe(results1);
expect(results3).not.toBe(results2);
expect(execSpy).toHaveBeenCalledTimes(3);
// Retrieve results from the cache once available.
expect(u.getRemoteRefs('other-pattern', {remote: u.NG_REMOTE_URL})).toBe(results3);
expect(execSpy).toHaveBeenCalledTimes(3);
});
it('should not retrieve results from the cache with `retrieveFromCache: false`', () => {
// Initial call to retrieve and cache the results.
const results1 = u.getRemoteRefs('some-pattern');
expect(execSpy).toHaveBeenCalledTimes(1);
// Do not use cached results with `retrieveFromCache: false`.
const results2 = u.getRemoteRefs('some-pattern', {retrieveFromCache: false});
expect(results2).not.toBe(results1);
expect(execSpy).toHaveBeenCalledTimes(2);
const results3 = u.getRemoteRefs(
'some-pattern', {remote: u.NG_REMOTE_URL, retrieveFromCache: false});
expect(results3).not.toBe(results1);
expect(results3).not.toBe(results2);
expect(execSpy).toHaveBeenCalledTimes(3);
});
it('should cache the results for future use even with `retrieveFromCache: false`', () => {
// Initial call with `retrieveFromCache: false` (should still cache the results).
const results = u.getRemoteRefs('some-pattern', {retrieveFromCache: false});
expect(execSpy).toHaveBeenCalledTimes(1);
// Subsequent call uses the cached results.
expect(u.getRemoteRefs('some-pattern')).toBe(results);
expect(u.getRemoteRefs('some-pattern', {other: 'option'})).toBe(results);
expect(u.getRemoteRefs('some-pattern', {retrieveFromCache: true})).toBe(results);
expect(execSpy).toHaveBeenCalledTimes(1);
});
});
describe('loadJson()', () => {
let readFileSyncSpy;
beforeEach(() => readFileSyncSpy = spyOn(fs, 'readFileSync'));
it('should load and parse a JSON file', () => {
readFileSyncSpy.withArgs('/foo/bar.json', 'utf8').and.returnValue('{"foo": "bar"}');
expect(u.loadJson('/foo/bar.json')).toEqual({foo: 'bar'});
});
});
describe('logSectionHeader()', () => {
let logSpy;
beforeEach(() => logSpy = spyOn(console, 'log'));
it('should log a section header', () => {
u.logSectionHeader('Foo header');
expect(logSpy).toHaveBeenCalledWith('\n\n\n==== Foo header ====\n');
});
});
describe('nameFunction()', () => {
it('should overwrite a function\'s name', () => {
function foo() {}
const bar = () => {};
const baz = ({baz() {}}).baz;
expect(foo.name).toBe('foo');
expect(bar.name).toBe('bar');
expect(baz.name).toBe('baz');
u.nameFunction('foo2', foo);
u.nameFunction('bar2', bar);
u.nameFunction('baz2', baz);
expect(foo.name).toBe('foo2');
expect(bar.name).toBe('bar2');
expect(baz.name).toBe('baz2');
});
it('should return the function', () => {
function foo() {}
const bar = () => {};
const baz = ({baz() {}}).baz;
expect(u.nameFunction('foo2', foo)).toBe(foo);
expect(u.nameFunction('bar2', bar)).toBe(bar);
expect(u.nameFunction('baz2', baz)).toBe(baz);
});
});
describe('yarn()', () => {
let execSpy;
beforeEach(() => execSpy = spyOn(sh, 'exec'));
it('should execute yarn in silent mode', () => {
u.yarn('foo --bar');
const cmd = execSpy.calls.argsFor(0)[0];
expect(cmd.endsWith('--silent foo --bar')).toEqual(true);
});
it('should return the output from the command\'s execution', () => {
execSpy.and.returnValue('command output\n');
expect(u.yarn('foo --bar')).toBe('command output\n');
});
});
});