156 lines
5.0 KiB
TypeScript
156 lines
5.0 KiB
TypeScript
|
/**
|
||
|
* @license
|
||
|
* Copyright Google Inc. All Rights Reserved.
|
||
|
*
|
||
|
* Use of this source code is governed by an MIT-style license that can be
|
||
|
* found in the LICENSE file at https://angular.io/license
|
||
|
*/
|
||
|
import {AbsoluteFsPath, FileSystem, absoluteFrom, getFileSystem} from '../../../src/ngtsc/file_system';
|
||
|
import {runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
||
|
import {loadTestFiles} from '../../../test/helpers';
|
||
|
import {DirectPackageJsonUpdater, PackageJsonUpdater} from '../../src/writing/package_json_updater';
|
||
|
|
||
|
runInEachFileSystem(() => {
|
||
|
describe('DirectPackageJsonUpdater', () => {
|
||
|
let _: typeof absoluteFrom;
|
||
|
let fs: FileSystem;
|
||
|
let updater: PackageJsonUpdater;
|
||
|
|
||
|
// Helpers
|
||
|
const readJson = (path: AbsoluteFsPath) => JSON.parse(fs.readFile(path));
|
||
|
|
||
|
beforeEach(() => {
|
||
|
_ = absoluteFrom;
|
||
|
fs = getFileSystem();
|
||
|
updater = new DirectPackageJsonUpdater(fs);
|
||
|
});
|
||
|
|
||
|
it('should update a `package.json` file on disk', () => {
|
||
|
const jsonPath = _('/foo/package.json');
|
||
|
loadTestFiles([
|
||
|
{name: jsonPath, contents: '{"foo": true, "bar": {"baz": "OK"}}'},
|
||
|
]);
|
||
|
|
||
|
const update = updater.createUpdate().addChange(['foo'], false).addChange(['bar', 'baz'], 42);
|
||
|
|
||
|
// Not updated yet.
|
||
|
expect(readJson(jsonPath)).toEqual({
|
||
|
foo: true,
|
||
|
bar: {baz: 'OK'},
|
||
|
});
|
||
|
|
||
|
update.writeChanges(jsonPath);
|
||
|
|
||
|
// Updated now.
|
||
|
expect(readJson(jsonPath)).toEqual({
|
||
|
foo: false,
|
||
|
bar: {baz: 42},
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('should update an in-memory representation (if provided)', () => {
|
||
|
const jsonPath = _('/foo/package.json');
|
||
|
loadTestFiles([
|
||
|
{name: jsonPath, contents: '{"foo": true, "bar": {"baz": "OK"}}'},
|
||
|
]);
|
||
|
|
||
|
const pkg = readJson(jsonPath);
|
||
|
const update = updater.createUpdate().addChange(['foo'], false).addChange(['bar', 'baz'], 42);
|
||
|
|
||
|
// Not updated yet.
|
||
|
expect(pkg).toEqual({
|
||
|
foo: true,
|
||
|
bar: {baz: 'OK'},
|
||
|
});
|
||
|
|
||
|
update.writeChanges(jsonPath, pkg);
|
||
|
|
||
|
// Updated now.
|
||
|
expect(pkg).toEqual({
|
||
|
foo: false,
|
||
|
bar: {baz: 42},
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('should create the `package.json` file, if it does not exist', () => {
|
||
|
const jsonPath = _('/foo/package.json');
|
||
|
expect(fs.exists(jsonPath)).toBe(false);
|
||
|
|
||
|
updater.createUpdate()
|
||
|
.addChange(['foo'], false)
|
||
|
.addChange(['bar', 'baz'], 42)
|
||
|
.writeChanges(jsonPath);
|
||
|
|
||
|
expect(fs.exists(jsonPath)).toBe(true);
|
||
|
expect(readJson(jsonPath)).toEqual({
|
||
|
foo: false,
|
||
|
bar: {baz: 42},
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('should create any missing ancestor objects', () => {
|
||
|
const jsonPath = _('/foo/package.json');
|
||
|
loadTestFiles([
|
||
|
{name: jsonPath, contents: '{"foo": {}}'},
|
||
|
]);
|
||
|
|
||
|
const pkg = readJson(jsonPath);
|
||
|
updater.createUpdate()
|
||
|
.addChange(['foo', 'bar', 'baz', 'qux'], 'updated')
|
||
|
.writeChanges(jsonPath, pkg);
|
||
|
|
||
|
expect(readJson(jsonPath)).toEqual(pkg);
|
||
|
expect(pkg).toEqual({
|
||
|
foo: {
|
||
|
bar: {
|
||
|
baz: {
|
||
|
qux: 'updated',
|
||
|
},
|
||
|
},
|
||
|
},
|
||
|
});
|
||
|
});
|
||
|
|
||
|
it('should throw, if no changes have been recorded', () => {
|
||
|
const jsonPath = _('/foo/package.json');
|
||
|
|
||
|
expect(() => updater.createUpdate().writeChanges(jsonPath))
|
||
|
.toThrowError(`No changes to write to '${jsonPath}'.`);
|
||
|
});
|
||
|
|
||
|
it('should throw, if a property-path is empty', () => {
|
||
|
const jsonPath = _('/foo/package.json');
|
||
|
|
||
|
expect(() => updater.createUpdate().addChange([], 'missing').writeChanges(jsonPath))
|
||
|
.toThrowError(`Missing property path for writing value to '${jsonPath}'.`);
|
||
|
});
|
||
|
|
||
|
it('should throw, if a property-path points to a non-object intermediate value', () => {
|
||
|
const jsonPath = _('/foo/package.json');
|
||
|
loadTestFiles([
|
||
|
{name: jsonPath, contents: '{"foo": null, "bar": 42, "baz": {"qux": []}}'},
|
||
|
]);
|
||
|
|
||
|
const writeToProp = (propPath: string[]) =>
|
||
|
updater.createUpdate().addChange(propPath, 'updated').writeChanges(jsonPath);
|
||
|
|
||
|
expect(() => writeToProp(['foo', 'child']))
|
||
|
.toThrowError('Property path \'foo.child\' does not point to an object.');
|
||
|
expect(() => writeToProp(['bar', 'child']))
|
||
|
.toThrowError('Property path \'bar.child\' does not point to an object.');
|
||
|
expect(() => writeToProp(['baz', 'qux', 'child']))
|
||
|
.toThrowError('Property path \'baz.qux.child\' does not point to an object.');
|
||
|
});
|
||
|
|
||
|
it('should throw, if trying to re-apply an already applied update', () => {
|
||
|
const update = updater.createUpdate().addChange(['foo'], 'updated');
|
||
|
|
||
|
expect(() => update.writeChanges(_('/foo/package.json'))).not.toThrow();
|
||
|
expect(() => update.writeChanges(_('/foo/package.json')))
|
||
|
.toThrowError('Trying to apply a `PackageJsonUpdate` that has already been applied.');
|
||
|
expect(() => update.writeChanges(_('/bar/package.json')))
|
||
|
.toThrowError('Trying to apply a `PackageJsonUpdate` that has already been applied.');
|
||
|
});
|
||
|
});
|
||
|
});
|