fix openapi 3 test doc and tests

This commit is contained in:
Maurits Lourens 2022-03-03 15:19:36 +01:00
parent 97509b561b
commit 5bc9051efa
5 changed files with 225 additions and 225 deletions

View File

@ -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)

View File

@ -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 || []

View File

@ -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": {

View File

@ -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"

View File

@ -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) => {