feat: add test and improve code

This commit is contained in:
Alex Varchuk 2021-05-26 18:40:35 +03:00
parent 83ed6f3538
commit 6acdba5f7b
9 changed files with 256 additions and 43 deletions

View File

@ -1,4 +1,4 @@
openapi: 3.0.0 openapi: 3.1.0
servers: servers:
- url: //petstore.swagger.io/v2 - url: //petstore.swagger.io/v2
description: Default server description: Default server
@ -42,6 +42,7 @@ info:
version: 1.0.0 version: 1.0.0
title: Swagger Petstore title: Swagger Petstore
summary: My lovely API
termsOfService: 'http://swagger.io/terms/' termsOfService: 'http://swagger.io/terms/'
contact: contact:
name: API Support name: API Support
@ -53,6 +54,7 @@ info:
license: license:
name: Apache 2.0 name: Apache 2.0
url: 'http://www.apache.org/licenses/LICENSE-2.0.html' url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
identifier: Apache 2.0
externalDocs: externalDocs:
description: Find out how to create Github repo for your OpenAPI spec. description: Find out how to create Github repo for your OpenAPI spec.
url: 'https://github.com/Rebilly/generator-openapi-repo' url: 'https://github.com/Rebilly/generator-openapi-repo'
@ -893,6 +895,38 @@ paths:
default: default:
description: successful operation description: successful operation
components: components:
pathItems:
catsWebhook:
put:
summary: Get a cat details after update
description: Get a cat details after update
operationId: updatedCat
tags:
- pet
requestBody:
description: Information about cat in the system
content:
multipart/form-data:
schema:
$ref: "#/components/schemas/Cat"
responses:
'200':
description: update Cat details
post:
summary: Create new cat
description: Info about new cat
operationId: createdCat
tags:
- pet
requestBody:
description: Information about cat in the system
content:
multipart/form-data:
schema:
$ref: "#/components/schemas/Cat"
responses:
'200':
description: create Cat details
schemas: schemas:
ApiResponse: ApiResponse:
type: object type: object
@ -1040,7 +1074,8 @@ components:
example: Guru example: Guru
photoUrls: photoUrls:
description: The list of URL to a cute photos featuring pet description: The list of URL to a cute photos featuring pet
type: array type: [string, integer, 'null', array]
minItems: 1
maxItems: 20 maxItems: 20
xml: xml:
name: photoUrl name: photoUrl
@ -1054,7 +1089,8 @@ components:
tags: tags:
description: Tags attached to the pet description: Tags attached to the pet
type: array type: array
minItems: 1 exclusiveMaximum: 100
exclusiveMinimum: 0
xml: xml:
name: tag name: tag
wrapped: true wrapped: true
@ -1067,6 +1103,7 @@ components:
- available - available
- pending - pending
- sold - sold
default: pending
petType: petType:
description: Type of a pet description: Type of a pet
type: string type: string
@ -1187,13 +1224,13 @@ components:
shipDate: '2018-10-19T16:46:45Z' shipDate: '2018-10-19T16:46:45Z'
status: placed status: placed
complete: false complete: false
x-webhooks: webhooks:
newPet: newPet:
post: post:
summary: New pet summary: New pet
description: Information about a new pet in the systems description: Information about a new pet in the systems
operationId: newPet operationId: newPet
tags: tags:
- pet - pet
requestBody: requestBody:
content: content:
@ -1202,4 +1239,8 @@ x-webhooks:
$ref: "#/components/schemas/Pet" $ref: "#/components/schemas/Pet"
responses: responses:
"200": "200":
description: Return a 200 status to indicate that the data was received successfully description: Return a 200 status to indicate that the data was received successfully
myWebhook:
$ref: '#/components/pathItems/catsWebhook'
description: Overriding description
summary: Overriding summary

View File

@ -6,7 +6,7 @@ describe('Menu', () => {
it('should have valid items count', () => { it('should have valid items count', () => {
cy.get('.menu-content') cy.get('.menu-content')
.find('li') .find('li')
.should('have.length', 34); .should('have.length', 36);
}); });
it('should sync active menu items while scroll', () => { it('should sync active menu items while scroll', () => {

View File

@ -110,7 +110,7 @@ export class FieldDetails extends React.PureComponent<FieldProps, { patternShown
<ExternalDocumentation externalDocs={schema.externalDocs} compact={true} /> <ExternalDocumentation externalDocs={schema.externalDocs} compact={true} />
)} )}
{(renderDiscriminatorSwitch && renderDiscriminatorSwitch(this.props)) || null} {(renderDiscriminatorSwitch && renderDiscriminatorSwitch(this.props)) || null}
{field.const && (<FieldDetail label={'Value:'} value={field.const}/>) || null} {field.const && (<FieldDetail label={l('const') + ':'} value={field.const}/>) || null}
</div> </div>
); );
} }

View File

