initial implementation of openapi 3
This commit is contained in:
parent
af5210e4dc
commit
97509b561b
|
@ -1,7 +1,8 @@
|
|||
import { queryValidation } from "../validation"
|
||||
import { generateQueryID } from "../../../../db/utils"
|
||||
import { ImportInfo, ImportSource } from "./sources/base"
|
||||
import { OpenAPI2 } from "./sources/openapi2"
|
||||
import { OpenAPI3 } from "./sources/openapi2"
|
||||
import { OpenAPI3 } from "./sources/openapi3"
|
||||
import { Query } from "./../../../../definitions/common"
|
||||
import { Curl } from "./sources/curl"
|
||||
// @ts-ignore
|
||||
|
@ -18,7 +19,7 @@ export class RestImporter {
|
|||
|
||||
constructor(data: string) {
|
||||
this.data = data
|
||||
this.sources = [new OpenAPI2(), new Curl()]
|
||||
this.sources = [new OpenAPI3(), new OpenAPI3(), new Curl()]
|
||||
}
|
||||
|
||||
init = async () => {
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
import { ImportInfo } from "./base"
|
||||
import { Query, QueryParameter } from "../../../../../definitions/datasource"
|
||||
import { OpenAPIV3 } from "openapi-types"
|
||||
import { OpenAPISource } from "./base/openapi"
|
||||
import { URL } from "url"
|
||||
import {
|
||||
getGlobalDB,
|
||||
getTenantId,
|
||||
isMultiTenant,
|
||||
} from "@budibase/backend-core/tenancy"
|
||||
import { getScopedConfig } from "@budibase/backend-core/db"
|
||||
|
||||
const jsonMimeType = "application/json"
|
||||
const parameterNotRef = (
|
||||
param: OpenAPIV3.ParameterObject | OpenAPIV3.ReferenceObject
|
||||
): param is OpenAPIV3.ParameterObject => {
|
||||
// all refs are deferenced by parser library
|
||||
return true
|
||||
}
|
||||
|
||||
const requestBodyNotRef = (
|
||||
param: OpenAPIV3.RequestBodyObject | OpenAPIV3.ReferenceObject | undefined
|
||||
): param is OpenAPIV3.RequestBodyObject => {
|
||||
// all refs are deferenced by parser library
|
||||
return param !== undefined
|
||||
}
|
||||
|
||||
const isOpenAPI3 = (document: any): document is OpenAPIV3.Document => {
|
||||
return document.openapi.includes("3")
|
||||
}
|
||||
|
||||
const methods: string[] = Object.values(OpenAPIV3.HttpMethods)
|
||||
|
||||
const isOperation = (
|
||||
key: string,
|
||||
pathItem: any
|
||||
): pathItem is OpenAPIV3.OperationObject => {
|
||||
return methods.includes(key)
|
||||
}
|
||||
|
||||
const isParameter = (
|
||||
key: string,
|
||||
pathItem: any
|
||||
): pathItem is OpenAPIV3.ParameterObject => {
|
||||
return !isOperation(key, pathItem)
|
||||
}
|
||||
|
||||
const getRequestBody = (operation: OpenAPIV3.OperationObject) => {
|
||||
if (requestBodyNotRef(operation.requestBody)) {
|
||||
const request: OpenAPIV3.RequestBodyObject =
|
||||
operation.requestBody as OpenAPIV3.RequestBodyObject
|
||||
return request.content[jsonMimeType]?.example
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* OpenAPI Version 3.1 - aka "Swagger"
|
||||
* https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md
|
||||
*/
|
||||
export class OpenAPI3 extends OpenAPISource {
|
||||
document!: OpenAPIV3.Document
|
||||
|
||||
isSupported = async (data: string): Promise<boolean> => {
|
||||
try {
|
||||
const document: any = await this.parseData(data)
|
||||
if (isOpenAPI3(document)) {
|
||||
this.document = document
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
} catch (err) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
getPlatformUrl = async (): Promise<string> => {
|
||||
const db = getGlobalDB()
|
||||
const publicConfig = await getScopedConfig(db, {
|
||||
type: "settings",
|
||||
})
|
||||
|
||||
let url = publicConfig.platformUrl
|
||||
if (isMultiTenant()) {
|
||||
url += `/${getTenantId()}`
|
||||
}
|
||||
return url
|
||||
}
|
||||
|
||||
getUrl = async (): Promise<URL> => {
|
||||
const platformUrl = await this.getPlatformUrl()
|
||||
let url = this.document.servers ? this.document.servers[0].url : null
|
||||
if (url) {
|
||||
// check if url is relative or absolute
|
||||
if (url.includes("http") || url.includes("https")) {
|
||||
return new URL(url)
|
||||
}
|
||||
|
||||
return new URL(`${platformUrl}${url}`)
|
||||
}
|
||||
// if the specification doesn't contain a servers object, return the PLATFORM_URM environment variable
|
||||
return new URL(platformUrl)
|
||||
}
|
||||
|
||||
getInfo = async (): Promise<ImportInfo> => {
|
||||
const name = this.document.info.title || "Swagger Import"
|
||||
return {
|
||||
name,
|
||||
}
|
||||
}
|
||||
|
||||
getQueries = async (datasourceId: string): Promise<Query[]> => {
|
||||
const url: URL = await this.getUrl()
|
||||
const queries: Query[] = []
|
||||
|
||||
for (let [path, pathItemObject] of Object.entries(this.document.paths)) {
|
||||
// parameters that apply to every operation in the path
|
||||
let pathParams: OpenAPIV3.ParameterObject[] = []
|
||||
|
||||
// pathItemObject can be undefined
|
||||
if (!pathItemObject) {
|
||||
continue
|
||||
}
|
||||
|
||||
for (let [key, opOrParams] of Object.entries(pathItemObject)) {
|
||||
if (isParameter(key, opOrParams)) {
|
||||
const pathParameters = opOrParams as OpenAPIV3.ParameterObject[]
|
||||
pathParams.push(...pathParameters)
|
||||
continue
|
||||
}
|
||||
// can not be a parameter, must be an operation
|
||||
const operation = opOrParams as OpenAPIV3.OperationObject
|
||||
|
||||
const methodName = key
|
||||
const name = operation.operationId || path
|
||||
let queryString = ""
|
||||
const headers: any = {}
|
||||
let requestBody = getRequestBody(operation)
|
||||
const parameters: QueryParameter[] = []
|
||||
|
||||
// combine the path parameters with the operation parameters
|
||||
const operationParams = operation.parameters || []
|
||||
const allParams = [...pathParams, ...operationParams]
|
||||
|
||||
for (let param of allParams) {
|
||||
if (parameterNotRef(param)) {
|
||||
switch (param.in) {
|
||||
case "query":
|
||||
let prefix = ""
|
||||
if (queryString) {
|
||||
prefix = "&"
|
||||
}
|
||||
queryString = `${queryString}${prefix}${param.name}={{${param.name}}}`
|
||||
break
|
||||
case "header":
|
||||
headers[param.name] = `{{${param.name}}}`
|
||||
break
|
||||
case "path":
|
||||
// do nothing: param is already in the path
|
||||
break
|
||||
case "formData":
|
||||
// future enhancement
|
||||
break
|
||||
}
|
||||
|
||||
// add the parameter if it can be bound in our config
|
||||
if (["query", "header", "path"].includes(param.in)) {
|
||||
parameters.push({
|
||||
name: param.name,
|
||||
default: "",
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const query = this.constructQuery(
|
||||
datasourceId,
|
||||
name,
|
||||
methodName,
|
||||
path,
|
||||
url,
|
||||
queryString,
|
||||
headers,
|
||||
parameters,
|
||||
requestBody
|
||||
)
|
||||
queries.push(query)
|
||||
}
|
||||
}
|
||||
|
||||
return queries
|
||||
}
|
||||
}
|
|
@ -0,0 +1,231 @@
|
|||
{
|
||||
"openapi": "3.0.2",
|
||||
"info": {
|
||||
"description": "A basic swagger file",
|
||||
"version": "1.0.0",
|
||||
"title": "CRUD"
|
||||
},
|
||||
"tags": [
|
||||
{
|
||||
"name": "entity"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"/entities": {
|
||||
"post": {
|
||||
"tags": [
|
||||
"entity"
|
||||
],
|
||||
"operationId": "createEntity",
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/schemas/CreateEntityParameter"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "successful operation",
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"get": {
|
||||
"tags": [
|
||||
"entity"
|
||||
],
|
||||
"operationId": "getEntities",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/schemas/PageParameter"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/SizeParameter"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "successful operation",
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Entities"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/entities/{entityId}": {
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/schemas/EntityIdParameter"
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
"tags": [
|
||||
"entity"
|
||||
],
|
||||
"operationId": "getEntity",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "successful operation",
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"put": {
|
||||
"tags": [
|
||||
"entity"
|
||||
],
|
||||
"operationId": "updateEntity",
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/schemas/EntityParameter"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "successful operation",
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"patch": {
|
||||
"tags": [
|
||||
"entity"
|
||||
],
|
||||
"operationId": "patchEntity",
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/schemas/EntityParameter"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "successful operation",
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"tags": [
|
||||
"entity"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "x-api-key",
|
||||
"in": "header",
|
||||
"required": false
|
||||
}
|
||||
],
|
||||
"operationId": "deleteEntity",
|
||||
"responses": {
|
||||
"204": {
|
||||
"description": "successful operation"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"EntityIdParameter": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"name": "entityId",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
"CreateEntityParameter": {
|
||||
"name": "entity",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/CreateEntity"
|
||||
}
|
||||
},
|
||||
"EntityParameter": {
|
||||
"name": "entity",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Entity"
|
||||
}
|
||||
},
|
||||
"PageParameter": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"name": "page",
|
||||
"in": "query",
|
||||
"required": false
|
||||
},
|
||||
"SizeParameter": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"name": "size",
|
||||
"in": "query",
|
||||
"required": false
|
||||
},
|
||||
"APIKeyParameter": {
|
||||
"type": "string",
|
||||
"name": "x-api-key",
|
||||
"in": "header",
|
||||
"required": false
|
||||
},
|
||||
"CreateEntity": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"type": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"example": {
|
||||
"name": "name",
|
||||
"type": "type"
|
||||
}
|
||||
},
|
||||
"Entity": {
|
||||
"allOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/CreateEntity"
|
||||
}
|
||||
],
|
||||
"example": {
|
||||
"id": 1,
|
||||
"name": "name",
|
||||
"type": "type"
|
||||
}
|
||||
},
|
||||
"Entities" : {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/Entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
---
|
||||
openapi: "3.0.2"
|
||||
info:
|
||||
description: A basic swagger file
|
||||
version: 1.0.0
|
||||
title: CRUD
|
||||
host: example.com
|
||||
tags:
|
||||
- name: entity
|
||||
paths:
|
||||
"/entities":
|
||||
post:
|
||||
tags:
|
||||
- entity
|
||||
operationId: createEntity
|
||||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- "$ref": "#/parameters/CreateEntity"
|
||||
responses:
|
||||
"200":
|
||||
description: successful operation
|
||||
schema:
|
||||
"$ref": "#/definitions/Entity"
|
||||
get:
|
||||
tags:
|
||||
- entity
|
||||
operationId: getEntities
|
||||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- "$ref": "#/parameters/Page"
|
||||
- "$ref": "#/parameters/Size"
|
||||
responses:
|
||||
"200":
|
||||
description: successful operation
|
||||
schema:
|
||||
"$ref": "#/definitions/Entities"
|
||||
"/entities/{entityId}":
|
||||
parameters:
|
||||
- "$ref": "#/parameters/EntityId"
|
||||
get:
|
||||
tags:
|
||||
- entity
|
||||
operationId: getEntity
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: successful operation
|
||||
schema:
|
||||
"$ref": "#/definitions/Entity"
|
||||
put:
|
||||
tags:
|
||||
- entity
|
||||
operationId: updateEntity
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- "$ref": "#/parameters/Entity"
|
||||
responses:
|
||||
"200":
|
||||
description: successful operation
|
||||
schema:
|
||||
"$ref": "#/definitions/Entity"
|
||||
patch:
|
||||
tags:
|
||||
- entity
|
||||
operationId: patchEntity
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- "$ref": "#/parameters/Entity"
|
||||
responses:
|
||||
"200":
|
||||
description: successful operation
|
||||
schema:
|
||||
"$ref": "#/definitions/Entity"
|
||||
delete:
|
||||
tags:
|
||||
- entity
|
||||
parameters:
|
||||
- "$ref": "#/parameters/APIKey"
|
||||
operationId: deleteEntity
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"204":
|
||||
description: successful operation
|
||||
parameters:
|
||||
EntityId:
|
||||
type: integer
|
||||
format: int64
|
||||
name: entityId
|
||||
in: path
|
||||
required: true
|
||||
CreateEntity:
|
||||
name: entity
|
||||
in: body
|
||||
required: true
|
||||
schema:
|
||||
"$ref": "#/definitions/CreateEntity"
|
||||
Entity:
|
||||
name: entity
|
||||
in: body
|
||||
required: true
|
||||
schema:
|
||||
"$ref": "#/definitions/Entity"
|
||||
Page:
|
||||
type: integer
|
||||
format: int32
|
||||
name: page
|
||||
in: query
|
||||
required: false
|
||||
Size:
|
||||
type: integer
|
||||
format: int32
|
||||
name: size
|
||||
in: query
|
||||
required: false
|
||||
APIKey:
|
||||
type: string
|
||||
name: x-api-key
|
||||
in: header
|
||||
required: false
|
||||
definitions:
|
||||
CreateEntity:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
example:
|
||||
name: name
|
||||
type: type
|
||||
Entity:
|
||||
allOf:
|
||||
- type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
- "$ref": "#/definitions/CreateEntity"
|
||||
example:
|
||||
id: 1
|
||||
name: name
|
||||
type: type
|
||||
Entities:
|
||||
type: array
|
||||
items:
|
||||
"$ref": "#/definitions/Entity"
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,804 @@
|
|||
---
|
||||
openapi: 3.0.2
|
||||
info:
|
||||
title: Swagger Petstore - OpenAPI 3.0
|
||||
description: |-
|
||||
This is a sample Pet Store Server based on the OpenAPI 3.0 specification. You can find out more about
|
||||
Swagger at [http://swagger.io](http://swagger.io). In the third iteration of the pet store, we've switched to the design first approach!
|
||||
You can now help us improve the API whether it's by making changes to the definition itself or to the code.
|
||||
That way, with time, we can improve the API in general, and expose some of the new features in OAS3.
|
||||
|
||||
Some useful links:
|
||||
- [The Pet Store repository](https://github.com/swagger-api/swagger-petstore)
|
||||
- [The source API definition for the Pet Store](https://github.com/swagger-api/swagger-petstore/blob/master/src/main/resources/openapi.yaml)
|
||||
termsOfService: http://swagger.io/terms/
|
||||
contact:
|
||||
email: apiteam@swagger.io
|
||||
license:
|
||||
name: Apache 2.0
|
||||
url: http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
version: 1.0.11
|
||||
externalDocs:
|
||||
description: Find out more about Swagger
|
||||
url: http://swagger.io
|
||||
servers:
|
||||
- url: "/api/v3"
|
||||
tags:
|
||||
- name: pet
|
||||
description: Everything about your Pets
|
||||
externalDocs:
|
||||
description: Find out more
|
||||
url: http://swagger.io
|
||||
- name: store
|
||||
description: Access to Petstore orders
|
||||
externalDocs:
|
||||
description: Find out more about our store
|
||||
url: http://swagger.io
|
||||
- name: user
|
||||
description: Operations about user
|
||||
paths:
|
||||
"/pet":
|
||||
put:
|
||||
tags:
|
||||
- pet
|
||||
summary: Update an existing pet
|
||||
description: Update an existing pet by Id
|
||||
operationId: updatePet
|
||||
requestBody:
|
||||
description: Update an existent pet in the store
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
application/xml:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
application/x-www-form-urlencoded:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
required: true
|
||||
responses:
|
||||
'200':
|
||||
description: Successful operation
|
||||
content:
|
||||
application/xml:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
'400':
|
||||
description: Invalid ID supplied
|
||||
'404':
|
||||
description: Pet not found
|
||||
'405':
|
||||
description: Validation exception
|
||||
security:
|
||||
- petstore_auth:
|
||||
- write:pets
|
||||
- read:pets
|
||||
post:
|
||||
tags:
|
||||
- pet
|
||||
summary: Add a new pet to the store
|
||||
description: Add a new pet to the store
|
||||
operationId: addPet
|
||||
requestBody:
|
||||
description: Create a new pet in the store
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
application/xml:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
application/x-www-form-urlencoded:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
required: true
|
||||
responses:
|
||||
'200':
|
||||
description: Successful operation
|
||||
content:
|
||||
application/xml:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
'405':
|
||||
description: Invalid input
|
||||
security:
|
||||
- petstore_auth:
|
||||
- write:pets
|
||||
- read:pets
|
||||
"/pet/findByStatus":
|
||||
get:
|
||||
tags:
|
||||
- pet
|
||||
summary: Finds Pets by status
|
||||
description: Multiple status values can be provided with comma separated strings
|
||||
operationId: findPetsByStatus
|
||||
parameters:
|
||||
- name: status
|
||||
in: query
|
||||
description: Status values that need to be considered for filter
|
||||
required: false
|
||||
explode: true
|
||||
schema:
|
||||
type: string
|
||||
default: available
|
||||
enum:
|
||||
- available
|
||||
- pending
|
||||
- sold
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
content:
|
||||
application/xml:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
'400':
|
||||
description: Invalid status value
|
||||
security:
|
||||
- petstore_auth:
|
||||
- write:pets
|
||||
- read:pets
|
||||
"/pet/findByTags":
|
||||
get:
|
||||
tags:
|
||||
- pet
|
||||
summary: Finds Pets by tags
|
||||
description: Multiple tags can be provided with comma separated strings. Use
|
||||
tag1, tag2, tag3 for testing.
|
||||
operationId: findPetsByTags
|
||||
parameters:
|
||||
- name: tags
|
||||
in: query
|
||||
description: Tags to filter by
|
||||
required: false
|
||||
explode: true
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
content:
|
||||
application/xml:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
'400':
|
||||
description: Invalid tag value
|
||||
security:
|
||||
- petstore_auth:
|
||||
- write:pets
|
||||
- read:pets
|
||||
"/pet/{petId}":
|
||||
get:
|
||||
tags:
|
||||
- pet
|
||||
summary: Find pet by ID
|
||||
description: Returns a single pet
|
||||
operationId: getPetById
|
||||
parameters:
|
||||
- name: petId
|
||||
in: path
|
||||
description: ID of pet to return
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
content:
|
||||
application/xml:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
'400':
|
||||
description: Invalid ID supplied
|
||||
'404':
|
||||
description: Pet not found
|
||||
security:
|
||||
- api_key: []
|
||||
- petstore_auth:
|
||||
- write:pets
|
||||
- read:pets
|
||||
post:
|
||||
tags:
|
||||
- pet
|
||||
summary: Updates a pet in the store with form data
|
||||
description: ''
|
||||
operationId: updatePetWithForm
|
||||
parameters:
|
||||
- name: petId
|
||||
in: path
|
||||
description: ID of pet that needs to be updated
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
- name: name
|
||||
in: query
|
||||
description: Name of pet that needs to be updated
|
||||
schema:
|
||||
type: string
|
||||
- name: status
|
||||
in: query
|
||||
description: Status of pet that needs to be updated
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'405':
|
||||
description: Invalid input
|
||||
security:
|
||||
- petstore_auth:
|
||||
- write:pets
|
||||
- read:pets
|
||||
delete:
|
||||
tags:
|
||||
- pet
|
||||
summary: Deletes a pet
|
||||
description: ''
|
||||
operationId: deletePet
|
||||
parameters:
|
||||
- name: api_key
|
||||
in: header
|
||||
description: ''
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
- name: petId
|
||||
in: path
|
||||
description: Pet id to delete
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
responses:
|
||||
'400':
|
||||
description: Invalid pet value
|
||||
security:
|
||||
- petstore_auth:
|
||||
- write:pets
|
||||
- read:pets
|
||||
"/pet/{petId}/uploadImage":
|
||||
post:
|
||||
tags:
|
||||
- pet
|
||||
summary: uploads an image
|
||||
description: ''
|
||||
operationId: uploadFile
|
||||
parameters:
|
||||
- name: petId
|
||||
in: path
|
||||
description: ID of pet to update
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
- name: additionalMetadata
|
||||
in: query
|
||||
description: Additional Metadata
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
content:
|
||||
application/octet-stream:
|
||||
schema:
|
||||
type: string
|
||||
format: binary
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/ApiResponse"
|
||||
security:
|
||||
- petstore_auth:
|
||||
- write:pets
|
||||
- read:pets
|
||||
"/store/inventory":
|
||||
get:
|
||||
tags:
|
||||
- store
|
||||
summary: Returns pet inventories by status
|
||||
description: Returns a map of status codes to quantities
|
||||
operationId: getInventory
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: integer
|
||||
format: int32
|
||||
security:
|
||||
- api_key: []
|
||||
"/store/order":
|
||||
post:
|
||||
tags:
|
||||
- store
|
||||
summary: Place an order for a pet
|
||||
description: Place a new order in the store
|
||||
operationId: placeOrder
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Order"
|
||||
application/xml:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Order"
|
||||
application/x-www-form-urlencoded:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Order"
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Order"
|
||||
'405':
|
||||
description: Invalid input
|
||||
"/store/order/{orderId}":
|
||||
get:
|
||||
tags:
|
||||
- store
|
||||
summary: Find purchase order by ID
|
||||
description: For valid response try integer IDs with value <= 5 or > 10. Other
|
||||
values will generate exceptions.
|
||||
operationId: getOrderById
|
||||
parameters:
|
||||
- name: orderId
|
||||
in: path
|
||||
description: ID of order that needs to be fetched
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
content:
|
||||
application/xml:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Order"
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Order"
|
||||
'400':
|
||||
description: Invalid ID supplied
|
||||
'404':
|
||||
description: Order not found
|
||||
delete:
|
||||
tags:
|
||||
- store
|
||||
summary: Delete purchase order by ID
|
||||
description: For valid response try integer IDs with value < 1000. Anything
|
||||
above 1000 or nonintegers will generate API errors
|
||||
operationId: deleteOrder
|
||||
parameters:
|
||||
- name: orderId
|
||||
in: path
|
||||
description: ID of the order that needs to be deleted
|
||||
required: true
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
responses:
|
||||
'400':
|
||||
description: Invalid ID supplied
|
||||
'404':
|
||||
description: Order not found
|
||||
"/user":
|
||||
post:
|
||||
tags:
|
||||
- user
|
||||
summary: Create user
|
||||
description: This can only be done by the logged in user.
|
||||
operationId: createUser
|
||||
requestBody:
|
||||
description: Created user object
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/User"
|
||||
application/xml:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/User"
|
||||
application/x-www-form-urlencoded:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/User"
|
||||
responses:
|
||||
default:
|
||||
description: successful operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/User"
|
||||
application/xml:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/User"
|
||||
"/user/createWithList":
|
||||
post:
|
||||
tags:
|
||||
- user
|
||||
summary: Creates list of users with given input array
|
||||
description: Creates list of users with given input array
|
||||
operationId: createUsersWithListInput
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
"$ref": "#/components/schemas/User"
|
||||
responses:
|
||||
'200':
|
||||
description: Successful operation
|
||||
content:
|
||||
application/xml:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/User"
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/User"
|
||||
default:
|
||||
description: successful operation
|
||||
"/user/login":
|
||||
get:
|
||||
tags:
|
||||
- user
|
||||
summary: Logs user into the system
|
||||
description: ''
|
||||
operationId: loginUser
|
||||
parameters:
|
||||
- name: username
|
||||
in: query
|
||||
description: The user name for login
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
- name: password
|
||||
in: query
|
||||
description: The password for login in clear text
|
||||
required: false
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
headers:
|
||||
X-Rate-Limit:
|
||||
description: calls per hour allowed by the user
|
||||
schema:
|
||||
type: integer
|
||||
format: int32
|
||||
X-Expires-After:
|
||||
description: date in UTC when token expires
|
||||
schema:
|
||||
type: string
|
||||
format: date-time
|
||||
content:
|
||||
application/xml:
|
||||
schema:
|
||||
type: string
|
||||
application/json:
|
||||
schema:
|
||||
type: string
|
||||
'400':
|
||||
description: Invalid username/password supplied
|
||||
"/user/logout":
|
||||
get:
|
||||
tags:
|
||||
- user
|
||||
summary: Logs out current logged in user session
|
||||
description: ''
|
||||
operationId: logoutUser
|
||||
parameters: []
|
||||
responses:
|
||||
default:
|
||||
description: successful operation
|
||||
"/user/{username}":
|
||||
get:
|
||||
tags:
|
||||
- user
|
||||
summary: Get user by user name
|
||||
description: ''
|
||||
operationId: getUserByName
|
||||
parameters:
|
||||
- name: username
|
||||
in: path
|
||||
description: 'The name that needs to be fetched. Use user1 for testing. '
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'200':
|
||||
description: successful operation
|
||||
content:
|
||||
application/xml:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/User"
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/User"
|
||||
'400':
|
||||
description: Invalid username supplied
|
||||
'404':
|
||||
description: User not found
|
||||
put:
|
||||
tags:
|
||||
- user
|
||||
summary: Update user
|
||||
description: This can only be done by the logged in user.
|
||||
operationId: updateUser
|
||||
parameters:
|
||||
- name: username
|
||||
in: path
|
||||
description: name that need to be deleted
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
description: Update an existent user in the store
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/User"
|
||||
application/xml:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/User"
|
||||
application/x-www-form-urlencoded:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/User"
|
||||
responses:
|
||||
default:
|
||||
description: successful operation
|
||||
delete:
|
||||
tags:
|
||||
- user
|
||||
summary: Delete user
|
||||
description: This can only be done by the logged in user.
|
||||
operationId: deleteUser
|
||||
parameters:
|
||||
- name: username
|
||||
in: path
|
||||
description: The name that needs to be deleted
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
'400':
|
||||
description: Invalid username supplied
|
||||
'404':
|
||||
description: User not found
|
||||
components:
|
||||
schemas:
|
||||
Order:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
example: 10
|
||||
petId:
|
||||
type: integer
|
||||
format: int64
|
||||
example: 198772
|
||||
quantity:
|
||||
type: integer
|
||||
format: int32
|
||||
example: 7
|
||||
shipDate:
|
||||
type: string
|
||||
format: date-time
|
||||
status:
|
||||
type: string
|
||||
description: Order Status
|
||||
example: approved
|
||||
enum:
|
||||
- placed
|
||||
- approved
|
||||
- delivered
|
||||
complete:
|
||||
type: boolean
|
||||
xml:
|
||||
name: order
|
||||
Customer:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
example: 100000
|
||||
username:
|
||||
type: string
|
||||
example: fehguy
|
||||
address:
|
||||
type: array
|
||||
xml:
|
||||
name: addresses
|
||||
wrapped: true
|
||||
items:
|
||||
"$ref": "#/components/schemas/Address"
|
||||
xml:
|
||||
name: customer
|
||||
Address:
|
||||
type: object
|
||||
properties:
|
||||
street:
|
||||
type: string
|
||||
example: 437 Lytton
|
||||
city:
|
||||
type: string
|
||||
example: Palo Alto
|
||||
state:
|
||||
type: string
|
||||
example: CA
|
||||
zip:
|
||||
type: string
|
||||
example: '94301'
|
||||
xml:
|
||||
name: address
|
||||
Category:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
example: 1
|
||||
name:
|
||||
type: string
|
||||
example: Dogs
|
||||
xml:
|
||||
name: category
|
||||
User:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
example: 10
|
||||
username:
|
||||
type: string
|
||||
example: theUser
|
||||
firstName:
|
||||
type: string
|
||||
example: John
|
||||
lastName:
|
||||
type: string
|
||||
example: James
|
||||
email:
|
||||
type: string
|
||||
example: john@email.com
|
||||
password:
|
||||
type: string
|
||||
example: '12345'
|
||||
phone:
|
||||
type: string
|
||||
example: '12345'
|
||||
userStatus:
|
||||
type: integer
|
||||
description: User Status
|
||||
format: int32
|
||||
example: 1
|
||||
xml:
|
||||
name: user
|
||||
Tag:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
name:
|
||||
type: string
|
||||
xml:
|
||||
name: tag
|
||||
Pet:
|
||||
required:
|
||||
- name
|
||||
- photoUrls
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
format: int64
|
||||
example: 10
|
||||
name:
|
||||
type: string
|
||||
example: doggie
|
||||
category:
|
||||
"$ref": "#/components/schemas/Category"
|
||||
photoUrls:
|
||||
type: array
|
||||
xml:
|
||||
wrapped: true
|
||||
items:
|
||||
type: string
|
||||
xml:
|
||||
name: photoUrl
|
||||
tags:
|
||||
type: array
|
||||
xml:
|
||||
wrapped: true
|
||||
items:
|
||||
"$ref": "#/components/schemas/Tag"
|
||||
status:
|
||||
type: string
|
||||
description: pet status in the store
|
||||
enum:
|
||||
- available
|
||||
- pending
|
||||
- sold
|
||||
xml:
|
||||
name: pet
|
||||
ApiResponse:
|
||||
type: object
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
format: int32
|
||||
type:
|
||||
type: string
|
||||
message:
|
||||
type: string
|
||||
xml:
|
||||
name: "##default"
|
||||
requestBodies:
|
||||
Pet:
|
||||
description: Pet object that needs to be added to the store
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
application/xml:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Pet"
|
||||
UserArray:
|
||||
description: List of user object
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
"$ref": "#/components/schemas/User"
|
||||
securitySchemes:
|
||||
petstore_auth:
|
||||
type: oauth2
|
||||
flows:
|
||||
implicit:
|
||||
authorizationUrl: https://petstore3.swagger.io/oauth/authorize
|
||||
scopes:
|
||||
write:pets: modify pets in your account
|
||||
read:pets: read your pets
|
||||
api_key:
|
||||
type: apiKey
|
||||
name: api_key
|
||||
in: header
|
|
@ -0,0 +1,256 @@
|
|||
const fs = require("fs")
|
||||
const path = require("path")
|
||||
const getGlobalDB = jest.fn().mockReturnValue("db")
|
||||
const getTenantId = jest.fn().mockReturnValue("1")
|
||||
const isMultiTenant = jest.fn().mockReturnValue(true)
|
||||
const getScopedConfig = jest
|
||||
.fn()
|
||||
.mockResolvedValue({ platformUrl: "somePlatform" })
|
||||
|
||||
jest.mock("@budibase/backend-core/db", () => ({
|
||||
getScopedConfig,
|
||||
}))
|
||||
|
||||
jest.mock("@budibase/backend-core/tenancy", () => ({
|
||||
getTenantId,
|
||||
getGlobalDB,
|
||||
isMultiTenant,
|
||||
}))
|
||||
const { OpenAPI3 } = require("../../openapi3")
|
||||
|
||||
const getData = (file, extension) => {
|
||||
return fs.readFileSync(
|
||||
path.join(__dirname, `./data/${file}/${file}.${extension}`),
|
||||
"utf8"
|
||||
)
|
||||
}
|
||||
|
||||
describe("OpenAPI3 Import", () => {
|
||||
let openapi3
|
||||
|
||||
beforeEach(() => {
|
||||
openapi3 = new OpenAPI3()
|
||||
})
|
||||
|
||||
it("validates unsupported data", async () => {
|
||||
let data
|
||||
let supported
|
||||
|
||||
// non json / yaml
|
||||
data = "curl http://example.com"
|
||||
supported = await openapi3.isSupported(data)
|
||||
expect(supported).toBe(false)
|
||||
|
||||
// Empty
|
||||
data = ""
|
||||
supported = await openapi3.isSupported(data)
|
||||
expect(supported).toBe(false)
|
||||
})
|
||||
|
||||
const runTests = async (filename, test, assertions) => {
|
||||
/*for (let extension of ["json", "yaml"]) {
|
||||
await test(filename, extension, assertions)
|
||||
}*/
|
||||
await test(filename, "json", assertions)
|
||||
}
|
||||
|
||||
const testImportInfo = async (file, extension) => {
|
||||
await openapi3.isSupported(getData(file, extension))
|
||||
const info = await openapi3.getInfo()
|
||||
expect(info.name).toBe("Swagger Petstore - OpenAPI 3.0")
|
||||
}
|
||||
|
||||
it("returns import info", async () => {
|
||||
await runTests("petstore", testImportInfo)
|
||||
})
|
||||
|
||||
describe("Returns queries", () => {
|
||||
const indexQueries = queries => {
|
||||
return queries.reduce((acc, query) => {
|
||||
acc[query.name] = query
|
||||
return acc
|
||||
}, {})
|
||||
}
|
||||
|
||||
const getQueries = async (file, extension) => {
|
||||
await openapi3.isSupported(getData(file, extension))
|
||||
const queries = await openapi3.getQueries()
|
||||
expect(queries.length).toBe(6)
|
||||
return indexQueries(queries)
|
||||
}
|
||||
|
||||
const testVerb = async (file, extension, assertions) => {
|
||||
const queries = await getQueries(file, extension)
|
||||
for (let [operationId, method] of Object.entries(assertions)) {
|
||||
expect(queries[operationId].queryVerb).toBe(method)
|
||||
}
|
||||
}
|
||||
|
||||
it("populates verb", async () => {
|
||||
const assertions = {
|
||||
createEntity: "create",
|
||||
getEntities: "read",
|
||||
getEntity: "read",
|
||||
updateEntity: "update",
|
||||
patchEntity: "patch",
|
||||
deleteEntity: "delete",
|
||||
}
|
||||
await runTests("crud", testVerb, assertions)
|
||||
})
|
||||
|
||||
const testPath = async (file, extension, assertions) => {
|
||||
const queries = await getQueries(file, extension)
|
||||
for (let [operationId, urlPath] of Object.entries(assertions)) {
|
||||
expect(queries[operationId].fields.path).toBe(urlPath)
|
||||
}
|
||||
}
|
||||
|
||||
it("populates path", async () => {
|
||||
const assertions = {
|
||||
createEntity: "http://example.com/entities",
|
||||
getEntities: "http://example.com/entities",
|
||||
getEntity: "http://example.com/entities/{{entityId}}",
|
||||
updateEntity: "http://example.com/entities/{{entityId}}",
|
||||
patchEntity: "http://example.com/entities/{{entityId}}",
|
||||
deleteEntity: "http://example.com/entities/{{entityId}}",
|
||||
}
|
||||
await runTests("crud", testPath, assertions)
|
||||
})
|
||||
|
||||
const testHeaders = async (file, extension, assertions) => {
|
||||
const queries = await getQueries(file, extension)
|
||||
for (let [operationId, headers] of Object.entries(assertions)) {
|
||||
expect(queries[operationId].fields.headers).toStrictEqual(headers)
|
||||
}
|
||||
}
|
||||
|
||||
const contentTypeHeader = {
|
||||
"Content-Type": "application/json",
|
||||
}
|
||||
|
||||
it("populates headers", async () => {
|
||||
const assertions = {
|
||||
createEntity: {
|
||||
...contentTypeHeader,
|
||||
},
|
||||
getEntities: {},
|
||||
getEntity: {},
|
||||
updateEntity: {
|
||||
...contentTypeHeader,
|
||||
},
|
||||
patchEntity: {
|
||||
...contentTypeHeader,
|
||||
},
|
||||
deleteEntity: {
|
||||
"x-api-key": "{{x-api-key}}",
|
||||
},
|
||||
}
|
||||
|
||||
await runTests("crud", testHeaders, assertions)
|
||||
})
|
||||
|
||||
const testQuery = async (file, extension, assertions) => {
|
||||
const queries = await getQueries(file, extension)
|
||||
for (let [operationId, queryString] of Object.entries(assertions)) {
|
||||
expect(queries[operationId].fields.queryString).toStrictEqual(
|
||||
queryString
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
it("populates query", async () => {
|
||||
const assertions = {
|
||||
createEntity: "",
|
||||
getEntities: "page={{page}}&size={{size}}",
|
||||
getEntity: "",
|
||||
updateEntity: "",
|
||||
patchEntity: "",
|
||||
deleteEntity: "",
|
||||
}
|
||||
await runTests("crud", testQuery, assertions)
|
||||
})
|
||||
|
||||
const testParameters = async (file, extension, assertions) => {
|
||||
const queries = await getQueries(file, extension)
|
||||
for (let [operationId, parameters] of Object.entries(assertions)) {
|
||||
expect(queries[operationId].parameters).toStrictEqual(parameters)
|
||||
}
|
||||
}
|
||||
|
||||
it("populates parameters", async () => {
|
||||
const assertions = {
|
||||
createEntity: [],
|
||||
getEntities: [
|
||||
{
|
||||
name: "page",
|
||||
default: "",
|
||||
},
|
||||
{
|
||||
name: "size",
|
||||
default: "",
|
||||
},
|
||||
],
|
||||
getEntity: [
|
||||
{
|
||||
name: "entityId",
|
||||
default: "",
|
||||
},
|
||||
],
|
||||
updateEntity: [
|
||||
{
|
||||
name: "entityId",
|
||||
default: "",
|
||||
},
|
||||
],
|
||||
patchEntity: [
|
||||
{
|
||||
name: "entityId",
|
||||
default: "",
|
||||
},
|
||||
],
|
||||
deleteEntity: [
|
||||
{
|
||||
name: "entityId",
|
||||
default: "",
|
||||
},
|
||||
{
|
||||
name: "x-api-key",
|
||||
default: "",
|
||||
},
|
||||
],
|
||||
}
|
||||
await runTests("crud", testParameters, assertions)
|
||||
})
|
||||
|
||||
const testBody = async (file, extension, assertions) => {
|
||||
const queries = await getQueries(file, extension)
|
||||
for (let [operationId, body] of Object.entries(assertions)) {
|
||||
expect(queries[operationId].fields.requestBody).toStrictEqual(
|
||||
JSON.stringify(body, null, 2)
|
||||
)
|
||||
}
|
||||
}
|
||||
it("populates body", async () => {
|
||||
const assertions = {
|
||||
createEntity: {
|
||||
name: "name",
|
||||
type: "type",
|
||||
},
|
||||
getEntities: undefined,
|
||||
getEntity: undefined,
|
||||
updateEntity: {
|
||||
id: 1,
|
||||
name: "name",
|
||||
type: "type",
|
||||
},
|
||||
patchEntity: {
|
||||
id: 1,
|
||||
name: "name",
|
||||
type: "type",
|
||||
},
|
||||
deleteEntity: undefined,
|
||||
}
|
||||
await runTests("crud", testBody, assertions)
|
||||
})
|
||||
})
|
||||
})
|
Loading…
Reference in New Issue