diff --git a/packages/@angular/cli/commands/set.ts b/packages/@angular/cli/commands/set.ts index efeed832f2..1d1111d6d7 100644 --- a/packages/@angular/cli/commands/set.ts +++ b/packages/@angular/cli/commands/set.ts @@ -74,8 +74,12 @@ const SetCommand = Command.extend({ updateLintForPrefix(this.project.root + '/tslint.json', value); } - config.set(jsonPath, value); - config.save(); + try { + config.set(jsonPath, value); + config.save(); + } catch (error) { + throw new SilentError(error.message); + } resolve(); }); } diff --git a/packages/@ngtools/json-schema/src/schema-class-factory.ts b/packages/@ngtools/json-schema/src/schema-class-factory.ts index d932086282..f83bf95d2c 100644 --- a/packages/@ngtools/json-schema/src/schema-class-factory.ts +++ b/packages/@ngtools/json-schema/src/schema-class-factory.ts @@ -4,10 +4,8 @@ import {JsonSchemaErrorBase} from './error'; import './mimetypes'; - export class InvalidJsonPath extends JsonSchemaErrorBase {} - // The schema tree node property of the SchemaClass. const kSchemaNode = Symbol('schema-node'); // The value property of the SchemaClass. @@ -132,6 +130,7 @@ class SchemaClassBase implements SchemaClass { /** Set a value from a JSON path. */ $$set(path: string, value: any): void { const node = _getSchemaNodeForPath(this.$$schema(), path); + if (node) { node.set(value); } else { diff --git a/packages/@ngtools/json-schema/src/schema-tree.spec.ts b/packages/@ngtools/json-schema/src/schema-tree.spec.ts index 03726d78d8..fb101763a4 100644 --- a/packages/@ngtools/json-schema/src/schema-tree.spec.ts +++ b/packages/@ngtools/json-schema/src/schema-tree.spec.ts @@ -55,12 +55,11 @@ describe('@ngtools/json-schema', () => { }); expect(proto.a instanceof Array).toBe(true); - expect(proto.a).toEqual([undefined, 'v1', undefined, 'v3']); + expect(proto.a).toEqual(['v1', 'v3']); // Set it to a string, which is valid. proto.a[0] = 'v2'; - proto.a[1] = 'INVALID'; - expect(proto.a).toEqual(['v2', undefined, undefined, 'v3']); + expect(proto.a).toEqual(['v2', 'v3']); }); it('supports default values', () => { @@ -72,6 +71,23 @@ describe('@ngtools/json-schema', () => { expect(schema.children['b'].get()).toEqual('default'); }); + + + it('should throw error when setting invalid value', () => { + const proto: any = Object.create(null); + // tslint:disable-next-line + new RootSchemaTreeNode(proto, { + value: valueJson, + schema: schemaJson + }); + + try { + proto.a[0] = 'INVALID'; + } catch (error) { + expect(error.message).toBe('Invalid value can only be one of these: v1,v2,v3'); + } + }); + }); }); diff --git a/packages/@ngtools/json-schema/src/schema-tree.ts b/packages/@ngtools/json-schema/src/schema-tree.ts index 5f9fef73ad..674e31bb17 100644 --- a/packages/@ngtools/json-schema/src/schema-tree.ts +++ b/packages/@ngtools/json-schema/src/schema-tree.ts @@ -7,7 +7,7 @@ export class InvalidSchema extends JsonSchemaErrorBase {} export class InvalidValueError extends JsonSchemaErrorBase {} export class MissingImplementationError extends JsonSchemaErrorBase {} export class SettingReadOnlyPropertyError extends JsonSchemaErrorBase {} - +export class InvalidUpdateValue extends JsonSchemaErrorBase {} export interface Schema { [key: string]: any; @@ -482,6 +482,13 @@ class EnumSchemaTreeNode extends LeafSchemaTreeNode { get items() { return this._schema['enum']; } + set(value: string, init = false, force = false) { + if (!(value === undefined || this._isInEnum(value))) { + throw new InvalidUpdateValue('Invalid value can only be one of these: ' + this.items); + } + super.set(value, init, force); + } + isCompatible(v: any) { return this._isInEnum(v); } diff --git a/packages/@ngtools/json-schema/tests/value2-1.json b/packages/@ngtools/json-schema/tests/value2-1.json index d646965f6f..0bd3cff675 100644 --- a/packages/@ngtools/json-schema/tests/value2-1.json +++ b/packages/@ngtools/json-schema/tests/value2-1.json @@ -1,8 +1,6 @@ { "a": [ - "INVALID", "v1", - "INVALID", "v3" ] } diff --git a/tests/e2e/tests/commands/set/set-enum-check.ts b/tests/e2e/tests/commands/set/set-enum-check.ts new file mode 100644 index 0000000000..33d2847e19 --- /dev/null +++ b/tests/e2e/tests/commands/set/set-enum-check.ts @@ -0,0 +1,9 @@ +import {ng} from '../../../utils/process'; +import {expectToFail} from '../../../utils/utils'; + +export default function() { + return Promise.resolve() + .then(() => expectToFail(() => ng('set', 'defaults.component.aaa', 'bbb'))) + .then(() => expectToFail(() => ng('set', 'defaults.component.viewEncapsulation', 'bbb'))) + .then(() => ng('set', 'defaults.component.viewEncapsulation', 'Emulated')); +}