Merge pull request #15378 from Budibase/server-ts

Convert curl.spec.js and openapi2.spec.js to TypeScript
This commit is contained in:
Sam Rose 2025-01-16 11:10:51 +00:00 committed by GitHub
commit c4eb29fcdb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 154 additions and 269 deletions

View File

@ -1,34 +1,24 @@
const { Curl } = require("../../curl") import { Curl } from "../../curl"
const fs = require("fs") import { readFileSync } from "fs"
const path = require("path") import { join } from "path"
const getData = file => { const getData = (file: string) => {
return fs.readFileSync(path.join(__dirname, `./data/${file}.txt`), "utf8") return readFileSync(join(__dirname, `./data/${file}.txt`), "utf8")
} }
describe("Curl Import", () => { describe("Curl Import", () => {
let curl let curl: Curl
beforeEach(() => { beforeEach(() => {
curl = new Curl() curl = new Curl()
}) })
it("validates unsupported data", async () => { it("validates unsupported data", async () => {
let data expect(await curl.isSupported("{}")).toBe(false)
let supported expect(await curl.isSupported("")).toBe(false)
// JSON
data = "{}"
supported = await curl.isSupported(data)
expect(supported).toBe(false)
// Empty
data = ""
supported = await curl.isSupported(data)
expect(supported).toBe(false)
}) })
const init = async file => { const init = async (file: string) => {
await curl.isSupported(getData(file)) await curl.isSupported(getData(file))
} }
@ -39,14 +29,14 @@ describe("Curl Import", () => {
}) })
describe("Returns queries", () => { describe("Returns queries", () => {
const getQueries = async file => { const getQueries = async (file: string) => {
await init(file) await init(file)
const queries = await curl.getQueries() const queries = await curl.getQueries("fake_datasource_id")
expect(queries.length).toBe(1) expect(queries.length).toBe(1)
return queries return queries
} }
const testVerb = async (file, verb) => { const testVerb = async (file: string, verb: string) => {
const queries = await getQueries(file) const queries = await getQueries(file)
expect(queries[0].queryVerb).toBe(verb) expect(queries[0].queryVerb).toBe(verb)
} }
@ -59,7 +49,7 @@ describe("Curl Import", () => {
await testVerb("patch", "patch") await testVerb("patch", "patch")
}) })
const testPath = async (file, urlPath) => { const testPath = async (file: string, urlPath: string) => {
const queries = await getQueries(file) const queries = await getQueries(file)
expect(queries[0].fields.path).toBe(urlPath) expect(queries[0].fields.path).toBe(urlPath)
} }
@ -69,7 +59,10 @@ describe("Curl Import", () => {
await testPath("path", "http://example.com/paths/abc") await testPath("path", "http://example.com/paths/abc")
}) })
const testHeaders = async (file, headers) => { const testHeaders = async (
file: string,
headers: Record<string, string>
) => {
const queries = await getQueries(file) const queries = await getQueries(file)
expect(queries[0].fields.headers).toStrictEqual(headers) expect(queries[0].fields.headers).toStrictEqual(headers)
} }
@ -82,7 +75,7 @@ describe("Curl Import", () => {
}) })
}) })
const testQuery = async (file, queryString) => { const testQuery = async (file: string, queryString: string) => {
const queries = await getQueries(file) const queries = await getQueries(file)
expect(queries[0].fields.queryString).toBe(queryString) expect(queries[0].fields.queryString).toBe(queryString)
} }
@ -91,7 +84,7 @@ describe("Curl Import", () => {
await testQuery("query", "q1=v1&q1=v2") await testQuery("query", "q1=v1&q1=v2")
}) })
const testBody = async (file, body) => { const testBody = async (file: string, body?: Record<string, any>) => {
const queries = await getQueries(file) const queries = await getQueries(file)
expect(queries[0].fields.requestBody).toStrictEqual( expect(queries[0].fields.requestBody).toStrictEqual(
JSON.stringify(body, null, 2) JSON.stringify(body, null, 2)

View File

@ -1,243 +0,0 @@
const { OpenAPI2 } = require("../../openapi2")
const fs = require("fs")
const path = require("path")
const getData = (file, extension) => {
return fs.readFileSync(
path.join(__dirname, `./data/${file}/${file}.${extension}`),
"utf8"
)
}
describe("OpenAPI2 Import", () => {
let openapi2
beforeEach(() => {
openapi2 = new OpenAPI2()
})
it("validates unsupported data", async () => {
let data
let supported
// non json / yaml
data = "curl http://example.com"
supported = await openapi2.isSupported(data)
expect(supported).toBe(false)
// Empty
data = ""
supported = await openapi2.isSupported(data)
expect(supported).toBe(false)
})
const init = async (file, extension) => {
await openapi2.isSupported(getData(file, extension))
}
const runTests = async (filename, test, assertions) => {
for (let extension of ["json", "yaml"]) {
await test(filename, extension, assertions)
}
}
const testImportInfo = async (file, extension) => {
await init(file, extension)
const info = await openapi2.getInfo()
expect(info.name).toBe("Swagger Petstore")
}
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 init(file, extension)
const queries = await openapi2.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)
})
})
})

