better tests and cleaner import for server

This commit is contained in:
Martin McKeaveney 2022-09-15 19:51:11 +01:00
parent ef1c869b69
commit 65d41fdd20
21 changed files with 444 additions and 366 deletions

View File

@ -60,7 +60,8 @@ jobs:
# install: false # install: false
# command: yarn test:e2e:ci # command: yarn test:e2e:ci
- run: | - name: QA Core Integration Tests
run: |
cd qa-core cd qa-core
yarn yarn
yarn api:test:ci yarn api:test:ci

View File

@ -1377,6 +1377,11 @@ bcrypt@5.0.1:
"@mapbox/node-pre-gyp" "^1.0.0" "@mapbox/node-pre-gyp" "^1.0.0"
node-addon-api "^3.1.0" node-addon-api "^3.1.0"
bcryptjs@2.4.3:
version "2.4.3"
resolved "https://registry.yarnpkg.com/bcryptjs/-/bcryptjs-2.4.3.tgz#9ab5627b93e60621ff7cdac5da9733027df1d0cb"
integrity sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==
binary-extensions@^2.0.0: binary-extensions@^2.0.0:
version "2.2.0" version "2.2.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"

View File

@ -1659,6 +1659,117 @@
"data" "data"
] ]
}, },
"rowSearch": {
"type": "object",
"properties": {
"query": {
"type": "object",
"properties": {
"allOr": {
"type": "boolean",
"description": "Specifies that a row should be returned if it satisfies any of the specified options, rather than requiring it to fulfill all the search parameters. This defaults to false, meaning AND logic will be used."
},
"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 in the format of an object with a \"low\" and \"high\" property.",
"example": {
"columnName1": {
"low": 10,
"high": 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."
}
}
}
},
"required": [
"query"
]
},
"nameSearch": { "nameSearch": {
"type": "object", "type": "object",
"properties": { "properties": {
@ -2129,115 +2240,7 @@
"content": { "content": {
"application/json": { "application/json": {
"schema": { "schema": {
"type": "object", "$ref": "#/components/schemas/rowSearch"
"required": [
"query"
],
"properties": {
"query": {
"type": "object",
"properties": {
"allOr": {
"type": "boolean",
"description": "Specifies that a row should be returned if it satisfies any of the specified options, rather than requiring it to fulfill all the search parameters. This defaults to false, meaning AND logic will be used."
},
"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 in the format of an object with a \"low\" and \"high\" property.",
"example": {
"columnName1": {
"low": 10,
"high": 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."
}
}
}
}
} }
} }
} }

View File

@ -1264,6 +1264,98 @@ components:
- _id - _id
required: required:
- data - data
rowSearch:
type: object
properties:
query:
type: object
properties:
allOr:
type: boolean
description: Specifies that a row should be returned if it satisfies any of the
specified options, rather than requiring it to fulfill all the
search parameters. This defaults to false, meaning AND logic
will be used.
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 in the format
of an object with a "low" and "high" property.
example:
columnName1:
low: 10
high: 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.
required:
- query
nameSearch: nameSearch:
type: object type: object
properties: properties:
@ -1544,97 +1636,7 @@ paths:
content: content:
application/json: application/json:
schema: schema:
type: object $ref: "#/components/schemas/rowSearch"
required:
- query
properties:
query:
type: object
properties:
allOr:
type: boolean
description: Specifies that a row should be returned if it satisfies any of the
specified options, rather than requiring it to fulfill
all the search parameters. This defaults to false,
meaning AND logic will be used.
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 in the format
of an object with a "low" and "high" property.
example:
columnName1:
low: 10
high: 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: responses:
"200": "200":
description: The response will contain an array of rows that match the search description: The response will contain an array of rows that match the search

View File

@ -2,6 +2,122 @@ const { object } = require("./utils")
const Resource = require("./utils/Resource") const Resource = require("./utils/Resource")
module.exports = new Resource().setSchemas({ module.exports = new Resource().setSchemas({
rowSearch: object(
{
query: {
type: "object",
properties: {
allOr: {
type: "boolean",
description:
"Specifies that a row should be returned if it satisfies any of the specified options, rather than requiring it to fulfill all the search parameters. This defaults to false, meaning AND logic will be used.",
},
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 in the format of an object with a "low" and "high" property.',
example: {
columnName1: {
low: 10,
high: 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.",
},
},
},
},
{
required: ["query"],
}
),
nameSearch: object({ nameSearch: object({
name: { name: {
type: "string", type: "string",

View File

@ -18,4 +18,4 @@ export type CreateUserParams = components["schemas"]["user"]
export type SearchInputParams = export type SearchInputParams =
| components["schemas"]["nameSearch"] | components["schemas"]["nameSearch"]
| components["schemas"]["querySearch"] | components["schemas"]["rowSearch"]

View File

@ -143,88 +143,7 @@ read.push(new Endpoint("get", "/tables/:tableId/rows/:rowId", controller.read))
* content: * content:
* application/json: * application/json:
* schema: * schema:
* type: object * $ref: '#/components/schemas/rowSearch'
* required:
* - query
* properties:
* query:
* type: object
* properties:
* allOr:
* type: boolean
* description: Specifies that a row should be returned if it satisfies
* any of the specified options, rather than requiring it to fulfill all
* the search parameters. This defaults to false, meaning AND logic will be used.
* 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
* in the format of an object with a "low" and "high" property.
* example:
* columnName1: { low: 10, high: 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: * responses:
* 200: * 200:
* description: The response will contain an array of rows that match the search parameters. * description: The response will contain an array of rows that match the search parameters.

View File

@ -278,58 +278,7 @@ export interface paths {
}; };
requestBody: { requestBody: {
content: { content: {
"application/json": { "application/json": components["schemas"]["rowSearch"];
query: {
/** @description Specifies that a row should be returned if it satisfies any of the specified options, rather than requiring it to fulfill all the search parameters. This defaults to false, meaning AND logic will be used. */
allOr?: boolean;
/**
* @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.
* @example [object Object]
*/
string?: { [key: string]: string };
/** @description A fuzzy search, only supported by internal tables. */
fuzzy?: { [key: string]: unknown };
/**
* @description Searches within a range, the format of this must be in the format of an object with a "low" and "high" property.
* @example [object Object]
*/
range?: { [key: string]: unknown };
/** @description Searches for rows that have a column value that is exactly the value set. */
equal?: { [key: string]: unknown };
/** @description Searches for any row which does not contain the specified column value. */
notEqual?: { [key: string]: unknown };
/**
* @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 [object Object]
*/
empty?: { [key: string]: unknown };
/** @description Searches for rows which have the specified column. */
notEmpty?: { [key: string]: unknown };
/** @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]. */
oneOf?: { [key: string]: unknown };
};
/** @description Enables pagination, by default this is disabled. */
paginate?: boolean;
/** @description If retrieving another page, the bookmark from the previous request must be supplied. */
bookmark?: string | number;
/** @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. */
limit?: number;
/** @description A set of parameters describing the sort behaviour of the search. */
sort?: {
/**
* @description The order of the sort, by default this is ascending.
* @enum {string}
*/
order?: "ascending" | "descending";
/** @description The name of the column by which the rows will be sorted. */
column?: string;
/**
* @description Defines whether the column should be treated as a string or as numbers when sorting.
* @enum {string}
*/
type?: "string" | "number";
};
};
}; };
}; };
}; };
@ -1105,6 +1054,58 @@ export interface components {
_id: string; _id: string;
}[]; }[];
}; };
rowSearch: {
query: {
/** @description Specifies that a row should be returned if it satisfies any of the specified options, rather than requiring it to fulfill all the search parameters. This defaults to false, meaning AND logic will be used. */
allOr?: boolean;
/**
* @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.
* @example [object Object]
*/
string?: { [key: string]: string };
/** @description A fuzzy search, only supported by internal tables. */
fuzzy?: { [key: string]: unknown };
/**
* @description Searches within a range, the format of this must be in the format of an object with a "low" and "high" property.
* @example [object Object]
*/
range?: { [key: string]: unknown };
/** @description Searches for rows that have a column value that is exactly the value set. */
equal?: { [key: string]: unknown };
/** @description Searches for any row which does not contain the specified column value. */
notEqual?: { [key: string]: unknown };
/**
* @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 [object Object]
*/
empty?: { [key: string]: unknown };
/** @description Searches for rows which have the specified column. */
notEmpty?: { [key: string]: unknown };
/** @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]. */
oneOf?: { [key: string]: unknown };
};
/** @description Enables pagination, by default this is disabled. */
paginate?: boolean;
/** @description If retrieving another page, the bookmark from the previous request must be supplied. */
bookmark?: string | number;
/** @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. */
limit?: number;
/** @description A set of parameters describing the sort behaviour of the search. */
sort?: {
/**
* @description The order of the sort, by default this is ascending.
* @enum {string}
*/
order?: "ascending" | "descending";
/** @description The name of the column by which the rows will be sorted. */
column?: string;
/**
* @description Defines whether the column should be treated as a string or as numbers when sorting.
* @enum {string}
*/
type?: "string" | "number";
};
};
nameSearch: { nameSearch: {
/** @description The name to be used when searching - this will be used in a case insensitive starts with match. */ /** @description The name to be used when searching - this will be used in a case insensitive starts with match. */
name: string; name: string;

View File

@ -21,7 +21,8 @@
"preset": "ts-jest", "preset": "ts-jest",
"testEnvironment": "node", "testEnvironment": "node",
"moduleNameMapper": { "moduleNameMapper": {
"@budibase/types": "<rootDir>/../packages/types/src" "@budibase/types": "<rootDir>/../packages/types/src",
"@budibase/server": "<rootDir>/../packages/server/src"
}, },
"setupFiles": [ "setupFiles": [
"./scripts/jestSetup.js" "./scripts/jestSetup.js"

View File

@ -3,7 +3,7 @@ import {
Application, Application,
SearchInputParams, SearchInputParams,
CreateApplicationParams, CreateApplicationParams,
} from "../../../../../packages/server/src/api/controllers/public/mapping/types" } from "@budibase/server/api/controllers/public/mapping/types"
import { Response } from "node-fetch" import { Response } from "node-fetch"
import generateApp from "../fixtures/applications" import generateApp from "../fixtures/applications"
@ -32,7 +32,7 @@ export default class AppApi {
return [response, json.data] return [response, json.data]
} }
async search(body: SearchInputParams): Promise<[Response, Application]> { async search(body: SearchInputParams): Promise<[Response, [Application]]> {
const response = await this.api.post(`/applications/search`, { body }) const response = await this.api.post(`/applications/search`, { body })
const json = await response.json() const json = await response.json()
return [response, json.data] return [response, json.data]

View File

@ -3,8 +3,9 @@ import {
CreateRowParams, CreateRowParams,
Row, Row,
SearchInputParams, SearchInputParams,
} from "../../../../../packages/server/src/api/controllers/public/mapping/types" } from "@budibase/server/api/controllers/public/mapping/types"
import { HeadersInit, Response } from "node-fetch" import { HeadersInit, Response } from "node-fetch"
import { generateRow } from "../fixtures/tables"
export default class RowApi { export default class RowApi {
api: PublicAPIClient api: PublicAPIClient
@ -15,6 +16,10 @@ export default class RowApi {
this.api = apiClient this.api = apiClient
} }
async seed(tableId: string) {
return this.create(generateRow({ tableId }))
}
async create(body: CreateRowParams): Promise<[Response, Row]> { async create(body: CreateRowParams): Promise<[Response, Row]> {
const response = await this.api.post(`/tables/${this.tableId}/rows`, { const response = await this.api.post(`/tables/${this.tableId}/rows`, {
body, body,
@ -29,7 +34,7 @@ export default class RowApi {
return [response, json.data] return [response, json.data]
} }
async search(body: SearchInputParams): Promise<[Response, Row]> { async search(body: SearchInputParams): Promise<[Response, [Row]]> {
const response = await this.api.post( const response = await this.api.post(
`/tables/${this.tableId}/rows/search`, `/tables/${this.tableId}/rows/search`,
{ body } { body }

View File

@ -3,7 +3,7 @@ import {
Table, Table,
SearchInputParams, SearchInputParams,
CreateTableParams, CreateTableParams,
} from "../../../../../packages/server/src/api/controllers/public/mapping/types" } from "@budibase/server/api/controllers/public/mapping/types"
import { HeadersInit, Response } from "node-fetch" import { HeadersInit, Response } from "node-fetch"
import { generateTable } from "../fixtures/tables" import { generateTable } from "../fixtures/tables"
@ -33,7 +33,7 @@ export default class TableApi {
return [response, json.data] return [response, json.data]
} }
async search(body: SearchInputParams): Promise<[Response, Table]> { async search(body: SearchInputParams): Promise<[Response, [Table]]> {
const response = await this.api.post(`/tables/search`, { body }) const response = await this.api.post(`/tables/search`, { body })
const json = await response.json() const json = await response.json()
return [response, json.data] return [response, json.data]

View File

@ -3,7 +3,7 @@ import {
CreateUserParams, CreateUserParams,
SearchInputParams, SearchInputParams,
User, User,
} from "../../../../../packages/server/src/api/controllers/public/mapping/types" } from "@budibase/server/api/controllers/public/mapping/types"
import { Response } from "node-fetch" import { Response } from "node-fetch"
import generateUser from "../fixtures/users" import generateUser from "../fixtures/users"
@ -30,7 +30,7 @@ export default class UserApi {
return [response, json.data] return [response, json.data]
} }
async search(body: SearchInputParams): Promise<[Response, User]> { async search(body: SearchInputParams): Promise<[Response, [User]]> {
const response = await this.api.post(`/users/search`, { body }) const response = await this.api.post(`/users/search`, { body })
const json = await response.json() const json = await response.json()
return [response, json.data] return [response, json.data]

View File

@ -2,7 +2,7 @@ import generator from "../TestConfiguration/generator"
import { import {
Application, Application,
CreateApplicationParams, CreateApplicationParams,
} from "../../../../../packages/server/src/api/controllers/public/mapping/types" } from "@budibase/server/api/controllers/public/mapping/types"
const generate = ( const generate = (
overrides: Partial<Application> = {} overrides: Partial<Application> = {}

View File

@ -3,14 +3,14 @@ import {
CreateTableParams, CreateTableParams,
Row, Row,
Table, Table,
} from "../../../../../packages/server/src/api/controllers/public/mapping/types" } from "@budibase/server/api/controllers/public/mapping/types"
import generator from "../TestConfiguration/generator" import generator from "../TestConfiguration/generator"
export const generateTable = ( export const generateTable = (
overrides: Partial<Table> = {} overrides: Partial<Table> = {}
): CreateTableParams => ({ ): CreateTableParams => ({
name: generator.word(), name: generator.word(),
primaryDisplay: "sasa", primaryDisplay: "testColumn",
schema: { schema: {
"Auto ID": { "Auto ID": {
autocolumn: true, autocolumn: true,
@ -30,8 +30,8 @@ export const generateTable = (
tableId: "ta_users", tableId: "ta_users",
type: "link", type: "link",
}, },
sasa: { testColumn: {
name: "sasa", name: "testColumn",
type: "string", type: "string",
}, },
"Updated At": { "Updated At": {
@ -54,7 +54,7 @@ export const generateTable = (
export const generateRow = (overrides: Partial<Row> = {}): CreateRowParams => ({ export const generateRow = (overrides: Partial<Row> = {}): CreateRowParams => ({
type: "row", type: "row",
tableId: "seed_table", tableId: "seed_table",
sasa: generator.word(), testColumn: generator.word(),
relationship: [generator.string({ length: 32, alpha: true, numeric: true })], relationship: [generator.string({ length: 32, alpha: true, numeric: true })],
...overrides, ...overrides,
}) })

View File

@ -1,7 +1,7 @@
import { import {
CreateUserParams, CreateUserParams,
User, User,
} from "../../../../../packages/server/src/api/controllers/public/mapping/types" } from "@budibase/server/api/controllers/public/mapping/types"
import generator from "../TestConfiguration/generator" import generator from "../TestConfiguration/generator"
const generate = (overrides: Partial<User> = {}): CreateUserParams => ({ const generate = (overrides: Partial<User> = {}): CreateUserParams => ({

View File

@ -1,7 +1,7 @@
import TestConfiguration from "../../../config/public-api/TestConfiguration" import TestConfiguration from "../../../config/public-api/TestConfiguration"
import PublicAPIClient from "../../../config/public-api/TestConfiguration/PublicAPIClient" import PublicAPIClient from "../../../config/public-api/TestConfiguration/PublicAPIClient"
import generateApp from "../../../config/public-api/fixtures/applications" import generateApp from "../../../config/public-api/fixtures/applications"
import { Application } from "../../../../../packages/server/src/api/controllers/public/mapping/types" import { Application } from "@budibase/server/api/controllers/public/mapping/types"
describe("Public API - /applications endpoints", () => { describe("Public API - /applications endpoints", () => {
const api = new PublicAPIClient() const api = new PublicAPIClient()
@ -20,18 +20,21 @@ describe("Public API - /applications endpoints", () => {
it("POST - Create an application", async () => { it("POST - Create an application", async () => {
const [response, app] = await config.applications.create(generateApp()) const [response, app] = await config.applications.create(generateApp())
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(app._id).toBeDefined()
}) })
it("POST - Search applications", async () => { it("POST - Search applications", async () => {
const [response, app] = await config.applications.search({ const [response, apps] = await config.applications.search({
name: config.context.name, name: config.context.name,
}) })
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(apps[0]).toEqual(config.context)
}) })
it("GET - Retrieve an application", async () => { it("GET - Retrieve an application", async () => {
const [response, app] = await config.applications.read(config.context._id) const [response, app] = await config.applications.read(config.context._id)
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(app).toEqual(config.context)
}) })
it("PUT - update an application", async () => { it("PUT - update an application", async () => {
@ -41,5 +44,7 @@ describe("Public API - /applications endpoints", () => {
config.context config.context
) )
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(app.updatedAt).not.toEqual(config.context.updatedAt)
expect(app.name).toEqual(config.context.name)
}) })
}) })

View File

@ -1,4 +1,4 @@
import { Row } from "../../../../../packages/server/src/api/controllers/public/mapping/types" import { Row } from "@budibase/server/api/controllers/public/mapping/types"
import { generateRow } from "../../../config/public-api/fixtures/tables" import { generateRow } from "../../../config/public-api/fixtures/tables"
import TestConfiguration from "../../../config/public-api/TestConfiguration" import TestConfiguration from "../../../config/public-api/TestConfiguration"
import PublicAPIClient from "../../../config/public-api/TestConfiguration/PublicAPIClient" import PublicAPIClient from "../../../config/public-api/TestConfiguration/PublicAPIClient"
@ -10,15 +10,15 @@ describe("Public API - /rows endpoints", () => {
beforeAll(async () => { beforeAll(async () => {
await config.beforeAll() await config.beforeAll()
const [appResp, app] = await config.applications.seed() const [aResp, app] = await config.applications.seed()
config.tables.api.appId = app._id config.tables.api.appId = app._id
config.rows.api.appId = app._id config.rows.api.appId = app._id
const [tableResp, table] = await config.tables.seed() const [tResp, table] = await config.tables.seed()
config.rows.tableId = table._id config.rows.tableId = table._id
const [response, row] = await config.rows.create(generateRow()) const [rResp, row] = await config.rows.seed(table._id)
config.context = row config.context = row
}) })
@ -29,26 +29,37 @@ describe("Public API - /rows endpoints", () => {
it("POST - Create a row", async () => { it("POST - Create a row", async () => {
const [response, row] = await config.rows.create(generateRow()) const [response, row] = await config.rows.create(generateRow())
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(row._id).toBeDefined()
}) })
it("POST - Search rows", async () => { it("POST - Search rows", async () => {
const [response, row] = await config.rows.search({ const [response, rows] = await config.rows.search({
name: config.context.name as string, query: {
string: {
testColumn: config.context.testColumn as string,
},
},
}) })
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(rows[0]._id).toEqual(config.context._id)
expect(rows[0].tableId).toEqual(config.context.tableId)
expect(rows[0].testColumn).toEqual(config.context.testColumn)
}) })
it("GET - Retrieve a row", async () => { it("GET - Retrieve a row", async () => {
const [response, row] = await config.rows.read(config.context._id) const [response, row] = await config.rows.read(config.context._id)
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(row._id).toEqual(config.context._id)
expect(row.tableId).toEqual(config.context.tableId)
}) })
it("PUT - update a row", async () => { it("PUT - update a row", async () => {
config.context.name = "UpdatedName" config.context.testColumn = "UpdatedName"
const [response, row] = await config.rows.update( const [response, row] = await config.rows.update(
config.context._id, config.context._id,
config.context config.context
) )
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(row.testColumn).toEqual(config.context.testColumn)
}) })
}) })

View File

@ -1,4 +1,4 @@
import { Table } from "../../../../../packages/server/src/api/controllers/public/mapping/types" import { Table } from "@budibase/server/api/controllers/public/mapping/types"
import { generateTable } from "../../../config/public-api/fixtures/tables" import { generateTable } from "../../../config/public-api/fixtures/tables"
import TestConfiguration from "../../../config/public-api/TestConfiguration" import TestConfiguration from "../../../config/public-api/TestConfiguration"
import PublicAPIClient from "../../../config/public-api/TestConfiguration/PublicAPIClient" import PublicAPIClient from "../../../config/public-api/TestConfiguration/PublicAPIClient"
@ -23,18 +23,21 @@ describe("Public API - /tables endpoints", () => {
it("POST - Create a table", async () => { it("POST - Create a table", async () => {
const [response, table] = await config.tables.create(generateTable()) const [response, table] = await config.tables.create(generateTable())
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(table._id).toBeDefined()
}) })
it("POST - Search tables", async () => { it("POST - Search tables", async () => {
const [response, table] = await config.tables.search({ const [response, tables] = await config.tables.search({
name: config.context.name, name: config.context.name,
}) })
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(tables[0]).toEqual(config.context)
}) })
it("GET - Retrieve a table", async () => { it("GET - Retrieve a table", async () => {
const [response, table] = await config.tables.read(config.context._id) const [response, table] = await config.tables.read(config.context._id)
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(table).toEqual(config.context)
}) })
it("PUT - update a table", async () => { it("PUT - update a table", async () => {
@ -44,5 +47,6 @@ describe("Public API - /tables endpoints", () => {
config.context config.context
) )
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(table).toEqual(config.context)
}) })
}) })

View File

@ -1,7 +1,7 @@
import TestConfiguration from "../../../config/public-api/TestConfiguration" import TestConfiguration from "../../../config/public-api/TestConfiguration"
import PublicAPIClient from "../../../config/public-api/TestConfiguration/PublicAPIClient" import PublicAPIClient from "../../../config/public-api/TestConfiguration/PublicAPIClient"
import generateUser from "../../../config/public-api/fixtures/users" import generateUser from "../../../config/public-api/fixtures/users"
import { User } from "../../../../../packages/server/src/api/controllers/public/mapping/types" import { User } from "@budibase/server/api/controllers/public/mapping/types"
describe("Public API - /users endpoints", () => { describe("Public API - /users endpoints", () => {
const api = new PublicAPIClient() const api = new PublicAPIClient()
@ -9,7 +9,7 @@ describe("Public API - /users endpoints", () => {
beforeAll(async () => { beforeAll(async () => {
await config.beforeAll() await config.beforeAll()
const [response, user] = await config.users.seed() const [_, user] = await config.users.seed()
config.context = user config.context = user
}) })
@ -20,18 +20,21 @@ describe("Public API - /users endpoints", () => {
it("POST - Create a user", async () => { it("POST - Create a user", async () => {
const [response, user] = await config.users.create(generateUser()) const [response, user] = await config.users.create(generateUser())
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(user._id).toBeDefined()
}) })
it("POST - Search users", async () => { it("POST - Search users", async () => {
const [response, user] = await config.users.search({ const [response, users] = await config.users.search({
name: config.context.email, name: config.context.email,
}) })
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(users[0]).toEqual(config.context)
}) })
it("GET - Retrieve a user", async () => { it("GET - Retrieve a user", async () => {
const [response, user] = await config.users.read(config.context._id) const [response, user] = await config.users.read(config.context._id)
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(user).toEqual(config.context)
}) })
it("PUT - update a user", async () => { it("PUT - update a user", async () => {
@ -41,5 +44,6 @@ describe("Public API - /users endpoints", () => {
config.context config.context
) )
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(user).toEqual(config.context)
}) })
}) })

View File

@ -14,6 +14,7 @@
"skipLibCheck": true, "skipLibCheck": true,
"paths": { "paths": {
"@budibase/types": ["../packages/types/src"], "@budibase/types": ["../packages/types/src"],
"@budibase/server/*": ["../packages/server/src/*"],
} }
}, },
"ts-node": { "ts-node": {