@ -6,7 +6,6 @@ import {
Referenced, Referenced,
OpenAPIServer, OpenAPIServer,
OpenAPIPaths, OpenAPIPaths,
OpenAPIPath,
} from '../types'; } from '../types';
import { import {
isOperationName, isOperationName,
@ -235,12 +234,11 @@ export class MenuBuilder {
for (const pathName of Object.keys(paths)) { for (const pathName of Object.keys(paths)) {
const path = paths[pathName]; const path = paths[pathName];
const operations = Object.keys(path).filter(isOperationName); const operations = Object.keys(path).filter(isOperationName);
for (let operationName of operations) { for (const operationName of operations) {
let operationInfo = path[operationName]; const operationInfo = path[operationName];
if (path.$ref) { if (path.$ref) {
const resolvedPath = parser.deref<OpenAPIPath>(path || {}) const resolvedPaths = parser.deref<OpenAPIPaths>(path as OpenAPIPaths);
operationName = Object.keys(resolvedPath)[0] getTags(parser, { [operationName]: resolvedPaths }, isWebhook);
operationInfo = resolvedPath[operationName]
} }
let operationTags = operationInfo?.tags; let operationTags = operationInfo?.tags;

View File

@ -0,0 +1,66 @@
{
"openapi": "3.1.0",
"info": {
"version": "1.0.0",
"title": "Swagger Petstore"
},
"webhooks": {
"myWebhook": {
"$ref": "#/components/pathItems/catsWebhook",
"description": "Overriding description",
"summary": "Overriding summary"
}
},
"components": {
"pathItems": {
"catsWebhook": {
"put": {
"summary": "Get a cat details after update",
"description": "Get a cat details after update",
"operationId": "updatedCat",
"tags": [
"pet"
],
"requestBody": {
"description": "Information about cat in the system",
"content": {
"multipart/form-data": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
}
}
},
"responses": {
"200": {
"description": "update Cat details"
}
}
},
"post": {
"summary": "Create new cat",
"description": "Info about new cat",
"operationId": "createdCat",
"tags": [
"pet"
],
"requestBody": {
"description": "Information about cat in the system",
"content": {
"multipart/form-data": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
}
}
},
"responses": {
"200": {
"description": "create Cat details"
}
}
}
}
}
}
}

View File

@ -46,5 +46,21 @@ describe('Models', () => {
const info = new ApiInfoModel(parser); const info = new ApiInfoModel(parser);
expect(info.summary).toEqual('Test summary\nsome text\n## Heading\n test'); expect(info.summary).toEqual('Test summary\nsome text\n## Heading\n test');
}); });
test('should correctly populate license identifier', () => {
parser.spec = {
openapi: '3.1.0',
info: {
license: {
name: 'MIT',
identifier: 'MIT',
url: 'https://opensource.org/licenses/MIT'
}
},
} as any;
const { license = { identifier: null } } = new ApiInfoModel(parser);
expect(license.identifier).toEqual('MIT');
});
}); });
}); });

View File

@ -0,0 +1,25 @@
/* eslint-disable @typescript-eslint/no-var-requires */
import { MenuBuilder } from '../../MenuBuilder';
import { OpenAPIParser } from '../../OpenAPIParser';
import { RedocNormalizedOptions } from '../../RedocNormalizedOptions';
const opts = new RedocNormalizedOptions({});
describe('Models', () => {
describe('MenuBuilder', () => {
let parser;
test('discriminator with one field', () => {
const spec = require('../fixtures/3.1/pathItems.json');
parser = new OpenAPIParser(spec, undefined, opts);
const contentItems = MenuBuilder.buildStructure(parser, opts);
expect(contentItems).toHaveLength(2);
expect(contentItems[0].items).toHaveLength(2);
expect(contentItems[0].id).toEqual('tag/pet');
expect(contentItems[0].name).toEqual('pet');
expect(contentItems[0].type).toEqual('tag');
});
});
});

View File

