fix openapi 3 test doc and tests
This commit is contained in:
parent
97509b561b
commit
5bc9051efa
|
@ -23,7 +23,7 @@ export abstract class ImportSource {
|
|||
name: string,
|
||||
method: string,
|
||||
path: string,
|
||||
url: URL,
|
||||
url: URL | null,
|
||||
queryString: string,
|
||||
headers: object = {},
|
||||
parameters: QueryParameter[] = [],
|
||||
|
@ -34,7 +34,9 @@ export abstract class ImportSource {
|
|||
const transformer = "return data"
|
||||
const schema = {}
|
||||
path = this.processPath(path)
|
||||
path = `${url.origin}/${path}`
|
||||
if (url) {
|
||||
path = `${url.origin}/${path}`
|
||||
}
|
||||
queryString = this.processQuery(queryString)
|
||||
const requestBody = JSON.stringify(body, null, 2)
|
||||
|
||||
|
|
|
@ -3,14 +3,7 @@ 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 => {
|
||||
|
@ -25,6 +18,13 @@ const requestBodyNotRef = (
|
|||
return param !== undefined
|
||||
}
|
||||
|
||||
const schemaNotRef = (
|
||||
param: OpenAPIV3.SchemaObject | OpenAPIV3.ReferenceObject | undefined
|
||||
): param is OpenAPIV3.SchemaObject => {
|
||||
// all refs are deferenced by parser library
|
||||
return param !== undefined
|
||||
}
|
||||
|
||||
const isOpenAPI3 = (document: any): document is OpenAPIV3.Document => {
|
||||
return document.openapi.includes("3")
|
||||
}
|
||||
|
@ -49,9 +49,25 @@ const getRequestBody = (operation: OpenAPIV3.OperationObject) => {
|
|||
if (requestBodyNotRef(operation.requestBody)) {
|
||||
const request: OpenAPIV3.RequestBodyObject =
|
||||
operation.requestBody as OpenAPIV3.RequestBodyObject
|
||||
return request.content[jsonMimeType]?.example
|
||||
const supportedMimeTypes = getMimeTypes(operation)
|
||||
return supportedMimeTypes.length > 0 &&
|
||||
schemaNotRef(request.content[supportedMimeTypes[0]].schema)
|
||||
? (
|
||||
request.content[supportedMimeTypes[0]]
|
||||
.schema as OpenAPIV3.SchemaObject
|
||||
).example
|
||||
: undefined
|
||||
}
|
||||
return null
|
||||
return undefined
|
||||
}
|
||||
|
||||
const getMimeTypes = (operation: OpenAPIV3.OperationObject): string[] => {
|
||||
if (requestBodyNotRef(operation.requestBody)) {
|
||||
const request: OpenAPIV3.RequestBodyObject =
|
||||
operation.requestBody as OpenAPIV3.RequestBodyObject
|
||||
return Object.keys(request.content)
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,34 +91,6 @@ export class OpenAPI3 extends OpenAPISource {
|
|||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
|
@ -111,7 +99,9 @@ export class OpenAPI3 extends OpenAPISource {
|
|||
}
|
||||
|
||||
getQueries = async (datasourceId: string): Promise<Query[]> => {
|
||||
const url: URL = await this.getUrl()
|
||||
const url: URL | null = this.document.servers
|
||||
? new URL(this.document.servers[0].url)
|
||||
: null
|
||||
const queries: Query[] = []
|
||||
|
||||
for (let [path, pathItemObject] of Object.entries(this.document.paths)) {
|
||||
|
@ -138,6 +128,11 @@ export class OpenAPI3 extends OpenAPISource {
|
|||
const headers: any = {}
|
||||
let requestBody = getRequestBody(operation)
|
||||
const parameters: QueryParameter[] = []
|
||||
const mimeTypes = getMimeTypes(operation)
|
||||
|
||||
if (mimeTypes.length > 0) {
|
||||
headers["Content-Type"] = mimeTypes[0]
|
||||
}
|
||||
|
||||
// combine the path parameters with the operation parameters
|
||||
const operationParams = operation.parameters || []
|
||||
|
|
|
@ -5,6 +5,11 @@
|
|||
"version": "1.0.0",
|
||||
"title": "CRUD"
|
||||
},
|
||||
"servers": [
|
||||
{
|
||||
"url": "http://example.com"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
{
|
||||
"name": "entity"
|
||||
|
@ -17,16 +22,24 @@
|
|||
"entity"
|
||||
],
|
||||
"operationId": "createEntity",
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/schemas/CreateEntityParameter"
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/CreateEntity"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "successful operation",
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Entity"
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,22 +49,23 @@
|
|||
"entity"
|
||||
],
|
||||
"operationId": "getEntities",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/schemas/PageParameter"
|
||||
"$ref": "#/components/parameters/PageParameter"
|
||||
},
|
||||
{
|
||||
"$ref": "#/components/schemas/SizeParameter"
|
||||
"$ref": "#/components/parameters/SizeParameter"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "successful operation",
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Entities"
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Entities"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -60,7 +74,7 @@
|
|||
"/entities/{entityId}": {
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/schemas/EntityIdParameter"
|
||||
"$ref": "#/components/parameters/EntityIdParameter"
|
||||
}
|
||||
],
|
||||
"get": {
|
||||
|
@ -68,14 +82,15 @@
|
|||
"entity"
|
||||
],
|
||||
"operationId": "getEntity",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "successful operation",
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Entity"
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -85,16 +100,24 @@
|
|||
"entity"
|
||||
],
|
||||
"operationId": "updateEntity",
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/schemas/EntityParameter"
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "successful operation",
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Entity"
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -104,16 +127,24 @@
|
|||
"entity"
|
||||
],
|
||||
"operationId": "patchEntity",
|
||||
"parameters": [
|
||||
{
|
||||
"$ref": "#/components/schemas/EntityParameter"
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "successful operation",
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Entity"
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/Entity"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -124,10 +155,7 @@
|
|||
],
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"name": "x-api-key",
|
||||
"in": "header",
|
||||
"required": false
|
||||
"$ref": "#/components/parameters/APIKeyParameter"
|
||||
}
|
||||
],
|
||||
"operationId": "deleteEntity",
|
||||
|
@ -140,50 +168,44 @@
|
|||
}
|
||||
},
|
||||
"components": {
|
||||
"schemas": {
|
||||
"parameters": {
|
||||
"EntityIdParameter": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"schema": {
|
||||
"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",
|
||||
"PageParameter": {
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"name": "page",
|
||||
"in": "query",
|
||||
"required": false
|
||||
},
|
||||
"SizeParameter": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"schema": {
|
||||
"type": "integer",
|
||||
"format": "int32"
|
||||
},
|
||||
"name": "size",
|
||||
"in": "query",
|
||||
"required": false
|
||||
},
|
||||
"APIKeyParameter": {
|
||||
"type": "string",
|
||||
"schema": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": "x-api-key",
|
||||
"in": "header",
|
||||
"required": false
|
||||
},
|
||||
}
|
||||
},
|
||||
"schemas": {
|
||||
"CreateEntity": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
---
|
||||
openapi: "3.0.2"
|
||||
openapi: 3.0.2
|
||||
info:
|
||||
description: A basic swagger file
|
||||
version: 1.0.0
|
||||
title: CRUD
|
||||
host: example.com
|
||||
servers:
|
||||
- url: http://example.com
|
||||
tags:
|
||||
- name: entity
|
||||
paths:
|
||||
|
@ -13,144 +14,140 @@ paths:
|
|||
tags:
|
||||
- entity
|
||||
operationId: createEntity
|
||||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- "$ref": "#/parameters/CreateEntity"
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/CreateEntity"
|
||||
responses:
|
||||
"200":
|
||||
'200':
|
||||
description: successful operation
|
||||
schema:
|
||||
"$ref": "#/definitions/Entity"
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Entity"
|
||||
get:
|
||||
tags:
|
||||
- entity
|
||||
operationId: getEntities
|
||||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- "$ref": "#/parameters/Page"
|
||||
- "$ref": "#/parameters/Size"
|
||||
- "$ref": "#/components/parameters/PageParameter"
|
||||
- "$ref": "#/components/parameters/SizeParameter"
|
||||
responses:
|
||||
"200":
|
||||
'200':
|
||||
description: successful operation
|
||||
schema:
|
||||
"$ref": "#/definitions/Entities"
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Entities"
|
||||
"/entities/{entityId}":
|
||||
parameters:
|
||||
- "$ref": "#/parameters/EntityId"
|
||||
- "$ref": "#/components/parameters/EntityIdParameter"
|
||||
get:
|
||||
tags:
|
||||
- entity
|
||||
operationId: getEntity
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
'200':
|
||||
description: successful operation
|
||||
schema:
|
||||
"$ref": "#/definitions/Entity"
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Entity"
|
||||
put:
|
||||
tags:
|
||||
- entity
|
||||
operationId: updateEntity
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- "$ref": "#/parameters/Entity"
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Entity"
|
||||
responses:
|
||||
"200":
|
||||
'200':
|
||||
description: successful operation
|
||||
schema:
|
||||
"$ref": "#/definitions/Entity"
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Entity"
|
||||
patch:
|
||||
tags:
|
||||
- entity
|
||||
operationId: patchEntity
|
||||
consumes:
|
||||
- application/json
|
||||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- "$ref": "#/parameters/Entity"
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Entity"
|
||||
responses:
|
||||
"200":
|
||||
'200':
|
||||
description: successful operation
|
||||
schema:
|
||||
"$ref": "#/definitions/Entity"
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
"$ref": "#/components/schemas/Entity"
|
||||
delete:
|
||||
tags:
|
||||
- entity
|
||||
parameters:
|
||||
- "$ref": "#/parameters/APIKey"
|
||||
- "$ref": "#/components/parameters/APIKeyParameter"
|
||||
operationId: deleteEntity
|
||||
produces:
|
||||
- application/json
|
||||
responses:
|
||||
"204":
|
||||
'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:
|
||||
components:
|
||||
parameters:
|
||||
EntityIdParameter:
|
||||
schema:
|
||||
type: integer
|
||||
format: int64
|
||||
name: entityId
|
||||
in: path
|
||||
required: true
|
||||
PageParameter:
|
||||
schema:
|
||||
type: integer
|
||||
format: int32
|
||||
name: page
|
||||
in: query
|
||||
required: false
|
||||
SizeParameter:
|
||||
schema:
|
||||
type: integer
|
||||
format: int32
|
||||
name: size
|
||||
in: query
|
||||
required: false
|
||||
APIKeyParameter:
|
||||
schema:
|
||||
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"
|
||||
name: x-api-key
|
||||
in: header
|
||||
required: false
|
||||
schemas:
|
||||
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"
|
||||
|
|
|
@ -1,21 +1,6 @@
|
|||
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) => {
|
||||
|
@ -48,10 +33,9 @@ describe("OpenAPI3 Import", () => {
|
|||
})
|
||||
|
||||
const runTests = async (filename, test, assertions) => {
|
||||
/*for (let extension of ["json", "yaml"]) {
|
||||
for (let extension of ["json", "yaml"]) {
|
||||
await test(filename, extension, assertions)
|
||||
}*/
|
||||
await test(filename, "json", assertions)
|
||||
}
|
||||
}
|
||||
|
||||
const testImportInfo = async (file, extension) => {
|
||||
|
|
Loading…
Reference in New Issue