|
7 | 7 | */ |
8 | 8 |
|
9 | 9 | /* eslint-disable @typescript-eslint/no-explicit-any */ |
| 10 | +import { JsonValue } from '../utils'; |
10 | 11 | import { SchemaFormat } from './interface'; |
11 | 12 | import { CoreSchemaRegistry, SchemaValidationException } from './registry'; |
| 13 | +import { JsonSchema } from './schema'; |
12 | 14 | import { addUndefinedDefaults } from './transforms'; |
13 | 15 |
|
14 | 16 | describe('CoreSchemaRegistry', () => { |
@@ -340,4 +342,93 @@ describe('CoreSchemaRegistry', () => { |
340 | 342 | expect(deprecatedMessages[1]).toBe('Option "bar" is deprecated.'); |
341 | 343 | expect(result.success).toBe(true, result.errors); |
342 | 344 | }); |
| 345 | + |
| 346 | + describe('error messages', () => { |
| 347 | + async function messagesFor(schema: JsonSchema, data: JsonValue): Promise<string[]> { |
| 348 | + const registry = new CoreSchemaRegistry(); |
| 349 | + const validator = await registry.compile(schema); |
| 350 | + const result = await validator(data); |
| 351 | + expect(result.success).toBe(false); |
| 352 | + |
| 353 | + return SchemaValidationException.createMessages(result.errors); |
| 354 | + } |
| 355 | + |
| 356 | + it('names an unknown option and the options that are valid there', async () => { |
| 357 | + const messages = await messagesFor( |
| 358 | + { |
| 359 | + properties: { version: { type: 'number' }, projects: { type: 'object' } }, |
| 360 | + additionalProperties: false, |
| 361 | + }, |
| 362 | + { allowedCommonJsDependencies: [] }, |
| 363 | + ); |
| 364 | + |
| 365 | + expect(messages).toEqual([ |
| 366 | + 'Unknown option "allowedCommonJsDependencies". Valid options are: version, projects.', |
| 367 | + ]); |
| 368 | + }); |
| 369 | + |
| 370 | + it('points at the object an unknown option was found in', async () => { |
| 371 | + const messages = await messagesFor( |
| 372 | + { |
| 373 | + properties: { |
| 374 | + cli: { |
| 375 | + type: 'object', |
| 376 | + properties: { cache: { type: 'object' }, packageManager: { type: 'string' } }, |
| 377 | + additionalProperties: false, |
| 378 | + }, |
| 379 | + }, |
| 380 | + }, |
| 381 | + { cli: { completion: true } }, |
| 382 | + ); |
| 383 | + |
| 384 | + expect(messages).toEqual([ |
| 385 | + 'Unknown option "completion" at "/cli". Valid options are: cache, packageManager.', |
| 386 | + ]); |
| 387 | + }); |
| 388 | + |
| 389 | + it('looks through a $ref for the valid options', async () => { |
| 390 | + const messages = await messagesFor( |
| 391 | + { |
| 392 | + $ref: '#/definitions/global', |
| 393 | + definitions: { |
| 394 | + global: { |
| 395 | + type: 'object', |
| 396 | + properties: { cli: { type: 'object' }, schematics: { type: 'object' } }, |
| 397 | + additionalProperties: false, |
| 398 | + }, |
| 399 | + }, |
| 400 | + }, |
| 401 | + { version: 1 }, |
| 402 | + ); |
| 403 | + |
| 404 | + expect(messages).toEqual(['Unknown option "version". Valid options are: cli, schematics.']); |
| 405 | + }); |
| 406 | + |
| 407 | + it('omits the valid options when the schema does not list any', async () => { |
| 408 | + const messages = await messagesFor( |
| 409 | + { |
| 410 | + $ref: '#/definitions/cli', |
| 411 | + definitions: { |
| 412 | + cli: { |
| 413 | + type: 'object', |
| 414 | + patternProperties: { '^x-': { type: 'string' } }, |
| 415 | + additionalProperties: false, |
| 416 | + }, |
| 417 | + }, |
| 418 | + }, |
| 419 | + { completion: true }, |
| 420 | + ); |
| 421 | + |
| 422 | + expect(messages).toEqual(['Unknown option "completion".']); |
| 423 | + }); |
| 424 | + |
| 425 | + it('leaves an error that is not about an unknown option alone', async () => { |
| 426 | + const messages = await messagesFor( |
| 427 | + { properties: { outputPath: { type: 'string' } } }, |
| 428 | + { outputPath: 42 }, |
| 429 | + ); |
| 430 | + |
| 431 | + expect(messages).toEqual(['Data path "/outputPath" must be string.']); |
| 432 | + }); |
| 433 | + }); |
343 | 434 | }); |
0 commit comments