|
9 | 9 | transformBearerAuthToAPIToken, |
10 | 10 | transformServerVariables, |
11 | 11 | transformEnumDescriptions, |
| 12 | + transformGleanDeprecated, |
12 | 13 | injectOpenApiCommitSha, |
13 | 14 | } from '../src/source-spec-transformer.js'; |
14 | 15 |
|
@@ -423,4 +424,193 @@ describe('OpenAPI YAML Transformer', () => { |
423 | 424 |
|
424 | 425 | expect(transformedSpec.info['x-open-api-commit-sha']).toBeUndefined(); |
425 | 426 | }); |
| 427 | + |
| 428 | + test('transformGleanDeprecated adds Speakeasy deprecation fields to operations', () => { |
| 429 | + const testSpec = { |
| 430 | + paths: { |
| 431 | + '/test': { |
| 432 | + get: { |
| 433 | + operationId: 'getTest', |
| 434 | + 'x-glean-deprecated': { |
| 435 | + id: 'uuid-123', |
| 436 | + message: 'Use /v2/test instead', |
| 437 | + introduced: '2024-01-15', |
| 438 | + removal: '2024-07-15', |
| 439 | + }, |
| 440 | + }, |
| 441 | + }, |
| 442 | + }, |
| 443 | + }; |
| 444 | + |
| 445 | + const transformedSpec = transformGleanDeprecated(testSpec); |
| 446 | + |
| 447 | + expect(transformedSpec.paths['/test'].get.deprecated).toBe(true); |
| 448 | + expect( |
| 449 | + transformedSpec.paths['/test'].get['x-speakeasy-deprecation-message'], |
| 450 | + ).toBe( |
| 451 | + 'Deprecated on 2024-01-15, removal scheduled for 2024-07-15: Use /v2/test instead', |
| 452 | + ); |
| 453 | + // Verify original annotation is preserved |
| 454 | + expect( |
| 455 | + transformedSpec.paths['/test'].get['x-glean-deprecated'], |
| 456 | + ).toBeDefined(); |
| 457 | + expect(transformedSpec.paths['/test'].get['x-glean-deprecated'].id).toBe( |
| 458 | + 'uuid-123', |
| 459 | + ); |
| 460 | + }); |
| 461 | + |
| 462 | + test('transformGleanDeprecated adds Speakeasy deprecation fields to parameters', () => { |
| 463 | + const testSpec = { |
| 464 | + paths: { |
| 465 | + '/test': { |
| 466 | + get: { |
| 467 | + parameters: [ |
| 468 | + { |
| 469 | + name: 'oldParam', |
| 470 | + in: 'query', |
| 471 | + 'x-glean-deprecated': { |
| 472 | + id: 'param-uuid', |
| 473 | + message: 'Use newParam instead', |
| 474 | + introduced: '2024-02-01', |
| 475 | + removal: '2024-08-01', |
| 476 | + }, |
| 477 | + }, |
| 478 | + ], |
| 479 | + }, |
| 480 | + }, |
| 481 | + }, |
| 482 | + }; |
| 483 | + |
| 484 | + const transformedSpec = transformGleanDeprecated(testSpec); |
| 485 | + |
| 486 | + const param = transformedSpec.paths['/test'].get.parameters[0]; |
| 487 | + expect(param.deprecated).toBe(true); |
| 488 | + expect(param['x-speakeasy-deprecation-message']).toBe( |
| 489 | + 'Deprecated on 2024-02-01, removal scheduled for 2024-08-01: Use newParam instead', |
| 490 | + ); |
| 491 | + expect(param['x-glean-deprecated']).toBeDefined(); |
| 492 | + }); |
| 493 | + |
| 494 | + test('transformGleanDeprecated adds Speakeasy deprecation fields to schema properties', () => { |
| 495 | + const testSpec = { |
| 496 | + components: { |
| 497 | + schemas: { |
| 498 | + TestSchema: { |
| 499 | + type: 'object', |
| 500 | + properties: { |
| 501 | + oldField: { |
| 502 | + type: 'string', |
| 503 | + 'x-glean-deprecated': { |
| 504 | + id: 'schema-uuid', |
| 505 | + message: 'Field renamed to newField', |
| 506 | + introduced: '2024-03-01', |
| 507 | + removal: '2024-09-01', |
| 508 | + docs: 'https://docs.example.com/migration', |
| 509 | + }, |
| 510 | + }, |
| 511 | + newField: { |
| 512 | + type: 'string', |
| 513 | + }, |
| 514 | + }, |
| 515 | + }, |
| 516 | + }, |
| 517 | + }, |
| 518 | + }; |
| 519 | + |
| 520 | + const transformedSpec = transformGleanDeprecated(testSpec); |
| 521 | + |
| 522 | + const oldField = |
| 523 | + transformedSpec.components.schemas.TestSchema.properties.oldField; |
| 524 | + expect(oldField.deprecated).toBe(true); |
| 525 | + expect(oldField['x-speakeasy-deprecation-message']).toBe( |
| 526 | + 'Deprecated on 2024-03-01, removal scheduled for 2024-09-01: Field renamed to newField', |
| 527 | + ); |
| 528 | + expect(oldField['x-glean-deprecated']).toBeDefined(); |
| 529 | + expect(oldField['x-glean-deprecated'].docs).toBe( |
| 530 | + 'https://docs.example.com/migration', |
| 531 | + ); |
| 532 | + |
| 533 | + // Verify non-deprecated field is unchanged |
| 534 | + const newField = |
| 535 | + transformedSpec.components.schemas.TestSchema.properties.newField; |
| 536 | + expect(newField.deprecated).toBeUndefined(); |
| 537 | + expect(newField['x-speakeasy-deprecation-message']).toBeUndefined(); |
| 538 | + }); |
| 539 | + |
| 540 | + test('transformGleanDeprecated handles specs without x-glean-deprecated', () => { |
| 541 | + const testSpec = { |
| 542 | + paths: { |
| 543 | + '/test': { |
| 544 | + get: { |
| 545 | + operationId: 'getTest', |
| 546 | + summary: 'Test endpoint', |
| 547 | + }, |
| 548 | + }, |
| 549 | + }, |
| 550 | + components: { |
| 551 | + schemas: { |
| 552 | + TestSchema: { |
| 553 | + type: 'object', |
| 554 | + properties: { |
| 555 | + field: { |
| 556 | + type: 'string', |
| 557 | + }, |
| 558 | + }, |
| 559 | + }, |
| 560 | + }, |
| 561 | + }, |
| 562 | + }; |
| 563 | + |
| 564 | + const transformedSpec = transformGleanDeprecated(testSpec); |
| 565 | + |
| 566 | + // Verify no deprecated fields were added |
| 567 | + expect(transformedSpec.paths['/test'].get.deprecated).toBeUndefined(); |
| 568 | + expect( |
| 569 | + transformedSpec.paths['/test'].get['x-speakeasy-deprecation-message'], |
| 570 | + ).toBeUndefined(); |
| 571 | + expect( |
| 572 | + transformedSpec.components.schemas.TestSchema.properties.field.deprecated, |
| 573 | + ).toBeUndefined(); |
| 574 | + }); |
| 575 | + |
| 576 | + test('transformGleanDeprecated handles nested deprecations', () => { |
| 577 | + const testSpec = { |
| 578 | + paths: { |
| 579 | + '/test': { |
| 580 | + post: { |
| 581 | + requestBody: { |
| 582 | + content: { |
| 583 | + 'application/json': { |
| 584 | + schema: { |
| 585 | + properties: { |
| 586 | + deprecatedField: { |
| 587 | + type: 'string', |
| 588 | + 'x-glean-deprecated': { |
| 589 | + id: 'nested-uuid', |
| 590 | + message: 'This field is deprecated', |
| 591 | + introduced: '2024-04-01', |
| 592 | + removal: '2024-10-01', |
| 593 | + }, |
| 594 | + }, |
| 595 | + }, |
| 596 | + }, |
| 597 | + }, |
| 598 | + }, |
| 599 | + }, |
| 600 | + }, |
| 601 | + }, |
| 602 | + }, |
| 603 | + }; |
| 604 | + |
| 605 | + const transformedSpec = transformGleanDeprecated(testSpec); |
| 606 | + |
| 607 | + const deprecatedField = |
| 608 | + transformedSpec.paths['/test'].post.requestBody.content[ |
| 609 | + 'application/json' |
| 610 | + ].schema.properties.deprecatedField; |
| 611 | + expect(deprecatedField.deprecated).toBe(true); |
| 612 | + expect(deprecatedField['x-speakeasy-deprecation-message']).toBe( |
| 613 | + 'Deprecated on 2024-04-01, removal scheduled for 2024-10-01: This field is deprecated', |
| 614 | + ); |
| 615 | + }); |
426 | 616 | }); |
0 commit comments