View File

@ -0,0 +1,135 @@
import { OpenAPI2 } from "../../openapi2"
import { readFileSync } from "fs"
import { join } from "path"
import { groupBy, mapValues } from "lodash"
import { Query } from "@budibase/types"
const getData = (file: string, extension: string) => {
return readFileSync(
join(__dirname, `./data/${file}/${file}.${extension}`),
"utf8"
)
}
describe("OpenAPI2 Import", () => {
let openapi2: OpenAPI2
beforeEach(() => {
openapi2 = new OpenAPI2()
})
it("validates unsupported data", async () => {
expect(await openapi2.isSupported("curl http://example.com")).toBe(false)
expect(await openapi2.isSupported("")).toBe(false)
})
describe.each(["json", "yaml"])("%s", extension => {
describe("petstore", () => {
beforeEach(async () => {
await openapi2.isSupported(getData("petstore", extension))
})
it("returns import info", async () => {
const { name } = await openapi2.getInfo()
expect(name).toBe("Swagger Petstore")
})
})
describe("crud", () => {
let queries: Record<string, Query>
beforeEach(async () => {
await openapi2.isSupported(getData("crud", extension))
const raw = await openapi2.getQueries("fake_datasource_id")
queries = mapValues(groupBy(raw, "name"), group => group[0])
})
it("should have 6 queries", () => {
expect(Object.keys(queries).length).toBe(6)
})
it.each([
["createEntity", "create"],
["getEntities", "read"],
["getEntity", "read"],
["updateEntity", "update"],
["patchEntity", "patch"],
["deleteEntity", "delete"],
])("should have correct verb for %s", (operationId, method) => {
expect(queries[operationId].queryVerb).toBe(method)
})
it.each([
["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}}"],
])("should have correct path for %s", (operationId, urlPath) => {
expect(queries[operationId].fields.path).toBe(urlPath)
})
it.each([
["createEntity", { "Content-Type": "application/json" }],
["getEntities", {}],
["getEntity", {}],
["updateEntity", { "Content-Type": "application/json" }],
["patchEntity", { "Content-Type": "application/json" }],
["deleteEntity", { "x-api-key": "{{x-api-key}}" }],
])(`should have correct headers for %s`, (operationId, headers) => {
expect(queries[operationId].fields.headers).toStrictEqual(headers)
})
it.each([
["createEntity", ""],
["getEntities", "page={{page}}&size={{size}}"],
["getEntity", ""],
["updateEntity", ""],
["patchEntity", ""],
["deleteEntity", ""],
])(
`should have correct query string for %s`,
(operationId, queryString) => {
expect(queries[operationId].fields.queryString).toBe(queryString)
}
)
it.each([
["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: "" },
],
],
])(`should have correct parameters for %s`, (operationId, parameters) => {
expect(queries[operationId].parameters).toStrictEqual(parameters)
})
it.each([
["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],
])(`should have correct body for %s`, (operationId, body) => {
expect(queries[operationId].fields.requestBody).toBe(
JSON.stringify(body, null, 2)
)
})
})
})
})