Skip to content

Commit

Permalink
fix(oas-normalize): dont attempt to upconvert an OpenAPI definition (#…
Browse files Browse the repository at this point in the history
…862)

## 🧰 Changes

Discovered this while running our OpenAPI 3.1 webhooks example through
`OASNormalize.validate()` but when you supply `convertToLatest` we
always attempt to funnel the API definition through `swagger2openapi`;
because OpenAPI 3.1 definitions with only webhooks don't have paths
`swagger2openapi` throws an error on no `paths` being present.
  • Loading branch information
erunion authored Apr 17, 2024
1 parent e8705b0 commit 46cdc4f
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 12 deletions.
2 changes: 1 addition & 1 deletion packages/oas-normalize/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ export default class OASNormalize {
return openapiParser
.validate(clonedSchema, parserOptions)
.then(() => {
if (!convertToLatest) {
if (!convertToLatest || utils.isOpenAPI(schema)) {
return schema;
}

Expand Down
25 changes: 14 additions & 11 deletions packages/oas-normalize/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@ import { describe, afterEach, beforeAll, beforeEach, it, expect } from 'vitest';
import OASNormalize from '../src/index.js';
import { getAPIDefinitionType, isAPIDefinition, isOpenAPI, isPostman, isSwagger } from '../src/lib/utils.js';

function cloneObject(obj) {
return JSON.parse(JSON.stringify(obj));
}

describe('#load', () => {
describe.each([
['Swagger 2.0', '2.0'],
Expand All @@ -29,16 +25,16 @@ describe('#load', () => {
});

it('should reject if unrecognized file supplied', async () => {
await expect(new OASNormalize(cloneObject).load()).rejects.toThrow('Could not load this file.');
await expect(new OASNormalize(undefined).load()).rejects.toThrow('Could not load this file.');
});

it('should support JSON objects', async () => {
const o = new OASNormalize(cloneObject(json));
const o = new OASNormalize(structuredClone(json));
await expect(o.load()).resolves.toStrictEqual(json);
});

it('should support stringified JSON objects', async () => {
const def = JSON.stringify(cloneObject(json));
const def = JSON.stringify(structuredClone(json));
const o = new OASNormalize(def);

await expect(o.load()).resolves.toStrictEqual(json);
Expand Down Expand Up @@ -114,7 +110,7 @@ describe('#load', () => {
const yaml = require.resolve('./__fixtures__/quirks/yaml-date.yaml');
const o = new OASNormalize(fs.readFileSync(yaml, 'utf8'));

const s = await o.load();
const s = (await o.load()) as unknown as OpenAPIV3.Document;
expect(typeof s.info.version).toBe('string');
});
});
Expand Down Expand Up @@ -168,7 +164,7 @@ describe('#deref', () => {
$ref: '#/components/requestBodies/Pet',
});

const o = new OASNormalize(cloneObject(openapi));
const o = new OASNormalize(structuredClone(openapi));
const deref = (await o.deref()) as OpenAPIV3.Document;

expect(deref?.paths?.['/pet']?.post?.requestBody).toStrictEqual({
Expand Down Expand Up @@ -207,11 +203,18 @@ describe('#deref', () => {
describe('#validate', () => {
it("should not convert a Swagger definition to OpenAPI if we don't want to", async () => {
const swagger = await import('@readme/oas-examples/2.0/json/petstore.json').then(r => r.default);
const o = new OASNormalize(cloneObject(swagger));
const o = new OASNormalize(structuredClone(swagger));

await expect(o.validate()).resolves.toStrictEqual(swagger);
});

it('should not attempt to upconvert an OpenAPI definition if we dont need to', async () => {
const webhooks = await import('@readme/oas-examples/3.1/json/webhooks.json').then(r => r.default);
const o = new OASNormalize(structuredClone(webhooks));

await expect(o.validate({ convertToLatest: true })).resolves.toStrictEqual(webhooks);
});

it('should error out on a definition a missing component', async () => {
const contents = path.join(__dirname, '__fixtures__', 'invalid', 'swagger.json');
const o = new OASNormalize(contents, { enablePaths: true });
Expand Down Expand Up @@ -291,7 +294,7 @@ describe('#validate', () => {
it('should validate a URL hosting JSON as expected', async () => {
const json = await import(`@readme/oas-examples/${version}/json/petstore.json`).then(r => r.default);

fetchMock.get(`http://example.com/api-${version}.json`, cloneObject(json));
fetchMock.get(`http://example.com/api-${version}.json`, structuredClone(json));
const o = new OASNormalize(`http://example.com/api-${version}.json`);

await expect(o.validate({ convertToLatest: true })).resolves.toMatchSnapshot();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ describe('multipart/form-data parameters', () => {

// This is supposed to be supported, but the style-serializer library we use does not have
// support. Holding off for now.
// eslint-disable-next-line vitest/no-disabled-tests
it.skip(
'should NOT support space delimited multipart/form-data styles for exploded object input',
assertSpaceDelimitedStyle(bodyExplode, { body: { object: objectInput } }, []),
Expand Down Expand Up @@ -325,6 +326,7 @@ describe('multipart/form-data parameters', () => {

// This is supposed to be supported, but the style-seralizer library we use does not have
// support. Holding off for now.
// eslint-disable-next-line vitest/no-disabled-tests
it.skip(
'should NOT support pipe delimited multipart/form-data styles for exploded object input',
assertPipeDelimitedStyle(bodyExplode, { body: { color: objectInput } }, []),
Expand Down

0 comments on commit 46cdc4f

Please sign in to comment.