ci(aio): use custom package.json to run with local distributables (#19511)
Closes #19388 PR Close #19511
This commit is contained in:
parent
9fe6363575
commit
d1a00459a8
|
@ -4,14 +4,11 @@ const path = require('canonical-path');
|
|||
const shelljs = require('shelljs');
|
||||
const yargs = require('yargs');
|
||||
|
||||
const ngPackagesInstaller = require('../ng-packages-installer');
|
||||
|
||||
const SHARED_PATH = path.resolve(__dirname, 'shared');
|
||||
const SHARED_NODE_MODULES_PATH = path.resolve(SHARED_PATH, 'node_modules');
|
||||
const BOILERPLATE_BASE_PATH = path.resolve(SHARED_PATH, 'boilerplate');
|
||||
const BOILERPLATE_COMMON_BASE_PATH = path.resolve(BOILERPLATE_BASE_PATH, 'common');
|
||||
const EXAMPLES_BASE_PATH = path.resolve(__dirname, '../../content/examples');
|
||||
const TESTING_BASE_PATH = path.resolve(EXAMPLES_BASE_PATH, 'testing');
|
||||
|
||||
const BOILERPLATE_PATHS = {
|
||||
cli: [
|
||||
|
@ -99,13 +96,9 @@ class ExampleBoilerPlate {
|
|||
}
|
||||
|
||||
installNodeModules(basePath, useLocal) {
|
||||
shelljs.exec('yarn', {cwd: basePath});
|
||||
|
||||
if (useLocal) {
|
||||
ngPackagesInstaller.overwritePackages(basePath);
|
||||
} else {
|
||||
ngPackagesInstaller.restorePackages(basePath);
|
||||
}
|
||||
const tool = 'node tools/ng-packages-installer';
|
||||
const command = useLocal ? 'overwrite' : 'restore';
|
||||
shelljs.exec([tool, command, basePath, '--debug'].join(' '));
|
||||
}
|
||||
|
||||
getFoldersContaining(basePath, filename, ignore) {
|
||||
|
|
|
@ -3,7 +3,6 @@ const fs = require('fs-extra');
|
|||
const glob = require('glob');
|
||||
const shelljs = require('shelljs');
|
||||
|
||||
const ngPackagesInstaller = require('../ng-packages-installer');
|
||||
const exampleBoilerPlate = require('./example-boilerplate');
|
||||
|
||||
describe('example-boilerplate tool', () => {
|
||||
|
@ -99,31 +98,22 @@ describe('example-boilerplate tool', () => {
|
|||
describe('installNodeModules', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(shelljs, 'exec');
|
||||
spyOn(ngPackagesInstaller, 'overwritePackages');
|
||||
spyOn(ngPackagesInstaller, 'restorePackages');
|
||||
});
|
||||
|
||||
it('should run `yarn` in the base path', () => {
|
||||
exampleBoilerPlate.installNodeModules('some/base/path');
|
||||
expect(shelljs.exec).toHaveBeenCalledWith('yarn', { cwd: 'some/base/path' });
|
||||
});
|
||||
|
||||
it('should overwrite the Angular packages if `useLocal` is true', () => {
|
||||
ngPackagesInstaller.overwritePackages.and.callFake(() => expect(shelljs.exec).toHaveBeenCalled());
|
||||
|
||||
exampleBoilerPlate.installNodeModules('some/base/path', true);
|
||||
expect(ngPackagesInstaller.overwritePackages).toHaveBeenCalledWith('some/base/path');
|
||||
expect(ngPackagesInstaller.restorePackages).not.toHaveBeenCalled();
|
||||
expect(shelljs.exec).toHaveBeenCalledWith('node tools/ng-packages-installer overwrite some/base/path --debug');
|
||||
expect(shelljs.exec.calls.count()).toEqual(1);
|
||||
});
|
||||
|
||||
it('should restore the Angular packages if `useLocal` is not true', () => {
|
||||
exampleBoilerPlate.installNodeModules('some/base/path1');
|
||||
expect(ngPackagesInstaller.restorePackages).toHaveBeenCalledWith('some/base/path1');
|
||||
expect(shelljs.exec).toHaveBeenCalledWith('node tools/ng-packages-installer restore some/base/path1 --debug');
|
||||
|
||||
exampleBoilerPlate.installNodeModules('some/base/path2', false);
|
||||
expect(ngPackagesInstaller.restorePackages).toHaveBeenCalledWith('some/base/path2');
|
||||
expect(shelljs.exec).toHaveBeenCalledWith('node tools/ng-packages-installer restore some/base/path2 --debug');
|
||||
|
||||
expect(ngPackagesInstaller.overwritePackages).not.toHaveBeenCalled();
|
||||
expect(shelljs.exec.calls.count()).toEqual(2);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -1,235 +0,0 @@
|
|||
#!/bin/env node
|
||||
'use strict';
|
||||
|
||||
// Imports
|
||||
const chalk = require('chalk');
|
||||
const fs = require('fs-extra');
|
||||
const path = require('canonical-path');
|
||||
const shelljs = require('shelljs');
|
||||
const yargs = require('yargs');
|
||||
|
||||
// Config
|
||||
shelljs.set('-e');
|
||||
|
||||
// Constants
|
||||
const ROOT_DIR = path.resolve(__dirname, '../..');
|
||||
const PACKAGES_DIR = path.join(ROOT_DIR, 'packages');
|
||||
const PACKAGES_DIST_DIR = path.join(ROOT_DIR, 'dist/packages-dist');
|
||||
const NG_LOCAL_FILENAME = '.ng-local';
|
||||
|
||||
// Classes
|
||||
class NgPackagesInstaller {
|
||||
constructor() {
|
||||
// Properties - Protected
|
||||
|
||||
/**
|
||||
* A sorted list of Angular package names.
|
||||
* (Detected as directories in '/packages/' that contain a top-level 'package.json' file.)
|
||||
*/
|
||||
this.ngPackages = shelljs.
|
||||
find(PACKAGES_DIR).
|
||||
map(path => path.slice(PACKAGES_DIR.length + 1)).
|
||||
filter(path => /^[^/]+\/package.json$/.test(path)).
|
||||
map(path => path.slice(0, -13)).
|
||||
sort();
|
||||
}
|
||||
|
||||
// Methods - Public
|
||||
|
||||
/**
|
||||
* Check whether the Angular packages installed in the specified `rootDir`'s 'node_modules/' come from npm and print a
|
||||
* warning if not.
|
||||
* @param {string} rootDir - The root directory whose npm dependencies will be checked.
|
||||
*/
|
||||
checkPackages(rootDir) {
|
||||
rootDir = path.resolve(rootDir);
|
||||
const localPackages = this._findLocalPackages(rootDir);
|
||||
|
||||
if (localPackages.length) {
|
||||
const relativeScriptPath = path.relative('.', __filename.replace(/\.js$/, ''));
|
||||
const relativeRootDir = path.relative('.', rootDir) || '.';
|
||||
const restoreCmd = `node ${relativeScriptPath} restore ${relativeRootDir}`;
|
||||
|
||||
// Log a warning.
|
||||
console.warn(chalk.yellow([
|
||||
'',
|
||||
'!'.repeat(110),
|
||||
'!!!',
|
||||
'!!! WARNING',
|
||||
'!!!',
|
||||
`!!! The following packages have been overwritten in '${rootDir}/node_modules/' with the locally built ones:`,
|
||||
'!!!',
|
||||
...localPackages.map(pkg => `!!! - @angular/${pkg}`),
|
||||
'!!!',
|
||||
'!!! To restore the packages run:',
|
||||
'!!!',
|
||||
`!!! ${restoreCmd}`,
|
||||
'!!!',
|
||||
'!'.repeat(110),
|
||||
'',
|
||||
].join('\n')));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrite the Angular packages installed in the specified `rootDir`'s 'node_modules/' with the locally built ones.
|
||||
* @param {string} rootDir - The root directory whose npm dependencies will be overwritten.
|
||||
*/
|
||||
overwritePackages(rootDir) {
|
||||
rootDir = path.resolve(rootDir);
|
||||
const nodeModulesDir = path.join(rootDir, 'node_modules');
|
||||
|
||||
this.ngPackages.forEach(packageName => this._overwritePackage(packageName, nodeModulesDir));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the Angular packages installed in the specified `rootDir`'s 'node_modules/' come from npm.
|
||||
* (If necessary, re-install the Angular packages using `yarn`.)
|
||||
* @param {string} rootDir - The root directory whose npm dependencies will be restored.
|
||||
*/
|
||||
restorePackages(rootDir) {
|
||||
rootDir = path.resolve(rootDir);
|
||||
const localPackages = this._findLocalPackages(rootDir);
|
||||
|
||||
if (localPackages.length) {
|
||||
this._reinstallOverwrittenNodeModules(rootDir);
|
||||
}
|
||||
}
|
||||
|
||||
// Methods - Protected
|
||||
|
||||
/**
|
||||
* Find and return all Angular packages installed in the specified `rootDir`'s 'node_modules/' that have been
|
||||
* overwritten with the locally built ones.
|
||||
* @param {string} rootDir - The root directory whose npm dependencies will be checked.
|
||||
* @return {string[]} - A list of overwritten package names.
|
||||
*/
|
||||
_findLocalPackages(rootDir) {
|
||||
const nodeModulesDir = path.join(rootDir, 'node_modules');
|
||||
const localPackages = this.ngPackages.filter(packageName => this._isLocalPackage(packageName, nodeModulesDir));
|
||||
|
||||
this._log(`Local packages found: ${localPackages.join(', ') || '-'}`);
|
||||
|
||||
return localPackages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether an installed Angular package from `nodeModulesDir` has been overwritten with a
|
||||
* locally built package.
|
||||
* @param {string} packageName - The name of the package to check.
|
||||
* @param {string} nodeModulesDir - The target `node_modules/` directory.
|
||||
* @return {boolean} - True if the package has been overwritten or false otherwise.
|
||||
*/
|
||||
_isLocalPackage(packageName, nodeModulesDir) {
|
||||
const targetPackageDir = path.join(nodeModulesDir, '@angular', packageName);
|
||||
const localFlagFile = path.join(targetPackageDir, NG_LOCAL_FILENAME);
|
||||
const isLocal = fs.existsSync(localFlagFile);
|
||||
|
||||
this._log(`Checking package '${packageName}' (${targetPackageDir})... local: ${isLocal}`);
|
||||
|
||||
return isLocal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a message if the `debug` property is set to true.
|
||||
* @param {string} message - The message to be logged.
|
||||
*/
|
||||
_log(message) {
|
||||
if (this.debug) {
|
||||
const indent = ' ';
|
||||
console.info(`${indent}[${NgPackagesInstaller.name}]: ${message.split('\n').join(`\n${indent}`)}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse and validate the input and invoke the appropriate command.
|
||||
*/
|
||||
_main() {
|
||||
const preCommand = argv => {
|
||||
this.debug = argv.debug;
|
||||
|
||||
const availablePackages = this.ngPackages.map(pkg => `\n - @angular/${pkg}`).join('') || '-';
|
||||
this._log(`Available Angular packages: ${availablePackages}`);
|
||||
};
|
||||
|
||||
yargs.
|
||||
usage('$0 <cmd> <args>').
|
||||
command(
|
||||
'check <projectDir> [--debug]',
|
||||
'Check whether the Angular packages installed as dependencies of `projectDir` come from npm and print a ' +
|
||||
'warning if not.',
|
||||
{
|
||||
debug: {describe: 'Print debug information.'}
|
||||
},
|
||||
argv => {
|
||||
preCommand(argv);
|
||||
this.checkPackages(argv.projectDir);
|
||||
}).
|
||||
command(
|
||||
'overwrite <projectDir> [--debug]',
|
||||
'Overwrite the Angular packages installed as dependencies of `projectDir` with the locally built ones.',
|
||||
{
|
||||
debug: {describe: 'Print debug information.'}
|
||||
},
|
||||
argv => {
|
||||
preCommand(argv);
|
||||
this.overwritePackages(argv.projectDir);
|
||||
}).
|
||||
command(
|
||||
'restore <projectDir> [--debug]',
|
||||
'Ensure that the Angular packages installed as dependencies of `projectDir` come from npm.',
|
||||
{
|
||||
debug: {describe: 'Print debug information.'}
|
||||
},
|
||||
argv => {
|
||||
preCommand(argv);
|
||||
this.restorePackages(argv.projectDir);
|
||||
}).
|
||||
demandCommand(1, 'Please supply a command from the list above.').
|
||||
strict().
|
||||
argv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an installed Angular package from `nodeModulesDir` and replace it with the locally built
|
||||
* one. Mark the package by adding an `.ng-local` file in the target directory.
|
||||
* @param {string} packageName - The name of the package to overwrite.
|
||||
* @param {string} nodeModulesDir - The target `node_modules/` directory.
|
||||
*/
|
||||
_overwritePackage(packageName, nodeModulesDir) {
|
||||
const sourcePackageDir = path.join(PACKAGES_DIST_DIR, packageName);
|
||||
const targetPackageDir = path.join(nodeModulesDir, '@angular', packageName);
|
||||
const localFlagFile = path.join(targetPackageDir, NG_LOCAL_FILENAME);
|
||||
|
||||
this._log(`Overwriting package '${packageName}' (${sourcePackageDir} --> ${targetPackageDir})...`);
|
||||
|
||||
if (fs.existsSync(targetPackageDir)) {
|
||||
shelljs.rm('-rf', targetPackageDir);
|
||||
fs.copySync(sourcePackageDir, targetPackageDir);
|
||||
fs.writeFileSync(localFlagFile, '');
|
||||
} else {
|
||||
this._log(' Nothing to overwrite - the package is not installed...');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Re-install overwritten npm dependencies using `yarn`. Removes the `.yarn-integrity` file to ensure `yarn` detects
|
||||
* the overwritten packages.
|
||||
* @param {string} rootDir - The root directory whose npm dependencies will be re-installed.
|
||||
*/
|
||||
_reinstallOverwrittenNodeModules(rootDir) {
|
||||
const installCmd = 'yarn install --check-files';
|
||||
|
||||
this._log(`Running '${installCmd}' in '${rootDir}'...`);
|
||||
shelljs.exec(installCmd, {cwd: rootDir});
|
||||
}
|
||||
}
|
||||
|
||||
// Exports
|
||||
module.exports = new NgPackagesInstaller();
|
||||
|
||||
// Run
|
||||
if (require.main === module) {
|
||||
// This file was run directly; run the main function.
|
||||
module.exports._main();
|
||||
}
|
|
@ -1,286 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
const fs = require('fs-extra');
|
||||
const path = require('canonical-path');
|
||||
const shelljs = require('shelljs');
|
||||
|
||||
const installer = require('./ng-packages-installer');
|
||||
|
||||
describe('NgPackagesInstaller', () => {
|
||||
const ngPackages = installer.ngPackages;
|
||||
const rootDir = 'root/dir';
|
||||
const absoluteRootDir = path.resolve(rootDir);
|
||||
const nodeModulesDir = `${absoluteRootDir}/node_modules`;
|
||||
|
||||
beforeEach(() => {
|
||||
spyOn(fs, 'copySync');
|
||||
spyOn(fs, 'existsSync');
|
||||
spyOn(fs, 'writeFileSync');
|
||||
spyOn(shelljs, 'exec');
|
||||
spyOn(shelljs, 'rm');
|
||||
});
|
||||
|
||||
// Properties
|
||||
|
||||
describe('.ngPackages', () => {
|
||||
it('should include all package names', () => {
|
||||
// For example...
|
||||
expect(installer.ngPackages).toContain('common');
|
||||
expect(installer.ngPackages).toContain('core');
|
||||
expect(installer.ngPackages).toContain('router');
|
||||
expect(installer.ngPackages).toContain('upgrade');
|
||||
|
||||
expect(installer.ngPackages).not.toContain('static');
|
||||
expect(installer.ngPackages).not.toContain('upgrade/static');
|
||||
});
|
||||
|
||||
it('should correspond to package directories with top-level \'package.json\' files', () => {
|
||||
fs.existsSync.and.callThrough();
|
||||
|
||||
const packagesDir = path.resolve(__dirname, '../../packages');
|
||||
|
||||
installer.ngPackages.forEach(packageName => {
|
||||
const packageJson = `${packagesDir}/${packageName}/package.json`;
|
||||
expect(fs.existsSync(packageJson)).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Methods
|
||||
|
||||
describe('checkPackages()', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(console, 'warn');
|
||||
spyOn(installer, '_findLocalPackages');
|
||||
});
|
||||
|
||||
it('should check whether there are any local Angular packages in the target directory', () => {
|
||||
installer._findLocalPackages.and.returnValue([]);
|
||||
|
||||
installer.checkPackages(rootDir);
|
||||
expect(installer._findLocalPackages).toHaveBeenCalledWith(absoluteRootDir);
|
||||
});
|
||||
|
||||
it('should not print a warning if all Angular packages come from npm', () => {
|
||||
installer._findLocalPackages.and.returnValue([]);
|
||||
|
||||
installer.checkPackages(rootDir);
|
||||
expect(console.warn).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('when there are local Angular packages', () => {
|
||||
beforeEach(() => {
|
||||
installer._findLocalPackages.and.returnValue(['common', 'router']);
|
||||
});
|
||||
|
||||
it('should print a warning', () => {
|
||||
installer.checkPackages(rootDir);
|
||||
|
||||
expect(console.warn).toHaveBeenCalled();
|
||||
expect(console.warn.calls.mostRecent().args[0]).toContain('WARNING');
|
||||
});
|
||||
|
||||
it('should list the local (i.e. overwritten) packages', () => {
|
||||
installer.checkPackages(rootDir);
|
||||
|
||||
const warning = console.warn.calls.mostRecent().args[0];
|
||||
expect(warning).toContain('@angular/common');
|
||||
expect(warning).toContain('@angular/router');
|
||||
expect(warning).not.toContain('@angular/core');
|
||||
expect(warning).not.toContain('@angular/upgrade');
|
||||
});
|
||||
|
||||
it('should mention the command to restore the Angular packages', () => {
|
||||
// When run for the current working directory...
|
||||
const dir1 = '.';
|
||||
const restoreCmdRe1 = RegExp('\\bnode .*?ng-packages-installer restore \\.');
|
||||
|
||||
installer.checkPackages(dir1);
|
||||
|
||||
expect(console.warn.calls.argsFor(0)[0]).toMatch(restoreCmdRe1);
|
||||
|
||||
// When run for a different directory...
|
||||
const dir2 = rootDir;
|
||||
const restoreCmdRe2 = RegExp(`\\bnode .*?ng-packages-installer restore .*?${path.normalize(rootDir)}\\b`);
|
||||
|
||||
installer.checkPackages(dir2);
|
||||
|
||||
expect(console.warn.calls.argsFor(1)[0]).toMatch(restoreCmdRe2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('overwritePackages()', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(installer, '_overwritePackage');
|
||||
});
|
||||
|
||||
it('should override the Angular packages in the target directory with the locally built ones', () => {
|
||||
installer.overwritePackages(rootDir);
|
||||
expect(installer._overwritePackage).toHaveBeenCalledTimes(ngPackages.length);
|
||||
|
||||
ngPackages.forEach(packageName =>
|
||||
expect(installer._overwritePackage).toHaveBeenCalledWith(packageName, nodeModulesDir));
|
||||
});
|
||||
});
|
||||
|
||||
describe('restorePackages()', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(installer, '_findLocalPackages');
|
||||
spyOn(installer, '_reinstallOverwrittenNodeModules');
|
||||
});
|
||||
|
||||
it('should check whether there are any local Angular packages in the target directory first', () => {
|
||||
installer._findLocalPackages.and.callFake(() => {
|
||||
expect(installer._reinstallOverwrittenNodeModules).not.toHaveBeenCalled();
|
||||
return [];
|
||||
});
|
||||
|
||||
installer.restorePackages(rootDir);
|
||||
expect(installer._findLocalPackages).toHaveBeenCalledWith(absoluteRootDir);
|
||||
});
|
||||
|
||||
it('should re-install dependencies from npm afterwards (if necessary)', () => {
|
||||
// No local packages.
|
||||
installer._findLocalPackages.and.returnValue([]);
|
||||
|
||||
installer.restorePackages(rootDir);
|
||||
expect(installer._reinstallOverwrittenNodeModules).not.toHaveBeenCalled();
|
||||
|
||||
// All local packages.
|
||||
installer._reinstallOverwrittenNodeModules.calls.reset();
|
||||
installer._findLocalPackages.and.returnValue(ngPackages);
|
||||
|
||||
installer.restorePackages(rootDir);
|
||||
expect(installer._reinstallOverwrittenNodeModules).toHaveBeenCalledWith(absoluteRootDir);
|
||||
|
||||
// Some local packages.
|
||||
installer._reinstallOverwrittenNodeModules.calls.reset();
|
||||
installer._findLocalPackages.and.returnValue(['common', 'core', 'router', 'upgrade']);
|
||||
|
||||
installer.restorePackages(rootDir);
|
||||
expect(installer._reinstallOverwrittenNodeModules).toHaveBeenCalledWith(absoluteRootDir);
|
||||
});
|
||||
});
|
||||
|
||||
describe('_findLocalPackages()', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(installer, '_isLocalPackage');
|
||||
});
|
||||
|
||||
it('should check all Angular packages', () => {
|
||||
installer._findLocalPackages(absoluteRootDir);
|
||||
|
||||
ngPackages.forEach(packageName =>
|
||||
expect(installer._isLocalPackage).toHaveBeenCalledWith(packageName, nodeModulesDir));
|
||||
});
|
||||
|
||||
it('should return an empty list if all Angular packages come from npm', () => {
|
||||
installer._isLocalPackage.and.returnValue(false);
|
||||
expect(installer._findLocalPackages(rootDir)).toEqual([]);
|
||||
});
|
||||
|
||||
it('should return a list of all local (i.e. overwritten) Angular packages', () => {
|
||||
const localPackages = ['common', 'core', 'router', 'upgrade'];
|
||||
|
||||
installer._isLocalPackage.and.callFake(packageName => localPackages.includes(packageName));
|
||||
|
||||
expect(installer._findLocalPackages(rootDir)).toEqual(localPackages);
|
||||
});
|
||||
});
|
||||
|
||||
describe('_isLocalPackage()', () => {
|
||||
it('should check whether the specified package is local/overwritten', () => {
|
||||
const targetPackageDir = `${rootDir}/@angular/somePackage`;
|
||||
const localFlagFile = `${targetPackageDir}/.ng-local`;
|
||||
|
||||
installer._isLocalPackage('somePackage', rootDir);
|
||||
expect(fs.existsSync).toHaveBeenCalledWith(localFlagFile);
|
||||
});
|
||||
|
||||
it('should return whether the specified package was local', () => {
|
||||
fs.existsSync.and.returnValues(true, false);
|
||||
|
||||
expect(installer._isLocalPackage('somePackage', rootDir)).toBe(true);
|
||||
expect(installer._isLocalPackage('somePackage', rootDir)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('_log()', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(console, 'info');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
installer.debug = false;
|
||||
});
|
||||
|
||||
it('should log a message to the console if the `debug` property is true', () => {
|
||||
installer._log('foo');
|
||||
expect(console.info).not.toHaveBeenCalled();
|
||||
|
||||
installer.debug = true;
|
||||
installer._log('bar');
|
||||
expect(console.info).toHaveBeenCalledWith(' [NgPackagesInstaller]: bar');
|
||||
});
|
||||
});
|
||||
|
||||
describe('_overwritePackage()', () => {
|
||||
beforeEach(() => {
|
||||
fs.existsSync.and.returnValue(true);
|
||||
});
|
||||
|
||||
it('should check whether the Angular package is installed', () => {
|
||||
const targetPackageDir = `${rootDir}/@angular/somePackage`;
|
||||
|
||||
installer._overwritePackage('somePackage', rootDir);
|
||||
expect(fs.existsSync).toHaveBeenCalledWith(targetPackageDir);
|
||||
});
|
||||
|
||||
it('should remove the original package from the target directory', () => {
|
||||
const targetPackageDir = `${rootDir}/@angular/somePackage`;
|
||||
|
||||
shelljs.rm.and.callFake(() => expect(fs.existsSync).toHaveBeenCalled());
|
||||
|
||||
installer._overwritePackage('somePackage', rootDir);
|
||||
expect(shelljs.rm).toHaveBeenCalledWith('-rf', targetPackageDir);
|
||||
});
|
||||
|
||||
it('should copy the source package directory to the target directory', () => {
|
||||
const sourcePackageDir = path.resolve(__dirname, '../../dist/packages-dist/somePackage');
|
||||
const targetPackageDir = `${rootDir}/@angular/somePackage`;
|
||||
|
||||
fs.copySync.and.callFake(() => expect(shelljs.rm).toHaveBeenCalled());
|
||||
|
||||
installer._overwritePackage('somePackage', rootDir);
|
||||
expect(fs.copySync).toHaveBeenCalledWith(sourcePackageDir, targetPackageDir);
|
||||
});
|
||||
|
||||
it('should add an empty `.ng-local` file to the target directory', () => {
|
||||
const targetPackageDir = `${rootDir}/@angular/somePackage`;
|
||||
const localFlagFile = `${targetPackageDir}/.ng-local`;
|
||||
|
||||
fs.writeFileSync.and.callFake(() => expect(fs.copySync).toHaveBeenCalled());
|
||||
|
||||
installer._overwritePackage('somePackage', rootDir);
|
||||
expect(fs.writeFileSync).toHaveBeenCalledWith(localFlagFile, '');
|
||||
});
|
||||
|
||||
it('should do nothing if the Angular package is not installed', () => {
|
||||
fs.existsSync.and.returnValue(false);
|
||||
|
||||
installer._overwritePackage('somePackage', rootDir);
|
||||
|
||||
expect(shelljs.rm).not.toHaveBeenCalled();
|
||||
expect(fs.copySync).not.toHaveBeenCalled();
|
||||
expect(fs.writeFileSync).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('_reinstallOverwrittenNodeModules()', () => {
|
||||
it('should run `yarn install --check-files` in the specified directory', () => {
|
||||
installer._reinstallOverwrittenNodeModules(rootDir);
|
||||
expect(shelljs.exec).toHaveBeenCalledWith('yarn install --check-files', {cwd: rootDir});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,241 @@
|
|||
'use strict';
|
||||
|
||||
const chalk = require('chalk');
|
||||
const fs = require('fs-extra');
|
||||
const path = require('canonical-path');
|
||||
const shelljs = require('shelljs');
|
||||
const yargs = require('yargs');
|
||||
|
||||
const PACKAGE_JSON = 'package.json';
|
||||
const LOCKFILE = 'yarn.lock';
|
||||
const LOCAL_MARKER_PATH = 'node_modules/_local_.json';
|
||||
const PACKAGE_JSON_REGEX = /^[^/]+\/package\.json$/;
|
||||
|
||||
const ANGULAR_ROOT_DIR = path.resolve(__dirname, '../../..');
|
||||
const ANGULAR_DIST_PACKAGES = path.resolve(ANGULAR_ROOT_DIR, 'dist/packages-dist');
|
||||
|
||||
/**
|
||||
* A tool that can install Angular dependencies for a project from NPM or from the
|
||||
* locally built distributables.
|
||||
*
|
||||
* This tool is used to change dependencies of the `aio` application and the example
|
||||
* applications.
|
||||
*/
|
||||
class NgPackagesInstaller {
|
||||
|
||||
/**
|
||||
* Create a new installer for a project in the specified directory.
|
||||
*
|
||||
* @param {string} projectDir - the path to the directory containing the project.
|
||||
* @param {object} options - a hash of options for the install
|
||||
* * `debug` (`boolean`) - whether to display debug messages.
|
||||
* * `force` (`boolean`) - whether to force a local installation
|
||||
* even if there is a local marker file.
|
||||
* * `ignorePackages` (`string[]`) - a collection of names of packages
|
||||
* that should not be copied over.
|
||||
*/
|
||||
constructor(projectDir, options = {}) {
|
||||
this.debug = options.debug;
|
||||
this.force = options.force;
|
||||
this.projectDir = path.resolve(projectDir);
|
||||
this.localMarkerPath = path.resolve(this.projectDir, LOCAL_MARKER_PATH);
|
||||
|
||||
this._log('Project directory:', this.projectDir);
|
||||
}
|
||||
|
||||
// Public methods
|
||||
|
||||
/**
|
||||
* Check whether the dependencies have been overridden with locally built
|
||||
* Angular packages. This is done by checking for the `_local_.json` marker file.
|
||||
* This will emit a warning to the console if the dependencies have been overridden.
|
||||
*/
|
||||
checkDependencies() {
|
||||
if (this._checkLocalMarker()) {
|
||||
this._printWarning();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Install locally built Angular dependencies, overriding the dependencies in the package.json
|
||||
* This will also write a "marker" file (`_local_.json`), which contains the overridden package.json
|
||||
* contents and acts as an indicator that dependencies have been overridden.
|
||||
*/
|
||||
installLocalDependencies() {
|
||||
if (this._checkLocalMarker() !== true || this.force) {
|
||||
const pathToPackageConfig = path.resolve(this.projectDir, PACKAGE_JSON);
|
||||
const packages = this._getDistPackages();
|
||||
const packageConfigFile = fs.readFileSync(pathToPackageConfig);
|
||||
const packageConfig = JSON.parse(packageConfigFile);
|
||||
|
||||
const [dependencies, peers] = this._collectDependencies(packageConfig.dependencies || {}, packages);
|
||||
const [devDependencies, devPeers] = this._collectDependencies(packageConfig.devDependencies || {}, packages);
|
||||
|
||||
this._assignPeerDependencies(peers, dependencies, devDependencies);
|
||||
this._assignPeerDependencies(devPeers, dependencies, devDependencies);
|
||||
|
||||
const localPackageConfig = Object.assign(Object.create(null), packageConfig, { dependencies, devDependencies });
|
||||
localPackageConfig.__angular = { local: true };
|
||||
const localPackageConfigJson = JSON.stringify(localPackageConfig, null, 2);
|
||||
|
||||
try {
|
||||
this._log(`Writing temporary local ${PACKAGE_JSON} to ${pathToPackageConfig}`);
|
||||
fs.writeFileSync(pathToPackageConfig, localPackageConfigJson);
|
||||
this._installDeps('--no-lockfile', '--check-files');
|
||||
this._setLocalMarker(localPackageConfigJson);
|
||||
} finally {
|
||||
this._log(`Restoring original ${PACKAGE_JSON} to ${pathToPackageConfig}`);
|
||||
fs.writeFileSync(pathToPackageConfig, packageConfigFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reinstall the original package.json depdendencies
|
||||
* Yarn will also delete the local marker file for us.
|
||||
*/
|
||||
restoreNpmDependencies() {
|
||||
this._installDeps('--check-files');
|
||||
}
|
||||
|
||||
// Protected helpers
|
||||
|
||||
_assignPeerDependencies(peerDependencies, dependencies, devDependencies) {
|
||||
Object.keys(peerDependencies).forEach(key => {
|
||||
// If there is already an equivalent dependency then override it - otherwise assign/override the devDependency
|
||||
if (dependencies[key]) {
|
||||
this._log(`Overriding dependency with peerDependency: ${key}: ${peerDependencies[key]}`);
|
||||
dependencies[key] = peerDependencies[key];
|
||||
} else {
|
||||
this._log(`${devDependencies[key] ? 'Overriding' : 'Assigning'} devDependency with peerDependency: ${key}: ${peerDependencies[key]}`);
|
||||
devDependencies[key] = peerDependencies[key];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_collectDependencies(dependencies, packages) {
|
||||
const peerDependencies = Object.create(null);
|
||||
const mergedDependencies = Object.assign(Object.create(null), dependencies);
|
||||
|
||||
Object.keys(dependencies).forEach(key => {
|
||||
const sourcePackage = packages[key];
|
||||
if (sourcePackage) {
|
||||
// point the core Angular packages at the distributable folder
|
||||
mergedDependencies[key] = `file:${ANGULAR_DIST_PACKAGES}/${key.replace('@angular/', '')}`;
|
||||
this._log(`Overriding dependency with local package: ${key}: ${mergedDependencies[key]}`);
|
||||
// grab peer dependencies
|
||||
Object.keys(sourcePackage.peerDependencies || {})
|
||||
// ignore peerDependencies which are already core Angular packages
|
||||
.filter(key => !packages[key])
|
||||
.forEach(key => peerDependencies[key] = sourcePackage.peerDependencies[key]);
|
||||
}
|
||||
});
|
||||
return [mergedDependencies, peerDependencies];
|
||||
}
|
||||
|
||||
/**
|
||||
* A hash of Angular package configs.
|
||||
* (Detected as directories in '/packages/' that contain a top-level 'package.json' file.)
|
||||
*/
|
||||
_getDistPackages() {
|
||||
const packageConfigs = Object.create(null);
|
||||
this._log(`Angular distributable directory: ${ANGULAR_DIST_PACKAGES}.`);
|
||||
shelljs
|
||||
.find(ANGULAR_DIST_PACKAGES)
|
||||
.map(filePath => filePath.slice(ANGULAR_DIST_PACKAGES.length + 1))
|
||||
.filter(filePath => PACKAGE_JSON_REGEX.test(filePath))
|
||||
.forEach(packagePath => {
|
||||
const packageConfig = require(path.resolve(ANGULAR_DIST_PACKAGES, packagePath));
|
||||
const packageName = `@angular/${packagePath.slice(0, -PACKAGE_JSON.length -1)}`;
|
||||
packageConfigs[packageName] = packageConfig;
|
||||
});
|
||||
this._log('Found the following Angular distributables:', Object.keys(packageConfigs).map(key => `\n - ${key}`));
|
||||
return packageConfigs;
|
||||
}
|
||||
|
||||
_installDeps(...options) {
|
||||
const command = 'yarn install ' + options.join(' ');
|
||||
this._log('Installing dependencies with:', command);
|
||||
shelljs.exec(command, {cwd: this.projectDir});
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a message if the `debug` property is set to true.
|
||||
* @param {...string[]} messages - The messages to be logged.
|
||||
*/
|
||||
_log(...messages) {
|
||||
if (this.debug) {
|
||||
const header = ` [${NgPackagesInstaller.name}]: `;
|
||||
const indent = ' '.repeat(header.length);
|
||||
const message = messages.join(' ');
|
||||
console.info(`${header}${message.split('\n').join(`\n${indent}`)}`);
|
||||
}
|
||||
}
|
||||
|
||||
_printWarning() {
|
||||
const relativeScriptPath = path.relative('.', __filename.replace(/\.js$/, ''));
|
||||
const absoluteProjectDir = path.resolve(this.projectDir);
|
||||
const restoreCmd = `node ${relativeScriptPath} restore ${absoluteProjectDir}`;
|
||||
|
||||
// Log a warning.
|
||||
console.warn(chalk.yellow([
|
||||
'',
|
||||
'!'.repeat(110),
|
||||
'!!!',
|
||||
'!!! WARNING',
|
||||
'!!!',
|
||||
`!!! The project at "${absoluteProjectDir}" is running against the local Angular build.`,
|
||||
'!!!',
|
||||
'!!! To restore the npm packages run:',
|
||||
'!!!',
|
||||
`!!! "${restoreCmd}"`,
|
||||
'!!!',
|
||||
'!'.repeat(110),
|
||||
'',
|
||||
].join('\n')));
|
||||
}
|
||||
|
||||
// Local marker helpers
|
||||
|
||||
_checkLocalMarker() {
|
||||
this._log('Checking for local marker at', this.localMarkerPath);
|
||||
return fs.existsSync(this.localMarkerPath);
|
||||
}
|
||||
|
||||
_setLocalMarker(contents) {
|
||||
this._log('Writing local marker file to', this.localMarkerPath);
|
||||
fs.writeFileSync(this.localMarkerPath, contents);
|
||||
}
|
||||
}
|
||||
|
||||
function main() {
|
||||
shelljs.set('-e');
|
||||
|
||||
yargs
|
||||
.usage('$0 <cmd> [args]')
|
||||
|
||||
.option('debug', { describe: 'Print additional debug information.', default: false })
|
||||
.option('force', { describe: 'Force the command to execute even if not needed.', default: false })
|
||||
|
||||
.command('overwrite <projectDir> [--force] [--debug]', 'Install dependencies from the locally built Angular distributables.', () => {}, argv => {
|
||||
const installer = new NgPackagesInstaller(argv.projectDir, argv);
|
||||
installer.installLocalDependencies();
|
||||
})
|
||||
.command('restore <projectDir> [--debug]', 'Install dependencies from the npm registry.', () => {}, argv => {
|
||||
const installer = new NgPackagesInstaller(argv.projectDir, argv);
|
||||
installer.restoreNpmDependencies();
|
||||
})
|
||||
.command('check <projectDir> [--debug]', 'Check that dependencies came from npm. Otherwise display a warning message.', () => {}, argv => {
|
||||
const installer = new NgPackagesInstaller(argv.projectDir, argv);
|
||||
installer.checkDependencies();
|
||||
})
|
||||
.demandCommand(1, 'Please supply a command from the list above.')
|
||||
.strict()
|
||||
.wrap(yargs.terminalWidth())
|
||||
.argv;
|
||||
}
|
||||
|
||||
module.exports = NgPackagesInstaller;
|
||||
if (require.main === module) {
|
||||
main();
|
||||
}
|
|
@ -0,0 +1,246 @@
|
|||
'use strict';
|
||||
|
||||
const fs = require('fs-extra');
|
||||
const path = require('canonical-path');
|
||||
const shelljs = require('shelljs');
|
||||
|
||||
const NgPackagesInstaller = require('./index');
|
||||
|
||||
describe('NgPackagesInstaller', () => {
|
||||
const rootDir = 'root/dir';
|
||||
const absoluteRootDir = path.resolve(rootDir);
|
||||
const nodeModulesDir = path.resolve(absoluteRootDir, 'node_modules');
|
||||
const packageJsonPath = path.resolve(absoluteRootDir, 'package.json');
|
||||
const packagesDir = path.resolve(path.resolve(__dirname, '../../../dist/packages-dist'));
|
||||
let installer;
|
||||
|
||||
beforeEach(() => {
|
||||
spyOn(fs, 'existsSync');
|
||||
spyOn(fs, 'readFileSync');
|
||||
spyOn(fs, 'writeFileSync');
|
||||
spyOn(shelljs, 'exec');
|
||||
spyOn(shelljs, 'rm');
|
||||
spyOn(console, 'log');
|
||||
spyOn(console, 'warn');
|
||||
installer = new NgPackagesInstaller(rootDir);
|
||||
});
|
||||
|
||||
describe('checkDependencies()', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(installer, '_printWarning');
|
||||
});
|
||||
|
||||
it('should not print a warning if there is no _local_.json file', () => {
|
||||
fs.existsSync.and.returnValue(false);
|
||||
installer.checkDependencies();
|
||||
expect(fs.existsSync).toHaveBeenCalledWith(path.resolve(rootDir, 'node_modules/_local_.json'));
|
||||
expect(installer._printWarning).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should print a warning if there is a _local_.json file', () => {
|
||||
fs.existsSync.and.returnValue(true);
|
||||
installer.checkDependencies();
|
||||
expect(fs.existsSync).toHaveBeenCalledWith(path.resolve(rootDir, 'node_modules/_local_.json'));
|
||||
expect(installer._printWarning).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('installLocalDependencies()', () => {
|
||||
let dummyNgPackages, dummyPackage, dummyPackageJson, expectedModifiedPackage, expectedModifiedPackageJson;
|
||||
|
||||
beforeEach(() => {
|
||||
spyOn(installer, '_checkLocalMarker');
|
||||
|
||||
// These are the packages that are "found" in the dist directory
|
||||
dummyNgPackages = {
|
||||
'@angular/core': { peerDependencies: { rxjs: '5.0.1' } },
|
||||
'@angular/common': { peerDependencies: { '@angular/core': '4.4.1' } },
|
||||
'@angular/compiler': { },
|
||||
'@angular/compiler-cli': { peerDependencies: { typescript: '^2.4.2', '@angular/compiler': '4.3.2' } }
|
||||
};
|
||||
spyOn(installer, '_getDistPackages').and.returnValue(dummyNgPackages);
|
||||
|
||||
// This is the package.json in the "test" folder
|
||||
dummyPackage = {
|
||||
dependencies: {
|
||||
'@angular/core': '4.4.1',
|
||||
'@angular/common': '4.4.1'
|
||||
},
|
||||
devDependencies: {
|
||||
'@angular/compiler-cli': '4.4.1'
|
||||
}
|
||||
};
|
||||
dummyPackageJson = JSON.stringify(dummyPackage);
|
||||
fs.readFileSync.and.returnValue(dummyPackageJson);
|
||||
|
||||
// This is the package.json that is temporarily written to the "test" folder
|
||||
// Note that the Angular (dev)dependencies have been modified to use a "file:" path
|
||||
// And that the peerDependencies from `dummyNgPackages` have been added as (dev)dependencies.
|
||||
expectedModifiedPackage = {
|
||||
dependencies: {
|
||||
'@angular/core': `file:${packagesDir}/core`,
|
||||
'@angular/common': `file:${packagesDir}/common`
|
||||
},
|
||||
devDependencies: {
|
||||
'@angular/compiler-cli': `file:${packagesDir}/compiler-cli`,
|
||||
rxjs: '5.0.1',
|
||||
typescript: '^2.4.2'
|
||||
},
|
||||
__angular: { local: true }
|
||||
};
|
||||
expectedModifiedPackageJson = JSON.stringify(expectedModifiedPackage, null, 2);
|
||||
});
|
||||
|
||||
describe('when there is a local package marker', () => {
|
||||
it('should not continue processing', () => {
|
||||
installer._checkLocalMarker.and.returnValue(true);
|
||||
installer.installLocalDependencies();
|
||||
expect(installer._checkLocalMarker).toHaveBeenCalled();
|
||||
expect(installer._getDistPackages).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('when there is no local package marker', () => {
|
||||
let log;
|
||||
|
||||
beforeEach(() => {
|
||||
log = [];
|
||||
fs.writeFileSync.and.callFake((filePath, contents) => filePath === packageJsonPath && log.push(`writeFile: ${contents}`));
|
||||
spyOn(installer, '_installDeps').and.callFake(() => log.push('installDeps:'));
|
||||
spyOn(installer, '_setLocalMarker');
|
||||
installer._checkLocalMarker.and.returnValue(false);
|
||||
installer.installLocalDependencies();
|
||||
});
|
||||
|
||||
it('should get the dist packages', () => {
|
||||
expect(installer._checkLocalMarker).toHaveBeenCalled();
|
||||
expect(installer._getDistPackages).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should load the package.json', () => {
|
||||
expect(fs.readFileSync).toHaveBeenCalledWith(packageJsonPath);
|
||||
});
|
||||
|
||||
it('should overwrite package.json with modified config', () => {
|
||||
expect(fs.writeFileSync).toHaveBeenCalledWith(packageJsonPath, expectedModifiedPackageJson);
|
||||
});
|
||||
|
||||
it('should restore original package.json', () => {
|
||||
expect(fs.writeFileSync).toHaveBeenCalledWith(packageJsonPath, dummyPackageJson);
|
||||
});
|
||||
|
||||
it('should overwrite package.json, then install deps, then restore original package.json', () => {
|
||||
expect(log).toEqual([
|
||||
`writeFile: ${expectedModifiedPackageJson}`,
|
||||
`installDeps:`,
|
||||
`writeFile: ${dummyPackageJson}`
|
||||
]);
|
||||
});
|
||||
|
||||
it('should set the local marker file with the contents of the modified package.json', () => {
|
||||
expect(installer._setLocalMarker).toHaveBeenCalledWith(expectedModifiedPackageJson);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('restoreNpmDependencies()', () => {
|
||||
it('should run `yarn install --check-files` in the specified directory', () => {
|
||||
spyOn(installer, '_installDeps');
|
||||
installer.restoreNpmDependencies();
|
||||
expect(installer._installDeps).toHaveBeenCalledWith('--check-files');
|
||||
});
|
||||
});
|
||||
|
||||
describe('_getDistPackages', () => {
|
||||
it('should include top level Angular packages', () => {
|
||||
const ngPackages = installer._getDistPackages();
|
||||
|
||||
// For example...
|
||||
expect(ngPackages['@angular/common']).toBeDefined();
|
||||
expect(ngPackages['@angular/core']).toBeDefined();
|
||||
expect(ngPackages['@angular/router']).toBeDefined();
|
||||
expect(ngPackages['@angular/upgrade']).toBeDefined();
|
||||
|
||||
expect(ngPackages['@angular/upgrade/static']).not.toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe('_log()', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(console, 'info');
|
||||
});
|
||||
|
||||
it('should assign the debug property from the options', () => {
|
||||
installer = new NgPackagesInstaller(rootDir, { debug: true });
|
||||
expect(installer.debug).toBe(true);
|
||||
installer = new NgPackagesInstaller(rootDir, { });
|
||||
expect(installer.debug).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should log a message to the console if the `debug` property is true', () => {
|
||||
installer._log('foo');
|
||||
expect(console.info).not.toHaveBeenCalled();
|
||||
|
||||
installer.debug = true;
|
||||
installer._log('bar');
|
||||
expect(console.info).toHaveBeenCalledWith(' [NgPackagesInstaller]: bar');
|
||||
});
|
||||
});
|
||||
|
||||
describe('_printWarning', () => {
|
||||
it('should mention the message passed in the warning', () => {
|
||||
installer._printWarning();
|
||||
expect(console.warn.calls.argsFor(0)[0]).toContain('is running against the local Angular build');
|
||||
});
|
||||
|
||||
it('should mention the command to restore the Angular packages in any warning', () => {
|
||||
// When run for the current working directory...
|
||||
const dir1 = '.';
|
||||
const restoreCmdRe1 = RegExp('\\bnode .*?ng-packages-installer/index restore ' + path.resolve(dir1));
|
||||
installer = new NgPackagesInstaller(dir1);
|
||||
installer._printWarning('');
|
||||
expect(console.warn.calls.argsFor(0)[0]).toMatch(restoreCmdRe1);
|
||||
|
||||
// When run for a different directory...
|
||||
const dir2 = rootDir;
|
||||
const restoreCmdRe2 = RegExp(`\\bnode .*?ng-packages-installer/index restore .*?${path.resolve(dir1)}\\b`);
|
||||
installer = new NgPackagesInstaller(dir2);
|
||||
installer._printWarning('');
|
||||
expect(console.warn.calls.argsFor(1)[0]).toMatch(restoreCmdRe2);
|
||||
});
|
||||
});
|
||||
|
||||
describe('_installDeps', () => {
|
||||
it('should run yarn install with the given options', () => {
|
||||
installer._installDeps('option-1', 'option-2');
|
||||
expect(shelljs.exec).toHaveBeenCalledWith('yarn install option-1 option-2', { cwd: absoluteRootDir });
|
||||
});
|
||||
});
|
||||
|
||||
describe('local marker helpers', () => {
|
||||
let installer;
|
||||
beforeEach(() => {
|
||||
installer = new NgPackagesInstaller(rootDir);
|
||||
});
|
||||
|
||||
describe('_checkLocalMarker', () => {
|
||||
it ('should return true if the local marker file exists', () => {
|
||||
fs.existsSync.and.returnValue(true);
|
||||
expect(installer._checkLocalMarker()).toEqual(true);
|
||||
expect(fs.existsSync).toHaveBeenCalledWith(path.resolve(nodeModulesDir, '_local_.json'));
|
||||
fs.existsSync.calls.reset();
|
||||
|
||||
fs.existsSync.and.returnValue(false);
|
||||
expect(installer._checkLocalMarker()).toEqual(false);
|
||||
expect(fs.existsSync).toHaveBeenCalledWith(path.resolve(nodeModulesDir, '_local_.json'));
|
||||
});
|
||||
});
|
||||
|
||||
describe('_setLocalMarker', () => {
|
||||
it('should create a local marker file', () => {
|
||||
installer._setLocalMarker('test contents');
|
||||
expect(fs.writeFileSync).toHaveBeenCalledWith(path.resolve(nodeModulesDir, '_local_.json'), 'test contents');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue