Skip to content

Commit

Permalink
fix(@angular-devkit/core): handle complex smart defaults in schemas
Browse files Browse the repository at this point in the history
  • Loading branch information
alan-agius4 authored and filipesilva committed May 31, 2021
1 parent 600d266 commit 9f85bc5
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ describe('SimpleScheduler', () => {
// is released, otherwise this breaks because bazel downgrade to ES5 which does not support
// extending Error.
// expect(e instanceof JobInboundMessageSchemaValidationError).toBe(true);
expect(e.message).toMatch(/"\[0\]".*number/);
expect(e.message).toMatch(/"\/0" must be number/);
}
});

Expand Down
46 changes: 33 additions & 13 deletions packages/angular_devkit/core/src/json/schema/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* found in the LICENSE file at https://angular.io/license
*/

import Ajv, { ValidateFunction } from 'ajv';
import Ajv, { SchemaObjCxt, ValidateFunction } from 'ajv';
import ajvAddFormats from 'ajv-formats';
import * as http from 'http';
import * as https from 'https';
Expand Down Expand Up @@ -305,6 +305,8 @@ export class CoreSchemaRegistry implements SchemaRegistry {
try {
this._currentCompilationSchemaInfo = schemaInfo;
validator = this._ajv.compile(schema);
} catch {
validator = await this._ajv.compileAsync(schema);
} finally {
this._currentCompilationSchemaInfo = undefined;
}
Expand Down Expand Up @@ -406,10 +408,7 @@ export class CoreSchemaRegistry implements SchemaRegistry {
}

// We cheat, heavily.
const pathArray = it.dataPathArr
.slice(1, it.dataLevel + 1)
.map((p) => (typeof p === 'number' ? p : p.str.slice(1, -1)));

const pathArray = this.normalizeDataPathArr(it);
compilationSchemInfo.smartDefaultRecord.set(JSON.stringify(pathArray), schema);

return () => true;
Expand Down Expand Up @@ -449,12 +448,7 @@ export class CoreSchemaRegistry implements SchemaRegistry {
return () => true;
}

const path =
'/' +
it.dataPathArr
.slice(1, it.dataLevel + 1)
.map((p) => (typeof p === 'number' ? p : p.str.slice(1, -1)))
.join('/');
const path = '/' + this.normalizeDataPathArr(it).join('/');

let type: string | undefined;
let items: Array<string | { label: string; value: string | number | boolean }> | undefined;
Expand Down Expand Up @@ -593,11 +587,31 @@ export class CoreSchemaRegistry implements SchemaRegistry {
data: any,
fragments: string[],
value: unknown,
parent: Record<string, unknown> | null = null,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
parent: any = null,
parentProperty?: string,
force?: boolean,
): void {
for (const fragment of fragments) {
for (let index = 0; index < fragments.length; index++) {
const fragment = fragments[index];
if (/^i\d+$/.test(fragment)) {
if (!Array.isArray(data)) {
return;
}

for (let dataIndex = 0; dataIndex < data.length; dataIndex++) {
CoreSchemaRegistry._set(
data[dataIndex],
fragments.slice(index + 1),
value,
data,
`${dataIndex}`,
);
}

return;
}

if (!data && parent !== null && parentProperty) {
data = parent[parentProperty] = {};
}
Expand Down Expand Up @@ -665,4 +679,10 @@ export class CoreSchemaRegistry implements SchemaRegistry {
);
}
}

private normalizeDataPathArr(it: SchemaObjCxt): (number | string)[] {
return it.dataPathArr
.slice(1, it.dataLevel + 1)
.map((p) => (typeof p === 'number' ? p : p.str.replace(/\"/g, '')));
}
}
17 changes: 8 additions & 9 deletions packages/angular_devkit/core/src/json/schema/registry_spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ describe('CoreSchemaRegistry', () => {
},
},
tslint: {
$ref: 'https://json.schemastore.org/tslint#',
$ref: 'https://json.schemastore.org/npm-link-up#',
},
},
})
Expand Down Expand Up @@ -130,7 +130,7 @@ describe('CoreSchemaRegistry', () => {
map((result) => {
expect(result.success).toBe(false);
expect(result.errors && result.errors[0].message).toContain(
'should NOT have additional properties',
'must NOT have additional properties',
);
}),
)
Expand Down Expand Up @@ -180,10 +180,10 @@ describe('CoreSchemaRegistry', () => {
mergeMap((validator) => validator(data)),
map((result) => {
expect(result.success).toBe(false);
expect(result.errors && result.errors[0].message).toContain(
'should NOT have additional properties',
expect(result.errors?.[0].message).toContain(
'must NOT have additional properties',
);
expect(result.errors && result.errors[0].keyword).toBe('additionalProperties');
expect(result.errors?.[0].keyword).toBe('additionalProperties');
}),
)
.toPromise()
Expand Down Expand Up @@ -249,7 +249,7 @@ describe('CoreSchemaRegistry', () => {
.then(done, done.fail);
});

it('shows dataPath and message on error', (done) => {
it('shows dataPath and message on error', async () => {
const registry = new CoreSchemaRegistry();
const data = { hotdot: 'hotdog', banana: 'banana' };
const format: SchemaFormat = {
Expand All @@ -262,7 +262,7 @@ describe('CoreSchemaRegistry', () => {

registry.addFormat(format);

registry
await registry
.compile({
properties: {
hotdot: { type: 'string', format: 'is-hotdog' },
Expand All @@ -275,12 +275,11 @@ describe('CoreSchemaRegistry', () => {
expect(result.success).toBe(false);
expect(result.errors && result.errors[0]).toBeTruthy();
expect(result.errors && result.errors[0].keyword).toBe('format');
expect(result.errors && result.errors[0].instancePath).toBe('.banana');
expect(result.errors && result.errors[0].instancePath).toBe('/banana');
expect(result.errors && (result.errors[0].params as any).format).toBe('is-hotdog');
}),
)
.toPromise()
.then(done, done.fail);
});

it('supports smart defaults', (done) => {
Expand Down

0 comments on commit 9f85bc5

Please sign in to comment.