@ -14,16 +14,18 @@ export class WebhookModel {
) { ) {
const webhooks = parser.deref<OpenAPIPath>(infoOrRef || {}); const webhooks = parser.deref<OpenAPIPath>(infoOrRef || {});
parser.exitRef(infoOrRef); parser.exitRef(infoOrRef);
this.initWebhooks(parser, webhooks, options);
}
initWebhooks(parser: OpenAPIParser, webhooks: OpenAPIPath, options: RedocNormalizedOptions) {
for (const webhookName of Object.keys(webhooks)) { for (const webhookName of Object.keys(webhooks)) {
const webhook = webhooks[webhookName]; const webhook = webhooks[webhookName];
const operations = Object.keys(webhook).filter(isOperationName); const operations = Object.keys(webhook).filter(isOperationName);
for (let operationName of operations) { for (const operationName of operations) {
let operationInfo = webhook[operationName]; const operationInfo = webhook[operationName];
if (webhook.$ref) { if (webhook.$ref) {
const resolvedWebhook = parser.deref<OpenAPIPath>(webhook || {}); const resolvedWebhook = parser.deref<OpenAPIPath>(webhook || {});
operationName = Object.keys(resolvedWebhook)[0]; this.initWebhooks(parser, { [operationName]: resolvedWebhook }, options);
operationInfo = resolvedWebhook[operationName];
} }
if (!operationInfo) continue; if (!operationInfo) continue;

View File

@ -13,6 +13,56 @@ Object {
}, },
}, },
}, },
"pathItems": Object {
"catsWebhook": Object {
"post": Object {
"description": "Info about new cat",
"operationId": "createdCat",
"requestBody": Object {
"content": Object {
"multipart/form-data": Object {
"schema": Object {
"$ref": "#/components/schemas/Cat",
},
},
},
"description": "Information about cat in the system",
},
"responses": Object {
"200": Object {
"description": "create Cat details",
},
},
"summary": "Create new cat",
"tags": Array [
"pet",
],
},
"put": Object {
"description": "Get a cat details after update",
"operationId": "updatedCat",
"requestBody": Object {
"content": Object {
"multipart/form-data": Object {
"schema": Object {
"$ref": "#/components/schemas/Cat",
},
},
},
"description": "Information about cat in the system",
},
"responses": Object {
"200": Object {
"description": "update Cat details",
},
},
"summary": "Get a cat details after update",
"tags": Array [
"pet",
],
},
},
},
"requestBodies": Object { "requestBodies": Object {
"Pet": Object { "Pet": Object {
"content": Object { "content": Object {
@ -292,13 +342,20 @@ Object {
"type": "string", "type": "string",
}, },
"maxItems": 20, "maxItems": 20,
"type": "array", "minItems": 1,
"type": Array [
"string",
"integer",
"null",
"array",
],
"xml": Object { "xml": Object {
"name": "photoUrl", "name": "photoUrl",
"wrapped": true, "wrapped": true,
}, },
}, },
"status": Object { "status": Object {
"default": "pending",
"description": "Pet status in the store", "description": "Pet status in the store",
"enum": Array [ "enum": Array [
"available", "available",
@ -309,10 +366,11 @@ Object {
}, },
"tags": Object { "tags": Object {
"description": "Tags attached to the pet", "description": "Tags attached to the pet",
"exclusiveMaximum": 100,
"exclusiveMinimum": 0,
"items": Object { "items": Object {
"$ref": "#/components/schemas/Tag", "$ref": "#/components/schemas/Tag",
}, },
"minItems": 1,
"type": "array", "type": "array",
"xml": Object { "xml": Object {
"name": "tag", "name": "tag",
@ -485,9 +543,11 @@ and standard method from web, mobile and desktop applications.
<SecurityDefinitions /> <SecurityDefinitions />
", ",
"license": Object { "license": Object {
"identifier": "Apache 2.0",
"name": "Apache 2.0", "name": "Apache 2.0",
"url": "http://www.apache.org/licenses/LICENSE-2.0.html", "url": "http://www.apache.org/licenses/LICENSE-2.0.html",
}, },
"summary": "My lovely API",
"termsOfService": "http://swagger.io/terms/", "termsOfService": "http://swagger.io/terms/",
"title": "Swagger Petstore", "title": "Swagger Petstore",
"version": "1.0.0", "version": "1.0.0",
@ -496,7 +556,7 @@ and standard method from web, mobile and desktop applications.
"url": "https://redocly.github.io/redoc/petstore-logo.png", "url": "https://redocly.github.io/redoc/petstore-logo.png",
}, },
}, },
"openapi": "3.0.0", "openapi": "3.1.0",
"paths": Object { "paths": Object {
"/pet": Object { "/pet": Object {
"parameters": Array [ "parameters": Array [
@ -1745,29 +1805,12 @@ culpa qui officia deserunt mollit anim id est laborum.
"x-displayName": "The Order Model", "x-displayName": "The Order Model",
}, },
], ],
"x-tagGroups": Array [ "webhooks": Object {
Object { "myWebhook": Object {
"name": "General", "$ref": "#/components/pathItems/catsWebhook",
"tags": Array [ "description": "Overriding description",
"pet", "summary": "Overriding summary",
"store",
],
}, },
Object {
"name": "User Management",
"tags": Array [
"user",
],
},
Object {
"name": "Models",
"tags": Array [
"pet_model",
"store_model",
],
},
],
"x-webhooks": Object {
"newPet": Object { "newPet": Object {
"post": Object { "post": Object {
"description": "Information about a new pet in the systems", "description": "Information about a new pet in the systems",
@ -1793,6 +1836,28 @@ culpa qui officia deserunt mollit anim id est laborum.
}, },
}, },
}, },
"x-tagGroups": Array [
Object {
"name": "General",
"tags": Array [
"pet",
"store",
],
},
Object {
"name": "User Management",
"tags": Array [
"user",
],
},
Object {
"name": "Models",
"tags": Array [
"pet_model",
"store_model",
],
},
],
} }
`; `;