Skip to content

Commit 339e42c

Browse files
Merge pull request #1851 from markscott-ms/timelines
Update release-1.1 from main - bad schema validation test
2 parents e73f177 + a81cde6 commit 339e42c

File tree

3 files changed

+66
-6
lines changed

3 files changed

+66
-6
lines changed

shared/src/commands/validate/json-schema-validator.spec.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ import { describe, it, beforeEach, afterEach, expect, vi } from 'vitest';
22
import { JsonSchemaValidator } from './json-schema-validator';
33
import Ajv2020 from 'ajv/dist/2020.js';
44
import { SchemaDirectory } from '../../schema-directory.js';
5+
import { FileSystemDocumentLoader } from '../../document-loader/file-system-document-loader.js';
6+
import path from 'path';
7+
import { readFileSync } from 'fs';
58

69
describe('JsonSchemaValidator', () => {
710
let schemaDirectory: SchemaDirectory;
@@ -61,3 +64,17 @@ describe('JsonSchemaValidator', () => {
6164
expect(() => validator.validate({})).toThrowError('Validator has not been initialized. Call initialize() before validating.');
6265
});
6366
});
67+
68+
describe('JsonSchemaValidator integration', () => {
69+
const schemaDir = path.join(__dirname, '../../../../calm/release/1.0/meta/');
70+
const badPatternPath = path.join(__dirname, '../../../test_fixtures/bad-schema/bad-json-schema.json');
71+
72+
it('throws when compiling the bad-json-schema fixture', async () => {
73+
const schemaDirectory = new SchemaDirectory(new FileSystemDocumentLoader([schemaDir], true));
74+
await schemaDirectory.loadSchemas();
75+
const badPattern = JSON.parse(readFileSync(badPatternPath, 'utf-8'));
76+
const validator = new JsonSchemaValidator(schemaDirectory, badPattern);
77+
78+
await expect(validator.initialize()).rejects.toThrow(/type/i);
79+
});
80+
});

shared/src/commands/validate/validate.e2e.spec.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ const inputPatternPath = path.join(
1313
__dirname,
1414
'../../../test_fixtures/command/validate/options/pattern.json'
1515
);
16+
const badPatternPath = path.join(
17+
__dirname,
18+
'../../../test_fixtures/bad-schema/bad-json-schema.json'
19+
);
1620

1721
const schemaDir = path.join(__dirname, '../../../../calm/release/1.0/meta/');
1822

@@ -38,6 +42,21 @@ describe('validate E2E', () => {
3842
expect(response.spectralSchemaValidationOutputs[1].path).toBe('/nodes/1/description');
3943
});
4044

45+
it('reports json schema compilation errors for bad-json-schema fixture', async () => {
46+
schemaDirectory = new SchemaDirectory(new FileSystemDocumentLoader([schemaDir], true));
47+
await schemaDirectory.loadSchemas();
48+
49+
const badPattern = JSON.parse(readFileSync(badPatternPath, 'utf-8'));
50+
const inputArch = JSON.parse(readFileSync(inputArchPath, 'utf-8'));
51+
52+
const response = await validate(inputArch, badPattern, undefined, schemaDirectory, false);
53+
54+
expect(response.hasErrors).toBeTruthy();
55+
expect(response.jsonSchemaValidationOutputs).toHaveLength(1);
56+
expect(response.jsonSchemaValidationOutputs[0].message).toContain('type');
57+
expect(response.jsonSchemaValidationOutputs[0].path).toBe('/');
58+
});
59+
4160
describe('applyArchitectureOptionsToPattern', () => {
4261
it('works with one options relationship', async () => {
4362
const architecture = JSON.parse(

shared/src/commands/validate/validate.ts

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,19 @@ async function validateArchitectureAgainstPattern(architecture: object, pattern:
149149

150150
const patternResolved = applyArchitectureOptionsToPattern(architecture, pattern, debug);
151151

152-
const jsonSchemaValidator = new JsonSchemaValidator(schemaDirectory, patternResolved, debug);
153-
await jsonSchemaValidator.initialize();
154-
155152
let jsonSchemaValidations = [];
153+
let jsonSchemaValidator: JsonSchemaValidator;
154+
try {
155+
jsonSchemaValidator = new JsonSchemaValidator(schemaDirectory, patternResolved, debug);
156+
await jsonSchemaValidator.initialize();
157+
} catch (error) {
158+
const errorMessage = toErrorMessage(error);
159+
logger.error(`JSON Schema compilation failed: ${errorMessage}`);
160+
jsonSchemaValidations = [
161+
new ValidationOutput('json-schema', 'error', errorMessage, '/')
162+
];
163+
return new ValidationOutcome(jsonSchemaValidations, spectralResult.spectralIssues, true, warnings);
164+
}
156165

157166
const schemaErrors = jsonSchemaValidator.validate(architecture);
158167
if (schemaErrors.length > 0) {
@@ -184,10 +193,11 @@ async function validatePatternOnly(pattern: object, schemaDirectory: SchemaDirec
184193

185194
try {
186195
// Compile pattern as a schema to check if it's valid
187-
new JsonSchemaValidator(schemaDirectory, pattern, debug);
196+
const jsonSchemaValidator = new JsonSchemaValidator(schemaDirectory, pattern, debug);
197+
await jsonSchemaValidator.initialize();
188198
} catch (error) {
189199
errors = true;
190-
jsonSchemaErrors.push(new ValidationOutput('json-schema', 'error', error.message, '/'));
200+
jsonSchemaErrors.push(new ValidationOutput('json-schema', 'error', toErrorMessage(error), '/'));
191201
}
192202

193203
return new ValidationOutcome(jsonSchemaErrors, spectralValidationResults.spectralIssues, errors, warnings);// added spectral to return object
@@ -294,6 +304,20 @@ function prettifyJson(json) {
294304
return JSON.stringify(json, null, 4);
295305
}
296306

307+
function toErrorMessage(error: unknown): string {
308+
if (error instanceof Error) {
309+
return error.message;
310+
}
311+
if (typeof error === 'string') {
312+
return error;
313+
}
314+
try {
315+
return JSON.stringify(error);
316+
} catch {
317+
return 'Unknown error';
318+
}
319+
}
320+
297321
export function stripRefs(obj: object): string {
298322
return JSON.stringify(obj).replaceAll('$ref', 'ref');
299323
}
@@ -364,4 +388,4 @@ function mergeSpectralResults(spectralResultPattern: SpectralResult, spectralRes
364388
const warnings: boolean = spectralResultPattern.warnings || spectralResultArchitecture.warnings;
365389
const spectralValidations = spectralResultPattern.spectralIssues.concat(spectralResultArchitecture.spectralIssues);
366390
return new SpectralResult(warnings, errors, spectralValidations);
367-
}
391+
}

0 commit comments

Comments
 (0)