From 5029c3ce8aaf132d45b5b440c4bda3f86e84fe0e Mon Sep 17 00:00:00 2001 From: Swain Molster Date: Thu, 4 Aug 2022 11:08:20 -0400 Subject: [PATCH 1/3] add failing test --- .gitignore | 4 +-- src/bin/cli.test.ts | 66 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 67 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 6b82d14..bedc23b 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,5 @@ node_modules coverage .vscode dist/ -src/test-generated.js -src/test-generated.d.ts \ No newline at end of file +src/test-schema.json +src/test-generated.* \ No newline at end of file diff --git a/src/bin/cli.test.ts b/src/bin/cli.test.ts index fbdb648..b98402a 100644 --- a/src/bin/cli.test.ts +++ b/src/bin/cli.test.ts @@ -1,6 +1,7 @@ import { execSync } from 'child_process'; -import { writeFileSync } from 'fs'; +import { readFileSync, writeFileSync } from 'fs'; import { tmpNameSync } from 'tmp'; +import { OneSchemaDefinition } from '../types'; const executeCLI = (command: string): string => { try { @@ -14,6 +15,15 @@ const executeCLI = (command: string): string => { } }; +/** + * Writes the `schema`, and returns its filepath. + */ +const writeSchema = (schema: OneSchemaDefinition): string => { + const path = `${__dirname}/../test-schema.json`; + writeFileSync(path, JSON.stringify(schema, null, 2), { encoding: 'utf8' }); + return path; +}; + describe('schema validation snapshots', () => { const SCENARIOS: { test: string; @@ -78,3 +88,57 @@ describe('input validation snapshots', () => { }); }); }); + +describe('generate-open-api-spec', () => { + it('does not create new newlines when serializing + deserializing to YAML', () => { + const description = + 'This is a long description that might go over the js-yaml default line length.\nIt also contains newlines.\n\nLots of newlines!'; + + const path = writeSchema({ + Endpoints: { + 'GET /something': { + Name: 'getSomething', + Description: description, + Response: { + type: 'object', + }, + }, + }, + }); + + const output = `${__dirname}/../test-generated.yaml`; + + executeCLI( + `generate-open-api-spec --schema '${path}' --output '${output}' --apiTitle 'test title'`, + ); + + const yamlContent = readFileSync(output, { encoding: 'utf8' }); + + expect(yamlContent.trim()).toStrictEqual( + ` +openapi: 3.0.0 +info: + version: 1.0.0 + title: test title +components: {} +paths: + /something: + get: + operationId: getSomething + description: |- + This is a long description that might go over the js-yaml default line length. + It also contains newlines. + + Lots of newlines! + responses: + "200": + description: A successful response + content: + application/json: + schema: + additionalProperties: false + type: object +`.trim(), + ); + }); +}); From 93923a8434bf044de0561449e416b94f02257714 Mon Sep 17 00:00:00 2001 From: Swain Molster Date: Thu, 4 Aug 2022 11:18:21 -0400 Subject: [PATCH 2/3] fix: stop adding newlines to yaml output --- src/bin/cli.ts | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/bin/cli.ts b/src/bin/cli.ts index f9c72ef..e9eb101 100644 --- a/src/bin/cli.ts +++ b/src/bin/cli.ts @@ -179,7 +179,17 @@ const program = yargs(process.argv.slice(2)) const output = argv.output.endsWith('.yml') || argv.output.endsWith('.yaml') - ? dump(openAPISpec) + ? dump(openAPISpec, { + /** + * Without this, js-yaml will default to a line width of 80 and use + * "line folding". While this should not actually affect serialization + * or deserialization, it can result in ugly-looking output that contains + * newlines in unexpected places. + * + * This option allows us to preserve the original developer's newlines. + */ + lineWidth: -1, + }) : JSON.stringify(openAPISpec, null, 2); writeGeneratedFile(argv.output, output, { format: argv.format }); From ea8bd1981b6addf350881f3780d3b87ffdfa6430 Mon Sep 17 00:00:00 2001 From: Swain Molster Date: Thu, 4 Aug 2022 11:25:17 -0400 Subject: [PATCH 3/3] improve comment and assertion --- src/bin/cli.test.ts | 9 +++++++++ src/bin/cli.ts | 6 +++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/bin/cli.test.ts b/src/bin/cli.test.ts index b98402a..59f48d9 100644 --- a/src/bin/cli.test.ts +++ b/src/bin/cli.test.ts @@ -2,6 +2,7 @@ import { execSync } from 'child_process'; import { readFileSync, writeFileSync } from 'fs'; import { tmpNameSync } from 'tmp'; import { OneSchemaDefinition } from '../types'; +import * as yaml from 'js-yaml'; const executeCLI = (command: string): string => { try { @@ -114,6 +115,7 @@ describe('generate-open-api-spec', () => { const yamlContent = readFileSync(output, { encoding: 'utf8' }); + // Assert the output looks right. expect(yamlContent.trim()).toStrictEqual( ` openapi: 3.0.0 @@ -140,5 +142,12 @@ paths: type: object `.trim(), ); + + // Assert the output deserializes correctly. + const openapi: any = yaml.load(yamlContent); + + expect(openapi.paths['/something'].get.description).toStrictEqual( + description, + ); }); }); diff --git a/src/bin/cli.ts b/src/bin/cli.ts index e9eb101..9568887 100644 --- a/src/bin/cli.ts +++ b/src/bin/cli.ts @@ -182,9 +182,9 @@ const program = yargs(process.argv.slice(2)) ? dump(openAPISpec, { /** * Without this, js-yaml will default to a line width of 80 and use - * "line folding". While this should not actually affect serialization - * or deserialization, it can result in ugly-looking output that contains - * newlines in unexpected places. + * the "folded" multiline style. While this should not actually affect + * serialization or deserialization, it can result in ugly-looking output + * that contains newlines in unexpected places. * * This option allows us to preserve the original developer's newlines. */