Adding a testing system which generates the schema and compares against responses.
This commit is contained in:
parent
53f108865a
commit
01bb56cbf4
|
@ -53,10 +53,10 @@
|
|||
to-gfm-code-block "^0.1.1"
|
||||
year "^0.2.1"
|
||||
|
||||
"@budibase/string-templates@^1.0.66-alpha.0":
|
||||
version "1.0.72"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-1.0.72.tgz#acc154e402cce98ea30eedde9c6124183ee9b37c"
|
||||
integrity sha512-w715TjgO6NUHkZNqoOEo8lAKJ/PQ4b00ATWSX5VB523SAu7y/uOiqKqV1E3fgwxq1o8L+Ff7rn9FTkiYtjkV/g==
|
||||
"@budibase/string-templates@^1.0.72-alpha.0":
|
||||
version "1.0.75"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-1.0.75.tgz#5b4061f1a626160ec092f32f036541376298100c"
|
||||
integrity sha512-hPgr6n5cpSCGFEha5DS/P+rtRXOLc72M6y4J/scl59JvUi/ZUJkjRgJdpQPdBLu04CNKp89V59+rAqAuDjOC0g==
|
||||
dependencies:
|
||||
"@budibase/handlebars-helpers" "^0.11.7"
|
||||
dayjs "^1.10.4"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -53,6 +53,7 @@ module FetchMock {
|
|||
{
|
||||
doc: {
|
||||
_id: "test",
|
||||
tableId: opts.body.split("tableId:")[1].split('"')[0],
|
||||
},
|
||||
},
|
||||
],
|
||||
|
|
|
@ -158,6 +158,7 @@
|
|||
"docker-compose": "^0.23.6",
|
||||
"eslint": "^6.8.0",
|
||||
"jest": "^27.0.5",
|
||||
"jest-openapi": "^0.14.2",
|
||||
"nodemon": "^2.0.4",
|
||||
"openapi-types": "^9.3.1",
|
||||
"path-to-regexp": "^6.2.0",
|
||||
|
|
|
@ -49,12 +49,11 @@ const options = {
|
|||
apis: [join(__dirname, "..", "src", "api", "routes", "public", "*.ts")],
|
||||
}
|
||||
|
||||
function writeFile(output, { isJson } = {}) {
|
||||
function writeFile(output, filename) {
|
||||
try {
|
||||
const filename = isJson ? "openapi.json" : "openapi.yaml"
|
||||
const path = join(__dirname, filename)
|
||||
let spec = output
|
||||
if (isJson) {
|
||||
if (filename.endsWith("json")) {
|
||||
spec = JSON.stringify(output, null, 2)
|
||||
}
|
||||
// input the static variables
|
||||
|
@ -63,13 +62,22 @@ function writeFile(output, { isJson } = {}) {
|
|||
}
|
||||
writeFileSync(path, spec)
|
||||
console.log(`Wrote spec to ${path}`)
|
||||
return path
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
}
|
||||
|
||||
const outputJSON = swaggerJsdoc(options)
|
||||
options.format = ".yaml"
|
||||
const outputYAML = swaggerJsdoc(options)
|
||||
writeFile(outputJSON, { isJson: true })
|
||||
writeFile(outputYAML)
|
||||
function run() {
|
||||
const outputJSON = swaggerJsdoc(options)
|
||||
options.format = ".yaml"
|
||||
const outputYAML = swaggerJsdoc(options)
|
||||
writeFile(outputJSON, "openapi.json")
|
||||
return writeFile(outputYAML, "openapi.yaml")
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
run()
|
||||
}
|
||||
|
||||
module.exports = run
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -63,6 +63,7 @@ const baseColumnDef = {
|
|||
const tableSchema = {
|
||||
description: "The table to be created/updated.",
|
||||
type: "object",
|
||||
required: ["name", "schema"],
|
||||
properties: {
|
||||
name: {
|
||||
description: "The name of the table",
|
||||
|
@ -74,82 +75,85 @@ const tableSchema = {
|
|||
"The name of the column which should be used in relationship tags when relating to this table.",
|
||||
},
|
||||
schema: {
|
||||
oneOf: [
|
||||
// relationship
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
...baseColumnDef,
|
||||
type: {
|
||||
type: "string",
|
||||
enum: [FieldTypes.LINK],
|
||||
description: "A relationship column.",
|
||||
},
|
||||
fieldName: {
|
||||
type: "string",
|
||||
description:
|
||||
"The name of the column which a relationship column is related to in another table.",
|
||||
},
|
||||
tableId: {
|
||||
type: "string",
|
||||
description:
|
||||
"The ID of the table which a relationship column is related to.",
|
||||
},
|
||||
relationshipType: {
|
||||
type: "string",
|
||||
enum: Object.values(RelationshipTypes),
|
||||
description:
|
||||
"Defines the type of relationship that this column will be used for.",
|
||||
},
|
||||
through: {
|
||||
type: "string",
|
||||
description:
|
||||
"When using a SQL table that contains many to many relationships this defines the table the relationships are linked through.",
|
||||
},
|
||||
foreignKey: {
|
||||
type: "string",
|
||||
description:
|
||||
"When using a SQL table that contains a one to many relationship this defines the foreign key.",
|
||||
},
|
||||
throughFrom: {
|
||||
type: "string",
|
||||
description:
|
||||
"When using a SQL table that utilises a through table, this defines the primary key in the through table for this table.",
|
||||
},
|
||||
throughTo: {
|
||||
type: "string",
|
||||
description:
|
||||
"When using a SQL table that utilises a through table, this defines the primary key in the through table for the related table.",
|
||||
type: "object",
|
||||
additionalProperties: {
|
||||
oneOf: [
|
||||
// relationship
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
...baseColumnDef,
|
||||
type: {
|
||||
type: "string",
|
||||
enum: [FieldTypes.LINK],
|
||||
description: "A relationship column.",
|
||||
},
|
||||
fieldName: {
|
||||
type: "string",
|
||||
description:
|
||||
"The name of the column which a relationship column is related to in another table.",
|
||||
},
|
||||
tableId: {
|
||||
type: "string",
|
||||
description:
|
||||
"The ID of the table which a relationship column is related to.",
|
||||
},
|
||||
relationshipType: {
|
||||
type: "string",
|
||||
enum: Object.values(RelationshipTypes),
|
||||
description:
|
||||
"Defines the type of relationship that this column will be used for.",
|
||||
},
|
||||
through: {
|
||||
type: "string",
|
||||
description:
|
||||
"When using a SQL table that contains many to many relationships this defines the table the relationships are linked through.",
|
||||
},
|
||||
foreignKey: {
|
||||
type: "string",
|
||||
description:
|
||||
"When using a SQL table that contains a one to many relationship this defines the foreign key.",
|
||||
},
|
||||
throughFrom: {
|
||||
type: "string",
|
||||
description:
|
||||
"When using a SQL table that utilises a through table, this defines the primary key in the through table for this table.",
|
||||
},
|
||||
throughTo: {
|
||||
type: "string",
|
||||
description:
|
||||
"When using a SQL table that utilises a through table, this defines the primary key in the through table for the related table.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
...baseColumnDef,
|
||||
type: {
|
||||
type: "string",
|
||||
enum: [FieldTypes.FORMULA],
|
||||
description: "A formula column.",
|
||||
},
|
||||
formula: {
|
||||
type: "string",
|
||||
description:
|
||||
"Defines a Handlebars or JavaScript formula to use, note that Javascript formulas are expected to be provided in the base64 format.",
|
||||
},
|
||||
formulaType: {
|
||||
type: "string",
|
||||
enum: Object.values(FormulaTypes),
|
||||
description:
|
||||
"Defines whether this is a static or dynamic formula.",
|
||||
{
|
||||
type: "object",
|
||||
properties: {
|
||||
...baseColumnDef,
|
||||
type: {
|
||||
type: "string",
|
||||
enum: [FieldTypes.FORMULA],
|
||||
description: "A formula column.",
|
||||
},
|
||||
formula: {
|
||||
type: "string",
|
||||
description:
|
||||
"Defines a Handlebars or JavaScript formula to use, note that Javascript formulas are expected to be provided in the base64 format.",
|
||||
},
|
||||
formulaType: {
|
||||
type: "string",
|
||||
enum: Object.values(FormulaTypes),
|
||||
description:
|
||||
"Defines whether this is a static or dynamic formula.",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
type: "object",
|
||||
properties: baseColumnDef,
|
||||
},
|
||||
],
|
||||
{
|
||||
type: "object",
|
||||
properties: baseColumnDef,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ exports.object = (props, opts) => {
|
|||
return {
|
||||
type: "object",
|
||||
properties: props,
|
||||
required: Object.keys(props),
|
||||
...opts,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,43 +5,6 @@ const { nameValidator, applicationValidator } = require("../utils/validators")
|
|||
const read = [],
|
||||
write = []
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /applications/search:
|
||||
* post:
|
||||
* summary: Search for an application based on its app name.
|
||||
* tags:
|
||||
* - applications
|
||||
* parameters:
|
||||
* - $ref: '#/components/parameters/appId'
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: '#/components/schemas/nameSearch'
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Returns the applications that were found based on the search parameters.
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* applications:
|
||||
* type: array
|
||||
* items:
|
||||
* $ref: '#/components/schemas/application'
|
||||
* examples:
|
||||
* applications:
|
||||
* $ref: '#/components/examples/applications'
|
||||
*/
|
||||
read.push(
|
||||
new Endpoint("post", "/applications/search", controller.search).addMiddleware(
|
||||
nameValidator()
|
||||
)
|
||||
)
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /applications:
|
||||
|
@ -68,7 +31,11 @@ read.push(
|
|||
* application:
|
||||
* $ref: '#/components/examples/application'
|
||||
*/
|
||||
write.push(new Endpoint("post", "/applications", controller.create))
|
||||
write.push(
|
||||
new Endpoint("post", "/applications", controller.create).addMiddleware(
|
||||
applicationValidator
|
||||
)
|
||||
)
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
|
@ -96,7 +63,11 @@ write.push(new Endpoint("post", "/applications", controller.create))
|
|||
* application:
|
||||
* $ref: '#/components/examples/application'
|
||||
*/
|
||||
write.push(new Endpoint("put", "/applications/:appId", controller.update))
|
||||
write.push(
|
||||
new Endpoint("put", "/applications/:appId", controller.update).addMiddleware(
|
||||
applicationValidator
|
||||
)
|
||||
)
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
|
@ -142,4 +113,43 @@ write.push(new Endpoint("delete", "/applications/:appId", controller.destroy))
|
|||
*/
|
||||
read.push(new Endpoint("get", "/applications/:appId", controller.read))
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /applications/search:
|
||||
* post:
|
||||
* summary: Search for an application based on its app name.
|
||||
* tags:
|
||||
* - applications
|
||||
* parameters:
|
||||
* - $ref: '#/components/parameters/appId'
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: '#/components/schemas/nameSearch'
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Returns the applications that were found based on the search parameters.
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - applications
|
||||
* properties:
|
||||
* applications:
|
||||
* type: array
|
||||
* items:
|
||||
* $ref: '#/components/schemas/application'
|
||||
* examples:
|
||||
* applications:
|
||||
* $ref: '#/components/examples/applications'
|
||||
*/
|
||||
read.push(
|
||||
new Endpoint("post", "/applications/search", controller.search).addMiddleware(
|
||||
nameValidator()
|
||||
)
|
||||
)
|
||||
|
||||
export default { read, write }
|
||||
|
|
|
@ -5,43 +5,6 @@ import { nameValidator } from "../utils/validators"
|
|||
const read = [],
|
||||
write = []
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /queries/search:
|
||||
* post:
|
||||
* summary: Search for a query based on its name.
|
||||
* tags:
|
||||
* - queries
|
||||
* parameters:
|
||||
* - $ref: '#/components/parameters/appId'
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: '#/components/schemas/nameSearch'
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Returns the queries found based on the search parameters.
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* queries:
|
||||
* type: array
|
||||
* items:
|
||||
* $ref: '#/components/schemas/query'
|
||||
* examples:
|
||||
* queries:
|
||||
* $ref: '#/components/examples/queries'
|
||||
*/
|
||||
read.push(
|
||||
new Endpoint("post", "/queries/search", controller.search).addMiddleware(
|
||||
nameValidator()
|
||||
)
|
||||
)
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /queries/{queryId}:
|
||||
|
@ -89,4 +52,43 @@ read.push(
|
|||
*/
|
||||
write.push(new Endpoint("post", "/queries/:queryId", controller.execute))
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /queries/search:
|
||||
* post:
|
||||
* summary: Search for a query based on its name.
|
||||
* tags:
|
||||
* - queries
|
||||
* parameters:
|
||||
* - $ref: '#/components/parameters/appId'
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: '#/components/schemas/nameSearch'
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Returns the queries found based on the search parameters.
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - queries
|
||||
* properties:
|
||||
* queries:
|
||||
* type: array
|
||||
* items:
|
||||
* $ref: '#/components/schemas/query'
|
||||
* examples:
|
||||
* queries:
|
||||
* $ref: '#/components/examples/queries'
|
||||
*/
|
||||
read.push(
|
||||
new Endpoint("post", "/queries/search", controller.search).addMiddleware(
|
||||
nameValidator()
|
||||
)
|
||||
)
|
||||
|
||||
export default { read, write }
|
||||
|
|
|
@ -5,130 +5,6 @@ import { externalSearchValidator } from "../utils/validators"
|
|||
const read = [],
|
||||
write = []
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /tables/{tableId}/rows/search:
|
||||
* post:
|
||||
* summary: Used to search for rows within a table.
|
||||
* tags:
|
||||
* - rows
|
||||
* parameters:
|
||||
* - $ref: '#/components/parameters/tableId'
|
||||
* - $ref: '#/components/parameters/appId'
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* query:
|
||||
* type: object
|
||||
* properties:
|
||||
* string:
|
||||
* type: object
|
||||
* example:
|
||||
* columnName1: value
|
||||
* columnName2: value
|
||||
* description: A map of field name to the string to search for,
|
||||
* this will look for rows that have a value starting with the
|
||||
* string value.
|
||||
* additionalProperties:
|
||||
* type: string
|
||||
* description: The value to search for in the column.
|
||||
* fuzzy:
|
||||
* type: object
|
||||
* description: A fuzzy search, only supported by internal tables.
|
||||
* range:
|
||||
* type: object
|
||||
* description: Searches within a range, the format of this must be
|
||||
* columnName -> [low, high].
|
||||
* example:
|
||||
* columnName1: [10, 20]
|
||||
* equal:
|
||||
* type: object
|
||||
* description: Searches for rows that have a column value that is
|
||||
* exactly the value set.
|
||||
* notEqual:
|
||||
* type: object
|
||||
* description: Searches for any row which does not contain the specified
|
||||
* column value.
|
||||
* empty:
|
||||
* type: object
|
||||
* description: Searches for rows which do not contain the specified column.
|
||||
* The object should simply contain keys of the column names, these
|
||||
* can map to any value.
|
||||
* example:
|
||||
* columnName1: ""
|
||||
* notEmpty:
|
||||
* type: object
|
||||
* description: Searches for rows which have the specified column.
|
||||
* oneOf:
|
||||
* type: object
|
||||
* description: Searches for rows which have a column value that is any
|
||||
* of the specified values. The format of this must be columnName -> [value1, value2].
|
||||
* paginate:
|
||||
* type: boolean
|
||||
* description: Enables pagination, by default this is disabled.
|
||||
* bookmark:
|
||||
* oneOf:
|
||||
* - type: string
|
||||
* - type: integer
|
||||
* description: If retrieving another page, the bookmark from the previous request must be supplied.
|
||||
* limit:
|
||||
* type: integer
|
||||
* description: The maximum number of rows to return, useful when paginating, for internal tables this
|
||||
* will be limited to 1000, for SQL tables it will be 5000.
|
||||
* sort:
|
||||
* type: object
|
||||
* description: A set of parameters describing the sort behaviour of the search.
|
||||
* properties:
|
||||
* order:
|
||||
* type: string
|
||||
* enum: [ascending, descending]
|
||||
* description: The order of the sort, by default this is ascending.
|
||||
* column:
|
||||
* type: string
|
||||
* description: The name of the column by which the rows will be sorted.
|
||||
* type:
|
||||
* type: string
|
||||
* enum: [string, number]
|
||||
* description: Defines whether the column should be treated as a string
|
||||
* or as numbers when sorting.
|
||||
* responses:
|
||||
* 200:
|
||||
* description: The response will contain an array of rows that match the search parameters.
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* rows:
|
||||
* description: An array of rows, these will each contain an _id field which can be used
|
||||
* to update or delete them.
|
||||
* type: array
|
||||
* items:
|
||||
* type: object
|
||||
* bookmark:
|
||||
* oneOf:
|
||||
* - type: string
|
||||
* - type: integer
|
||||
* description: If pagination in use, this should be provided.
|
||||
* hasNextPage:
|
||||
* description: If pagination in use, this will determine if there is another page to fetch.
|
||||
* type: boolean
|
||||
* examples:
|
||||
* search:
|
||||
* $ref: '#/components/examples/rows'
|
||||
*/
|
||||
read.push(
|
||||
new Endpoint(
|
||||
"post",
|
||||
"/tables/:tableId/rows/search",
|
||||
controller.search
|
||||
).addMiddleware(externalSearchValidator())
|
||||
)
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /tables/{tableId}/rows:
|
||||
|
@ -247,4 +123,132 @@ write.push(
|
|||
*/
|
||||
read.push(new Endpoint("get", "/tables/:tableId/rows/:rowId", controller.read))
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /tables/{tableId}/rows/search:
|
||||
* post:
|
||||
* summary: Used to search for rows within a table.
|
||||
* tags:
|
||||
* - rows
|
||||
* parameters:
|
||||
* - $ref: '#/components/parameters/tableId'
|
||||
* - $ref: '#/components/parameters/appId'
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - query
|
||||
* properties:
|
||||
* query:
|
||||
* type: object
|
||||
* properties:
|
||||
* string:
|
||||
* type: object
|
||||
* example:
|
||||
* columnName1: value
|
||||
* columnName2: value
|
||||
* description: A map of field name to the string to search for,
|
||||
* this will look for rows that have a value starting with the
|
||||
* string value.
|
||||
* additionalProperties:
|
||||
* type: string
|
||||
* description: The value to search for in the column.
|
||||
* fuzzy:
|
||||
* type: object
|
||||
* description: A fuzzy search, only supported by internal tables.
|
||||
* range:
|
||||
* type: object
|
||||
* description: Searches within a range, the format of this must be
|
||||
* columnName -> [low, high].
|
||||
* example:
|
||||
* columnName1: [10, 20]
|
||||
* equal:
|
||||
* type: object
|
||||
* description: Searches for rows that have a column value that is
|
||||
* exactly the value set.
|
||||
* notEqual:
|
||||
* type: object
|
||||
* description: Searches for any row which does not contain the specified
|
||||
* column value.
|
||||
* empty:
|
||||
* type: object
|
||||
* description: Searches for rows which do not contain the specified column.
|
||||
* The object should simply contain keys of the column names, these
|
||||
* can map to any value.
|
||||
* example:
|
||||
* columnName1: ""
|
||||
* notEmpty:
|
||||
* type: object
|
||||
* description: Searches for rows which have the specified column.
|
||||
* oneOf:
|
||||
* type: object
|
||||
* description: Searches for rows which have a column value that is any
|
||||
* of the specified values. The format of this must be columnName -> [value1, value2].
|
||||
* paginate:
|
||||
* type: boolean
|
||||
* description: Enables pagination, by default this is disabled.
|
||||
* bookmark:
|
||||
* oneOf:
|
||||
* - type: string
|
||||
* - type: integer
|
||||
* description: If retrieving another page, the bookmark from the previous request must be supplied.
|
||||
* limit:
|
||||
* type: integer
|
||||
* description: The maximum number of rows to return, useful when paginating, for internal tables this
|
||||
* will be limited to 1000, for SQL tables it will be 5000.
|
||||
* sort:
|
||||
* type: object
|
||||
* description: A set of parameters describing the sort behaviour of the search.
|
||||
* properties:
|
||||
* order:
|
||||
* type: string
|
||||
* enum: [ascending, descending]
|
||||
* description: The order of the sort, by default this is ascending.
|
||||
* column:
|
||||
* type: string
|
||||
* description: The name of the column by which the rows will be sorted.
|
||||
* type:
|
||||
* type: string
|
||||
* enum: [string, number]
|
||||
* description: Defines whether the column should be treated as a string
|
||||
* or as numbers when sorting.
|
||||
* responses:
|
||||
* 200:
|
||||
* description: The response will contain an array of rows that match the search parameters.
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - rows
|
||||
* properties:
|
||||
* rows:
|
||||
* description: An array of rows, these will each contain an _id field which can be used
|
||||
* to update or delete them.
|
||||
* type: array
|
||||
* items:
|
||||
* type: object
|
||||
* bookmark:
|
||||
* oneOf:
|
||||
* - type: string
|
||||
* - type: integer
|
||||
* description: If pagination in use, this should be provided.
|
||||
* hasNextPage:
|
||||
* description: If pagination in use, this will determine if there is another page to fetch.
|
||||
* type: boolean
|
||||
* examples:
|
||||
* search:
|
||||
* $ref: '#/components/examples/rows'
|
||||
*/
|
||||
read.push(
|
||||
new Endpoint(
|
||||
"post",
|
||||
"/tables/:tableId/rows/search",
|
||||
controller.search
|
||||
).addMiddleware(externalSearchValidator())
|
||||
)
|
||||
|
||||
export default { read, write }
|
||||
|
|
|
@ -5,43 +5,6 @@ import { tableValidator, nameValidator } from "../utils/validators"
|
|||
const read = [],
|
||||
write = []
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /tables/search:
|
||||
* post:
|
||||
* summary: Search internal and external tables based on their name.
|
||||
* tags:
|
||||
* - tables
|
||||
* parameters:
|
||||
* - $ref: '#/components/parameters/appId'
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: '#/components/schemas/nameSearch'
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Returns the found tables, based on the search parameters.
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* properties:
|
||||
* applications:
|
||||
* type: array
|
||||
* items:
|
||||
* $ref: '#/components/schemas/table'
|
||||
* examples:
|
||||
* tables:
|
||||
* $ref: '#/components/examples/tables'
|
||||
*/
|
||||
read.push(
|
||||
new Endpoint("post", "/tables/search", controller.search).addMiddleware(
|
||||
nameValidator()
|
||||
)
|
||||
)
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /tables:
|
||||
|
@ -158,4 +121,43 @@ write.push(new Endpoint("delete", "/tables/:tableId", controller.destroy))
|
|||
*/
|
||||
read.push(new Endpoint("get", "/tables/:tableId", controller.read))
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /tables/search:
|
||||
* post:
|
||||
* summary: Search internal and external tables based on their name.
|
||||
* tags:
|
||||
* - tables
|
||||
* parameters:
|
||||
* - $ref: '#/components/parameters/appId'
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: '#/components/schemas/nameSearch'
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Returns the found tables, based on the search parameters.
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - tables
|
||||
* properties:
|
||||
* tables:
|
||||
* type: array
|
||||
* items:
|
||||
* $ref: '#/components/schemas/table'
|
||||
* examples:
|
||||
* tables:
|
||||
* $ref: '#/components/examples/tables'
|
||||
*/
|
||||
read.push(
|
||||
new Endpoint("post", "/tables/search", controller.search).addMiddleware(
|
||||
nameValidator()
|
||||
)
|
||||
)
|
||||
|
||||
export default { read, write }
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
const jestOpenAPI = require("jest-openapi").default
|
||||
const generateSchema = require("../../../../../specs/generate")
|
||||
const setup = require("../../tests/utilities")
|
||||
const { checkSlashesInUrl } = require("../../../../utilities")
|
||||
|
||||
const yamlPath = generateSchema()
|
||||
jestOpenAPI(yamlPath)
|
||||
|
||||
let request = setup.getRequest()
|
||||
let config = setup.getConfig()
|
||||
let apiKey, table
|
||||
|
||||
beforeAll(async () => {
|
||||
await config.init()
|
||||
table = await config.updateTable()
|
||||
apiKey = await config.generateApiKey()
|
||||
})
|
||||
|
||||
afterAll(setup.afterAll)
|
||||
|
||||
async function makeRequest(method, endpoint, body, appId) {
|
||||
const extraHeaders = {
|
||||
"x-budibase-api-key": apiKey,
|
||||
"x-budibase-app-id": appId ? appId : config.getAppId(),
|
||||
}
|
||||
const req = request
|
||||
[method](checkSlashesInUrl(`/api/public/v1/${endpoint}`))
|
||||
.set(config.defaultHeaders(extraHeaders))
|
||||
if (body) {
|
||||
req.send(body)
|
||||
}
|
||||
const res = await req.expect("Content-Type", /json/).expect(200)
|
||||
expect(res.body).toBeDefined()
|
||||
return res
|
||||
}
|
||||
|
||||
describe("check the applications endpoints", () => {
|
||||
it("should allow retrieving applications through search", async () => {
|
||||
const res = await makeRequest("post", "/applications/search")
|
||||
expect(res).toSatisfyApiSpec()
|
||||
})
|
||||
})
|
||||
|
||||
describe("check the tables endpoints", () => {
|
||||
it("should allow retrieving applications through search", async () => {
|
||||
const res = await makeRequest("post", "/tables/search")
|
||||
expect(res).toSatisfyApiSpec()
|
||||
})
|
||||
})
|
||||
|
||||
describe("check the rows endpoints", () => {
|
||||
it("should allow retrieving applications through search", async () => {
|
||||
const res = await makeRequest("post", `/tables/${table._id}/rows/search`, {
|
||||
query: {
|
||||
},
|
||||
})
|
||||
expect(res).toSatisfyApiSpec()
|
||||
})
|
||||
})
|
||||
|
||||
describe("check the users endpoints", () => {
|
||||
it("should allow retrieving applications through search", async () => {
|
||||
const res = await makeRequest("post", "/users/search")
|
||||
expect(res).toSatisfyApiSpec()
|
||||
})
|
||||
})
|
||||
|
||||
describe("check the queries endpoints", () => {
|
||||
it("should allow retrieving applications through search", async () => {
|
||||
const res = await makeRequest("post", "/queries/search")
|
||||
expect(res).toSatisfyApiSpec()
|
||||
})
|
||||
})
|
||||
|
|
@ -5,40 +5,6 @@ import { nameValidator } from "../utils/validators"
|
|||
const read = [],
|
||||
write = []
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /users/search:
|
||||
* post:
|
||||
* summary: Search for a user based on their email/username.
|
||||
* tags:
|
||||
* - users
|
||||
* parameters:
|
||||
* - $ref: '#/components/parameters/appId'
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: '#/components/schemas/nameSearch'
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Returns the found users based on search parameters.
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: array
|
||||
* items:
|
||||
* $ref: '#/components/schemas/user'
|
||||
* examples:
|
||||
* users:
|
||||
* $ref: '#/components/examples/users'
|
||||
*/
|
||||
read.push(
|
||||
new Endpoint("post", "/users/search", controller.search).addMiddleware(
|
||||
nameValidator()
|
||||
)
|
||||
)
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /users:
|
||||
|
@ -142,4 +108,43 @@ write.push(new Endpoint("delete", "/users/:userId", controller.destroy))
|
|||
*/
|
||||
read.push(new Endpoint("get", "/users/:userId", controller.read))
|
||||
|
||||
/**
|
||||
* @openapi
|
||||
* /users/search:
|
||||
* post:
|
||||
* summary: Search for a user based on their email/username.
|
||||
* tags:
|
||||
* - users
|
||||
* parameters:
|
||||
* - $ref: '#/components/parameters/appId'
|
||||
* requestBody:
|
||||
* required: true
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* $ref: '#/components/schemas/nameSearch'
|
||||
* responses:
|
||||
* 200:
|
||||
* description: Returns the found users based on search parameters.
|
||||
* content:
|
||||
* application/json:
|
||||
* schema:
|
||||
* type: object
|
||||
* required:
|
||||
* - users
|
||||
* properties:
|
||||
* users:
|
||||
* type: array
|
||||
* items:
|
||||
* $ref: '#/components/schemas/user'
|
||||
* examples:
|
||||
* users:
|
||||
* $ref: '#/components/examples/users'
|
||||
*/
|
||||
read.push(
|
||||
new Endpoint("post", "/users/search", controller.search).addMiddleware(
|
||||
nameValidator()
|
||||
)
|
||||
)
|
||||
|
||||
export default { read, write }
|
||||
|
|
|
@ -25,6 +25,8 @@ const { createASession } = require("@budibase/backend-core/sessions")
|
|||
const { user: userCache } = require("@budibase/backend-core/cache")
|
||||
const newid = require("../../db/newid")
|
||||
const context = require("@budibase/backend-core/context")
|
||||
const { generateDevInfoID, SEPARATOR } = require("@budibase/backend-core/db")
|
||||
const { encrypt } = require("@budibase/backend-core/encryption")
|
||||
|
||||
const GLOBAL_USER_ID = "us_uuid1"
|
||||
const EMAIL = "babs@babs.com"
|
||||
|
@ -83,6 +85,20 @@ class TestConfiguration {
|
|||
}
|
||||
}
|
||||
|
||||
async generateApiKey(userId = GLOBAL_USER_ID) {
|
||||
const db = getGlobalDB(TENANT_ID)
|
||||
const id = generateDevInfoID(userId)
|
||||
let devInfo
|
||||
try {
|
||||
devInfo = await db.get(id)
|
||||
} catch (err) {
|
||||
devInfo = { _id: id, userId }
|
||||
}
|
||||
devInfo.apiKey = encrypt(`${TENANT_ID}${SEPARATOR}${newid()}`)
|
||||
await db.put(devInfo)
|
||||
return devInfo.apiKey
|
||||
}
|
||||
|
||||
async globalUser({
|
||||
id = GLOBAL_USER_ID,
|
||||
builder = true,
|
||||
|
@ -135,7 +151,7 @@ class TestConfiguration {
|
|||
cleanup(this.allApps.map(app => app.appId))
|
||||
}
|
||||
|
||||
defaultHeaders() {
|
||||
defaultHeaders(extras = {}) {
|
||||
const auth = {
|
||||
userId: GLOBAL_USER_ID,
|
||||
sessionId: "sessionid",
|
||||
|
@ -154,6 +170,7 @@ class TestConfiguration {
|
|||
`${Cookies.CurrentApp}=${appToken}`,
|
||||
],
|
||||
[Headers.CSRF_TOKEN]: CSRF_TOKEN,
|
||||
...extras,
|
||||
}
|
||||
if (this.appId) {
|
||||
headers[Headers.APP_ID] = this.appId
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue