Skip to content

Commit

Permalink
feat(openapi/convert): support openapi in convert command (#941)
Browse files Browse the repository at this point in the history
* fix(openapi/convert): support openapi in convert command

* test: fix single-threaded test
  • Loading branch information
kanadgupta authored Nov 21, 2023
1 parent 8c6c54c commit a33bbeb
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 14 deletions.
9 changes: 6 additions & 3 deletions __tests__/__snapshots__/index.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ Options
Related commands
$ rdme openapi:convert Convert a Swagger or Postman Collection to OpenAPI.
$ rdme openapi:convert Convert an API definition to OpenAPI and bundle any
external references.
$ rdme openapi:inspect Analyze an OpenAPI/Swagger definition for various
OpenAPI and ReadMe feature usage.
$ rdme openapi:reduce Reduce an OpenAPI definition into a smaller subset.
Expand Down Expand Up @@ -86,7 +87,8 @@ Options
Related commands
$ rdme openapi:convert Convert a Swagger or Postman Collection to OpenAPI.
$ rdme openapi:convert Convert an API definition to OpenAPI and bundle any
external references.
$ rdme openapi:inspect Analyze an OpenAPI/Swagger definition for various
OpenAPI and ReadMe feature usage.
$ rdme openapi:reduce Reduce an OpenAPI definition into a smaller subset.
Expand Down Expand Up @@ -133,7 +135,8 @@ Options
Related commands
$ rdme openapi:convert Convert a Swagger or Postman Collection to OpenAPI.
$ rdme openapi:convert Convert an API definition to OpenAPI and bundle any
external references.
$ rdme openapi:inspect Analyze an OpenAPI/Swagger definition for various
OpenAPI and ReadMe feature usage.
$ rdme openapi:reduce Reduce an OpenAPI definition into a smaller subset.
Expand Down
38 changes: 35 additions & 3 deletions __tests__/cmds/openapi/convert.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import OpenAPIConvertCommand from '../../../src/cmds/openapi/convert.js';

const convert = new OpenAPIConvertCommand();

const successfulConversion = () => 'Your converted API definition has been saved to output.json!';
const successfulConversion = () => 'Your API definition has been converted and bundled and saved to output.json!';

describe('rdme openapi:convert', () => {
describe('converting', () => {
Expand Down Expand Up @@ -41,13 +41,45 @@ describe('rdme openapi:convert', () => {
it.each([['json'], ['yaml']])('should fail if given an OpenAPI 3.0 definition (format: %s)', async format => {
const spec = require.resolve(`@readme/oas-examples/3.0/${format}/petstore.${format}`);

const consoleWarnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});

let reducedSpec;
fs.writeFileSync = vi.fn((fileName, data) => {
reducedSpec = JSON.parse(data as string);
});

prompts.inject(['output.json']);

await expect(
convert.run({
spec,
}),
).rejects.toStrictEqual(
new Error("Sorry, this API definition is already an OpenAPI definition and doesn't need to be converted."),
).resolves.toBe(successfulConversion());

expect(fs.writeFileSync).toHaveBeenCalledWith('output.json', expect.any(String));
expect(reducedSpec.tags).toHaveLength(3);
expect(Object.keys(reducedSpec.paths)).toStrictEqual([
'/pet',
'/pet/findByStatus',
'/pet/findByTags',
'/pet/{petId}',
'/pet/{petId}/uploadImage',
'/store/inventory',
'/store/order',
'/store/order/{orderId}',
'/user',
'/user/createWithArray',
'/user/createWithList',
'/user/login',
'/user/logout',
'/user/{username}',
]);
expect(Object.keys(reducedSpec.paths['/pet/{petId}'])).toStrictEqual(['get', 'post', 'delete']);
expect(consoleWarnSpy).toHaveBeenCalledWith(
'⚠️ Warning! The input file is already OpenAPI, so no conversion is necessary. Any external references will be bundled.',
);

consoleWarnSpy.mockRestore();
});
});
});
2 changes: 1 addition & 1 deletion __tests__/lib/__snapshots__/commands.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ exports[`utils > #listByCategory > should list commands by category 1`] = `
"name": "openapi",
},
{
"description": "Convert a Swagger or Postman Collection to OpenAPI.",
"description": "Convert an API definition to OpenAPI and bundle any external references.",
"hidden": false,
"name": "openapi:convert",
},
Expand Down
2 changes: 1 addition & 1 deletion __tests__/single-threaded/openapi/convert.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import OpenAPIConvertCommand from '../../../src/cmds/openapi/convert.js';

const convert = new OpenAPIConvertCommand();

const successfulConversion = () => 'Your converted API definition has been saved to output.json!';
const successfulConversion = () => 'Your API definition has been converted and bundled and saved to output.json!';

describe('rdme openapi:convert (single-threaded)', () => {
let testWorkingDir: string;
Expand Down
16 changes: 10 additions & 6 deletions src/cmds/openapi/convert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default class OpenAPIConvertCommand extends Command {

this.command = 'openapi:convert';
this.usage = 'openapi:convert [file|url] [options]';
this.description = 'Convert a Swagger or Postman Collection to OpenAPI.';
this.description = 'Convert an API definition to OpenAPI and bundle any external references.';
this.cmdCategory = CommandCategories.APIS;

this.hiddenArgs = ['spec'];
Expand Down Expand Up @@ -58,7 +58,9 @@ export default class OpenAPIConvertCommand extends Command {
const parsedPreparedSpec: OASDocument = JSON.parse(preparedSpec);

if (specType === 'OpenAPI') {
throw new Error("Sorry, this API definition is already an OpenAPI definition and doesn't need to be converted.");
Command.warn(
'The input file is already OpenAPI, so no conversion is necessary. Any external references will be bundled.',
);
}

prompts.override({
Expand All @@ -69,7 +71,7 @@ export default class OpenAPIConvertCommand extends Command {
{
type: 'text',
name: 'outputPath',
message: 'Enter the path to save your converted API definition to:',
message: 'Enter the path to save your converted/bundled API definition to:',
initial: () => {
const extension = path.extname(specPath);
return `${path.basename(specPath).split(extension)[0]}.openapi${extension}`;
Expand All @@ -78,12 +80,14 @@ export default class OpenAPIConvertCommand extends Command {
},
]);

Command.debug(`saving converted spec to ${promptResults.outputPath}`);
Command.debug(`saving converted/bundled spec to ${promptResults.outputPath}`);

fs.writeFileSync(promptResults.outputPath, JSON.stringify(parsedPreparedSpec, null, 2));

Command.debug('converted spec saved');
Command.debug('converted/bundled spec saved');

return Promise.resolve(chalk.green(`Your converted API definition has been saved to ${promptResults.outputPath}!`));
return Promise.resolve(
chalk.green(`Your API definition has been converted and bundled and saved to ${promptResults.outputPath}!`),
);
}
}

0 comments on commit a33bbeb

Please sign in to comment.