QA Core repo, and Jest API tests running end to end
This commit is contained in:
parent
9756d9bd17
commit
c3f15b5af2
|
@ -54,8 +54,10 @@ jobs:
|
|||
verbose: true
|
||||
|
||||
# TODO: parallelise this
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@v2
|
||||
with:
|
||||
install: false
|
||||
command: yarn test:e2e:ci
|
||||
# - name: Cypress run
|
||||
# uses: cypress-io/github-action@v2
|
||||
# with:
|
||||
# install: false
|
||||
# command: yarn test:e2e:ci
|
||||
|
||||
- run: yarn test:api:ci
|
|
@ -8,4 +8,4 @@ packages/server/client
|
|||
packages/server/src/definitions/openapi.ts
|
||||
packages/builder/.routify
|
||||
packages/builder/cypress/support/queryLevelTransformerFunction.js
|
||||
packages/builder/cypress/support/queryLevelTransformerFunctionWithData.js
|
||||
packages/builder/cypress/support/queryLevelTransformerFunctionWithData.js
|
|
@ -52,6 +52,8 @@
|
|||
"test:e2e:ci": "lerna run cy:ci --stream",
|
||||
"test:e2e:ci:record": "lerna run cy:ci:record --stream",
|
||||
"test:e2e:ci:notify": "lerna run cy:ci:notify",
|
||||
"test:api:ci": "npm --prefix ./qa-core run api:test:ci",
|
||||
"test:api": "npm --prefix ./qa-core run api:test",
|
||||
"build:specs": "lerna run specs",
|
||||
"build:docker": "lerna run build:docker && npm run build:docker:proxy:compose && cd hosting/scripts/linux/ && ./release-to-docker-hub.sh $BUDIBASE_RELEASE_VERSION && cd -",
|
||||
"build:docker:pre": "lerna run build && lerna run predocker",
|
||||
|
|
|
@ -22,6 +22,12 @@ process.env.COUCH_DB_PASSWORD = "budibase"
|
|||
process.env.INTERNAL_API_KEY = "budibase"
|
||||
process.env.ALLOW_DEV_AUTOMATIONS = 1
|
||||
|
||||
// TODO: inject at the qa-core level
|
||||
process.env.BB_ADMIN_USER_EMAIL = "qa@budibase.com"
|
||||
process.env.BB_ADMIN_USER_PASSWORD = "budibase"
|
||||
process.env.ENCRYPTED_TEST_PUBLIC_API_KEY =
|
||||
"a65722f06bee5caeadc5d7ca2f543a43-d610e627344210c643bb726f"
|
||||
|
||||
// Stop info logs polluting test outputs
|
||||
process.env.LOG_LEVEL = "error"
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@ describe("/users", () => {
|
|||
})
|
||||
|
||||
describe("fetch", () => {
|
||||
|
||||
it("returns a list of users from an instance db", async () => {
|
||||
await config.createUser("uuidx")
|
||||
await config.createUser("uuidy")
|
||||
|
|
|
@ -29,7 +29,11 @@ const { Thread } = require("./threads")
|
|||
import redis from "./utilities/redis"
|
||||
import * as migrations from "./migrations"
|
||||
import { events, installation, tenancy } from "@budibase/backend-core"
|
||||
import { createAdminUser, getChecklist } from "./utilities/workerRequests"
|
||||
import {
|
||||
createAdminUser,
|
||||
generateApiKey,
|
||||
getChecklist,
|
||||
} from "./utilities/workerRequests"
|
||||
|
||||
const app = new Koa()
|
||||
|
||||
|
@ -123,11 +127,16 @@ module.exports = server.listen(env.PORT || 0, async () => {
|
|||
if (!checklist?.adminUser?.checked) {
|
||||
try {
|
||||
const tenantId = tenancy.getTenantId()
|
||||
await createAdminUser(
|
||||
const user = await createAdminUser(
|
||||
env.BB_ADMIN_USER_EMAIL,
|
||||
env.BB_ADMIN_USER_PASSWORD,
|
||||
tenantId
|
||||
)
|
||||
// Need to set up an API key for automated integration tests
|
||||
if (env.isTest()) {
|
||||
await generateApiKey(user._id)
|
||||
}
|
||||
|
||||
console.log(
|
||||
"Admin account automatically created for",
|
||||
env.BB_ADMIN_USER_EMAIL
|
||||
|
|
|
@ -153,3 +153,11 @@ exports.getChecklist = async () => {
|
|||
)
|
||||
return checkResponse(response, "get checklist")
|
||||
}
|
||||
|
||||
exports.generateApiKey = async userId => {
|
||||
const response = await fetch(
|
||||
checkSlashesInUrl(env.WORKER_URL + "/api/global/self/api_key"),
|
||||
request(null, { method: "POST", body: { userId } })
|
||||
)
|
||||
return checkResponse(response, "generate API key")
|
||||
}
|
||||
|
|
|
@ -16,6 +16,11 @@ const { newid } = require("@budibase/backend-core/utils")
|
|||
const { users } = require("../../../sdk")
|
||||
const { Cookies } = require("@budibase/backend-core/constants")
|
||||
const { events, featureFlags } = require("@budibase/backend-core")
|
||||
const env = require("../../../environment")
|
||||
|
||||
function newTestApiKey() {
|
||||
return env.ENCRYPTED_TEST_PUBLIC_API_KEY
|
||||
}
|
||||
|
||||
function newApiKey() {
|
||||
return encrypt(`${getTenantId()}${SEPARATOR}${newid()}`)
|
||||
|
@ -29,15 +34,25 @@ function cleanupDevInfo(info) {
|
|||
}
|
||||
|
||||
exports.generateAPIKey = async ctx => {
|
||||
let userId
|
||||
let apiKey
|
||||
if (env.isTest() && ctx.request.body.userId) {
|
||||
userId = ctx.request.body.userId
|
||||
apiKey = newTestApiKey()
|
||||
} else {
|
||||
userId = ctx.user._id
|
||||
apiKey = newApiKey()
|
||||
}
|
||||
|
||||
const db = getGlobalDB()
|
||||
const id = generateDevInfoID(ctx.user._id)
|
||||
const id = generateDevInfoID(userId)
|
||||
let devInfo
|
||||
try {
|
||||
devInfo = await db.get(id)
|
||||
} catch (err) {
|
||||
devInfo = { _id: id, userId: ctx.user._id }
|
||||
devInfo = { _id: id, userId }
|
||||
}
|
||||
devInfo.apiKey = await newApiKey()
|
||||
devInfo.apiKey = await apiKey
|
||||
await db.put(devInfo)
|
||||
ctx.body = cleanupDevInfo(devInfo)
|
||||
}
|
||||
|
|
|
@ -62,6 +62,7 @@ const env = {
|
|||
// other
|
||||
CHECKLIST_CACHE_TTL: parseIntSafe(process.env.CHECKLIST_CACHE_TTL) || 3600,
|
||||
SESSION_UPDATE_PERIOD: process.env.SESSION_UPDATE_PERIOD,
|
||||
ENCRYPTED_TEST_PUBLIC_API_KEY: process.env.ENCRYPTED_TEST_PUBLIC_API_KEY,
|
||||
_set(key: any, value: any) {
|
||||
process.env[key] = value
|
||||
module.exports[key] = value
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
node_modules/
|
||||
.env
|
||||
watchtower-hook.json
|
||||
dist/
|
|
@ -0,0 +1,52 @@
|
|||
{
|
||||
"name": "@budibase/qa-core",
|
||||
"email": "hi@budibase.com",
|
||||
"version": "0.0.1",
|
||||
"main": "index.js",
|
||||
"description": "Budibase Integration Test Suite",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Budibase/budibase.git"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "jest --runInBand",
|
||||
"test:watch": "jest --watch",
|
||||
"test:debug": "DEBUG=1 jest",
|
||||
"api:server:setup": "ts-node ../packages/builder/cypress/ts/setup.ts",
|
||||
"api:server:setup:ci": "node ../packages/builder/cypress/setup.js",
|
||||
"api:test:ci": "start-server-and-test api:server:setup:ci http://localhost:4100/builder test",
|
||||
"api:test": "start-server-and-test api:server:setup http://localhost:4100/builder test"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "ts-jest",
|
||||
"testEnvironment": "node",
|
||||
"moduleNameMapper": {
|
||||
"@budibase/backend-core/(.*)": "<rootDir>/../packages/backend-core/$1",
|
||||
"@budibase/backend-core": "<rootDir>/../packages/backend-core/src",
|
||||
"@budibase/types": "<rootDir>/../packages/types/src"
|
||||
},
|
||||
"setupFiles": [
|
||||
"./scripts/jestSetup.js"
|
||||
],
|
||||
"setupFilesAfterEnv": [
|
||||
"./src/jest.extends.ts"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@budibase/types": "^1.3.4",
|
||||
"@types/jest": "^29.0.0",
|
||||
"@types/node-fetch": "^2.6.2",
|
||||
"chance": "^1.1.8",
|
||||
"jest": "^28.0.2",
|
||||
"prettier": "^2.7.1",
|
||||
"start-server-and-test": "^1.14.0",
|
||||
"timekeeper": "^2.2.0",
|
||||
"ts-jest": "28.0.8",
|
||||
"ts-node": "^10.9.1",
|
||||
"tsconfig-paths": "^4.1.0",
|
||||
"typescript": "^4.8.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"node-fetch": "2"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
const env = require("../src/environment")
|
||||
|
||||
env._set("BUDIBASE_SERVER_URL", "http://localhost:4100")
|
||||
env._set("BUDIBASE_PUBLIC_API_KEY", "a65722f06bee5caeadc5d7ca2f543a43-d610e627344210c643bb726f")
|
||||
|
||||
// mock all dates to 2020-01-01T00:00:00.000Z
|
||||
// use tk.reset() to use real dates in individual tests
|
||||
const MOCK_DATE = new Date("2020-01-01T00:00:00.000Z")
|
||||
const MOCK_DATE_TIMESTAMP = 1577836800000
|
||||
const tk = require("timekeeper")
|
||||
tk.freeze(MOCK_DATE)
|
||||
|
||||
if (!process.env.DEBUG) {
|
||||
global.console.log = jest.fn() // console.log are ignored in tests
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
export = {
|
||||
BUDIBASE_SERVER_URL: process.env.BUDIBASE_SERVER_URL,
|
||||
BUDIBASE_PUBLIC_API_KEY: process.env.BUDIBASE_PUBLIC_API_KEY,
|
||||
_set(key: any, value: any) {
|
||||
process.env[key] = value
|
||||
module.exports[key] = value
|
||||
},
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
// boilerplate to allow TS updates to the global scope
|
||||
export {};
|
||||
|
||||
declare global {
|
||||
namespace jest {
|
||||
interface Matchers<R> {
|
||||
toHaveStatusCode(code: number): R;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Expect extensions
|
||||
expect.extend({
|
||||
toHaveStatusCode(received, code) {
|
||||
const pass = received.status === code
|
||||
return {
|
||||
message: () =>
|
||||
`expected ${received.status} to match status code ${code}`,
|
||||
pass,
|
||||
}
|
||||
},
|
||||
})
|
|
@ -0,0 +1,58 @@
|
|||
import env from "../../environment"
|
||||
import fetch from "node-fetch"
|
||||
|
||||
interface HeaderOptions {
|
||||
headers?: object;
|
||||
body?: object;
|
||||
json?: boolean;
|
||||
}
|
||||
|
||||
type APIMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE"
|
||||
|
||||
class PublicAPIClient {
|
||||
host: string
|
||||
apiKey: string
|
||||
appId?: string
|
||||
|
||||
constructor(appId?: string) {
|
||||
if (!env.BUDIBASE_PUBLIC_API_KEY || !env.BUDIBASE_SERVER_URL) {
|
||||
throw new Error("Must set BUDIBASE_PUBLIC_API_KEY and BUDIBASE_SERVER_URL env vars")
|
||||
}
|
||||
this.host = `${env.BUDIBASE_SERVER_URL}/api/public/v1`
|
||||
this.apiKey = env.BUDIBASE_PUBLIC_API_KEY
|
||||
this.appId = appId
|
||||
}
|
||||
|
||||
apiCall =
|
||||
(method: APIMethod) =>
|
||||
async (url = "", options: HeaderOptions = {}) => {
|
||||
const requestOptions = {
|
||||
method: method,
|
||||
body: JSON.stringify(options.body),
|
||||
headers: {
|
||||
"x-budibase-api-key": this.apiKey,
|
||||
"x-budibase-app-id": this.appId,
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
...options.headers,
|
||||
},
|
||||
// TODO: See if this is necessary
|
||||
credentials: "include",
|
||||
}
|
||||
|
||||
// @ts-ignore
|
||||
const response = await fetch(`${this.host}${url}`, requestOptions)
|
||||
if (response.status !== 200) {
|
||||
console.error(response)
|
||||
}
|
||||
return response
|
||||
}
|
||||
|
||||
post = this.apiCall("POST")
|
||||
get = this.apiCall("GET")
|
||||
patch = this.apiCall("PATCH")
|
||||
del = this.apiCall("DELETE")
|
||||
put = this.apiCall("PUT")
|
||||
}
|
||||
|
||||
export default PublicAPIClient
|
|
@ -0,0 +1,39 @@
|
|||
import PublicAPIClient from "./PublicAPIClient";
|
||||
import generateApp from "./applications/fixtures/generate"
|
||||
|
||||
class TestConfiguration {
|
||||
testContext: Record<string, any>;
|
||||
apiClient: PublicAPIClient;
|
||||
|
||||
constructor() {
|
||||
this.testContext = {}
|
||||
this.apiClient = new PublicAPIClient()
|
||||
}
|
||||
|
||||
async beforeAll() {
|
||||
|
||||
}
|
||||
|
||||
async afterAll() {
|
||||
}
|
||||
|
||||
async seedTable(appId: string) {
|
||||
const response = await this.apiClient.post("/tables", {
|
||||
body: require("./tables/fixtures/seed.json"),
|
||||
headers: {
|
||||
"x-budibase-app-id": appId
|
||||
}
|
||||
})
|
||||
const json = await response.json()
|
||||
return json.data
|
||||
}
|
||||
|
||||
async seedApp() {
|
||||
const response = await this.apiClient.post("/applications", {
|
||||
body: generateApp()
|
||||
})
|
||||
return response.json()
|
||||
}
|
||||
}
|
||||
|
||||
export default TestConfiguration
|
|
@ -0,0 +1,47 @@
|
|||
import TestConfiguration from "../TestConfiguration"
|
||||
import PublicAPIClient from "../PublicAPIClient"
|
||||
import generateApp from "./fixtures/generate"
|
||||
|
||||
describe("Public API - /applications endpoints", () => {
|
||||
const api = new PublicAPIClient()
|
||||
const config = new TestConfiguration()
|
||||
|
||||
beforeAll(async () => {
|
||||
await config.beforeAll()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await config.afterAll()
|
||||
})
|
||||
|
||||
it("POST - Create a application", async () => {
|
||||
const response = await api.post(`/applications`, {
|
||||
body: generateApp()
|
||||
})
|
||||
const json = await response.json()
|
||||
config.testContext.application = json.data
|
||||
expect(response).toHaveStatusCode(200)
|
||||
})
|
||||
|
||||
it("POST - Search applications", async () => {
|
||||
const response = await api.post(`/applications/search`, {
|
||||
body: {
|
||||
name: config.testContext.application.name
|
||||
}
|
||||
})
|
||||
expect(response).toHaveStatusCode(200)
|
||||
})
|
||||
|
||||
it("GET - Retrieve a application", async () => {
|
||||
const response = await api.get(`/applications/${config.testContext.application._id}`)
|
||||
expect(response).toHaveStatusCode(200)
|
||||
})
|
||||
|
||||
|
||||
it("PUT - update a application", async () => {
|
||||
const response = await api.put(`/applications/${config.testContext.application._id}`, {
|
||||
body: require("./fixtures/update_application.json")
|
||||
})
|
||||
expect(response).toHaveStatusCode(200)
|
||||
})
|
||||
})
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"name": "TestApp",
|
||||
"url": "/testapp"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import generator from "../../generator"
|
||||
|
||||
const generate = (overrides = {}) => ({
|
||||
name: generator.word(),
|
||||
url: `/${generator.word()}`,
|
||||
...overrides
|
||||
})
|
||||
|
||||
export default generate
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"name": "SeedApp",
|
||||
"url": "/seedapp"
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
{
|
||||
"name": "UpdatedTestApp",
|
||||
"url": "/updatedtestapp"
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
const Chance = require("chance")
|
||||
|
||||
export default new Chance()
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"type": "row",
|
||||
"tableId": "seed_table",
|
||||
"sasa": "Mike",
|
||||
"relationship": [
|
||||
"ro_ta_"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
{
|
||||
"name": "test",
|
||||
"primaryDisplay": "sasa",
|
||||
"schema": {
|
||||
"Auto ID": {
|
||||
"autocolumn": true,
|
||||
"constraints": {
|
||||
"numericality": {
|
||||
"greaterThanOrEqualTo": "",
|
||||
"lessThanOrEqualTo": ""
|
||||
},
|
||||
"presence": false,
|
||||
"type": "number"
|
||||
},
|
||||
"icon": "ri-magic-line",
|
||||
"name": "Auto ID",
|
||||
"subtype": "autoID",
|
||||
"type": "number"
|
||||
},
|
||||
"Created At": {
|
||||
"autocolumn": true,
|
||||
"constraints": {
|
||||
"datetime": {
|
||||
"earliest": "",
|
||||
"latest": ""
|
||||
},
|
||||
"length": {},
|
||||
"presence": false,
|
||||
"type": "string"
|
||||
},
|
||||
"icon": "ri-magic-line",
|
||||
"name": "Created At",
|
||||
"subtype": "createdAt",
|
||||
"type": "datetime"
|
||||
},
|
||||
"Created By": {
|
||||
"autocolumn": true,
|
||||
"constraints": {
|
||||
"presence": false,
|
||||
"type": "array"
|
||||
},
|
||||
"fieldName": "test12-Created By",
|
||||
"icon": "ri-magic-line",
|
||||
"name": "Created By",
|
||||
"relationshipType": "many-to-many",
|
||||
"subtype": "createdBy",
|
||||
"tableId": "ta_users",
|
||||
"type": "link"
|
||||
},
|
||||
"sasa": {
|
||||
"constraints": {
|
||||
"length": {
|
||||
"maximum": null
|
||||
},
|
||||
"presence": {
|
||||
"allowEmpty": false
|
||||
},
|
||||
"type": "string"
|
||||
},
|
||||
"name": "sasa",
|
||||
"type": "string"
|
||||
},
|
||||
"Updated At": {
|
||||
"autocolumn": true,
|
||||
"constraints": {
|
||||
"datetime": {
|
||||
"earliest": "",
|
||||
"latest": ""
|
||||
},
|
||||
"length": {},
|
||||
"presence": false,
|
||||
"type": "string"
|
||||
},
|
||||
"icon": "ri-magic-line",
|
||||
"name": "Updated At",
|
||||
"subtype": "updatedAt",
|
||||
"type": "datetime"
|
||||
},
|
||||
"Updated By": {
|
||||
"autocolumn": true,
|
||||
"constraints": {
|
||||
"presence": false,
|
||||
"type": "array"
|
||||
},
|
||||
"fieldName": "test12-Updated By",
|
||||
"icon": "ri-magic-line",
|
||||
"name": "Updated By",
|
||||
"relationshipType": "many-to-many",
|
||||
"subtype": "updatedBy",
|
||||
"tableId": "ta_users",
|
||||
"type": "link"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
{
|
||||
"name": "test",
|
||||
"primaryDisplay": "sasa",
|
||||
"schema": {
|
||||
"Auto ID": {
|
||||
"autocolumn": true,
|
||||
"constraints": {
|
||||
"numericality": {
|
||||
"greaterThanOrEqualTo": "",
|
||||
"lessThanOrEqualTo": ""
|
||||
},
|
||||
"presence": false,
|
||||
"type": "number"
|
||||
},
|
||||
"icon": "ri-magic-line",
|
||||
"name": "Auto ID",
|
||||
"subtype": "autoID",
|
||||
"type": "number"
|
||||
},
|
||||
"Created At": {
|
||||
"autocolumn": true,
|
||||
"constraints": {
|
||||
"datetime": {
|
||||
"earliest": "",
|
||||
"latest": ""
|
||||
},
|
||||
"length": {},
|
||||
"presence": false,
|
||||
"type": "string"
|
||||
},
|
||||
"icon": "ri-magic-line",
|
||||
"name": "Created At",
|
||||
"subtype": "createdAt",
|
||||
"type": "datetime"
|
||||
},
|
||||
"Created By": {
|
||||
"autocolumn": true,
|
||||
"constraints": {
|
||||
"presence": false,
|
||||
"type": "array"
|
||||
},
|
||||
"fieldName": "test12-Created By",
|
||||
"icon": "ri-magic-line",
|
||||
"name": "Created By",
|
||||
"relationshipType": "many-to-many",
|
||||
"subtype": "createdBy",
|
||||
"tableId": "ta_users",
|
||||
"type": "link"
|
||||
},
|
||||
"sasa": {
|
||||
"constraints": {
|
||||
"length": {
|
||||
"maximum": null
|
||||
},
|
||||
"presence": {
|
||||
"allowEmpty": false
|
||||
},
|
||||
"type": "string"
|
||||
},
|
||||
"name": "sasa",
|
||||
"type": "string"
|
||||
},
|
||||
"Updated At": {
|
||||
"autocolumn": true,
|
||||
"constraints": {
|
||||
"datetime": {
|
||||
"earliest": "",
|
||||
"latest": ""
|
||||
},
|
||||
"length": {},
|
||||
"presence": false,
|
||||
"type": "string"
|
||||
},
|
||||
"icon": "ri-magic-line",
|
||||
"name": "Updated At",
|
||||
"subtype": "updatedAt",
|
||||
"type": "datetime"
|
||||
},
|
||||
"Updated By": {
|
||||
"autocolumn": true,
|
||||
"constraints": {
|
||||
"presence": false,
|
||||
"type": "array"
|
||||
},
|
||||
"fieldName": "test12-Updated By",
|
||||
"icon": "ri-magic-line",
|
||||
"name": "Updated By",
|
||||
"relationshipType": "many-to-many",
|
||||
"subtype": "updatedBy",
|
||||
"tableId": "ta_users",
|
||||
"type": "link"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"type": "row",
|
||||
"tableId": "seed_table",
|
||||
"sasa": "MikeIsTheBest",
|
||||
"relationship": [
|
||||
"ro_ta_..."
|
||||
]
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
{
|
||||
"name": "test123",
|
||||
"primaryDisplay": "sasa",
|
||||
"schema": {
|
||||
"Auto ID": {
|
||||
"autocolumn": true,
|
||||
"constraints": {
|
||||
"numericality": {
|
||||
"greaterThanOrEqualTo": "",
|
||||
"lessThanOrEqualTo": ""
|
||||
},
|
||||
"presence": false,
|
||||
"type": "number"
|
||||
},
|
||||
"icon": "ri-magic-line",
|
||||
"name": "Auto ID",
|
||||
"subtype": "autoID",
|
||||
"type": "number"
|
||||
},
|
||||
"Created At": {
|
||||
"autocolumn": true,
|
||||
"constraints": {
|
||||
"datetime": {
|
||||
"earliest": "",
|
||||
"latest": ""
|
||||
},
|
||||
"length": {},
|
||||
"presence": false,
|
||||
"type": "string"
|
||||
},
|
||||
"icon": "ri-magic-line",
|
||||
"name": "Created At",
|
||||
"subtype": "createdAt",
|
||||
"type": "datetime"
|
||||
},
|
||||
"Created By": {
|
||||
"autocolumn": true,
|
||||
"constraints": {
|
||||
"presence": false,
|
||||
"type": "array"
|
||||
},
|
||||
"fieldName": "test12-Created By",
|
||||
"icon": "ri-magic-line",
|
||||
"name": "Created By",
|
||||
"relationshipType": "many-to-many",
|
||||
"subtype": "createdBy",
|
||||
"tableId": "ta_users",
|
||||
"type": "link"
|
||||
},
|
||||
"sasa": {
|
||||
"constraints": {
|
||||
"length": {
|
||||
"maximum": null
|
||||
},
|
||||
"presence": {
|
||||
"allowEmpty": false
|
||||
},
|
||||
"type": "string"
|
||||
},
|
||||
"name": "sasa",
|
||||
"type": "string"
|
||||
},
|
||||
"Updated At": {
|
||||
"autocolumn": true,
|
||||
"constraints": {
|
||||
"datetime": {
|
||||
"earliest": "",
|
||||
"latest": ""
|
||||
},
|
||||
"length": {},
|
||||
"presence": false,
|
||||
"type": "string"
|
||||
},
|
||||
"icon": "ri-magic-line",
|
||||
"name": "Updated At",
|
||||
"subtype": "updatedAt",
|
||||
"type": "datetime"
|
||||
},
|
||||
"Updated By": {
|
||||
"autocolumn": true,
|
||||
"constraints": {
|
||||
"presence": false,
|
||||
"type": "array"
|
||||
},
|
||||
"fieldName": "test12-Updated By",
|
||||
"icon": "ri-magic-line",
|
||||
"name": "Updated By",
|
||||
"relationshipType": "many-to-many",
|
||||
"subtype": "updatedBy",
|
||||
"tableId": "ta_users",
|
||||
"type": "link"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
import TestConfiguration from "../TestConfiguration"
|
||||
import PublicAPIClient from "../PublicAPIClient"
|
||||
|
||||
describe("Public API - /rows endpoints", () => {
|
||||
let api: PublicAPIClient
|
||||
|
||||
const config = new TestConfiguration()
|
||||
|
||||
beforeAll(async () => {
|
||||
await config.beforeAll()
|
||||
const app = await config.seedApp()
|
||||
|
||||
config.testContext.table = await config.seedTable(app.data._id)
|
||||
api = new PublicAPIClient(app.data._id)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await config.afterAll()
|
||||
})
|
||||
|
||||
it("POST - Create a row", async () => {
|
||||
const response = await api.post(`/tables/${config.testContext.table._id}/rows`, {
|
||||
body: require("./fixtures/row.json")
|
||||
})
|
||||
const json = await response.json()
|
||||
config.testContext.row = json.data
|
||||
expect(response).toHaveStatusCode(200)
|
||||
})
|
||||
|
||||
it("POST - Search rows", async () => {
|
||||
const response = await api.post(`/tables/${config.testContext.table._id}/rows/search`, {
|
||||
body: {
|
||||
name: config.testContext.row.name
|
||||
}
|
||||
})
|
||||
expect(response).toHaveStatusCode(200)
|
||||
})
|
||||
|
||||
it("GET - Retrieve a row", async () => {
|
||||
const response = await api.get(`/tables/${config.testContext.table._id}/rows/${config.testContext.row._id}`)
|
||||
expect(response).toHaveStatusCode(200)
|
||||
})
|
||||
|
||||
|
||||
it("PUT - update a row", async () => {
|
||||
const response = await api.put(`/tables/${config.testContext.table._id}/rows/${config.testContext.row._id}`, {
|
||||
body: require("./fixtures/update_row.json")
|
||||
})
|
||||
expect(response).toHaveStatusCode(200)
|
||||
})
|
||||
})
|
|
@ -0,0 +1,48 @@
|
|||
import TestConfiguration from "../TestConfiguration"
|
||||
import PublicAPIClient from "../PublicAPIClient"
|
||||
|
||||
describe("Public API - /tables endpoints", () => {
|
||||
let api: PublicAPIClient
|
||||
const config = new TestConfiguration()
|
||||
|
||||
beforeAll(async () => {
|
||||
await config.beforeAll()
|
||||
const app = await config.seedApp()
|
||||
api = new PublicAPIClient(app.data._id)
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await config.afterAll()
|
||||
})
|
||||
|
||||
it("POST - Create a table", async () => {
|
||||
const response = await api.post(`/tables`, {
|
||||
body: require("./fixtures/table.json")
|
||||
})
|
||||
const json = await response.json()
|
||||
config.testContext.table = json.data
|
||||
expect(response).toHaveStatusCode(200)
|
||||
})
|
||||
|
||||
it("POST - Search tables", async () => {
|
||||
const response = await api.post(`/tables/search`, {
|
||||
body: {
|
||||
name: config.testContext.table.name
|
||||
}
|
||||
})
|
||||
expect(response).toHaveStatusCode(200)
|
||||
})
|
||||
|
||||
it("GET - Retrieve a table", async () => {
|
||||
const response = await api.get(`/tables/${config.testContext.table._id}`)
|
||||
expect(response).toHaveStatusCode(200)
|
||||
})
|
||||
|
||||
|
||||
it("PUT - update a table", async () => {
|
||||
const response = await api.put(`/tables/${config.testContext.table._id}`, {
|
||||
body: require("./fixtures/update_table.json")
|
||||
})
|
||||
expect(response).toHaveStatusCode(200)
|
||||
})
|
||||
})
|
|
@ -0,0 +1,22 @@
|
|||
import generator from "../../generator"
|
||||
import { User } from "@budibase/types"
|
||||
|
||||
const generate = (overrides = {}): User => ({
|
||||
tenantId: generator.word(),
|
||||
email: generator.email(),
|
||||
roles: {
|
||||
[generator.string({ length: 32, alpha: true, numeric: true })]: generator.word(),
|
||||
},
|
||||
password: generator.word(),
|
||||
status: "active",
|
||||
forceResetPassword: generator.bool(),
|
||||
builder: {
|
||||
global: generator.bool()
|
||||
},
|
||||
admin: {
|
||||
global: generator.bool()
|
||||
},
|
||||
...overrides
|
||||
})
|
||||
|
||||
export default generate
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"email": "test@budibase.com",
|
||||
"roles": {
|
||||
"sed_6d7": "sit ea amet",
|
||||
"cupidatat_e16": "fugiat proident sed"
|
||||
},
|
||||
"password": "cupidatat Lorem ad",
|
||||
"status": "active",
|
||||
"firstName": "QA",
|
||||
"lastName": "Updated",
|
||||
"forceResetPassword": true,
|
||||
"builder": {
|
||||
"global": true
|
||||
},
|
||||
"admin": {
|
||||
"global": false
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"email": "test@budibase.com",
|
||||
"roles": {
|
||||
"sed_6d7": "sit ea amet",
|
||||
"cupidatat_e16": "fugiat proident sed"
|
||||
},
|
||||
"password": "cupidatat Lorem ad",
|
||||
"status": "active",
|
||||
"firstName": "QA",
|
||||
"lastName": "Test",
|
||||
"forceResetPassword": true,
|
||||
"builder": {
|
||||
"global": true
|
||||
},
|
||||
"admin": {
|
||||
"global": false
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
import TestConfiguration from "../TestConfiguration"
|
||||
import PublicAPIClient from "../PublicAPIClient"
|
||||
|
||||
describe("Public API - /users endpoints", () => {
|
||||
const api = new PublicAPIClient()
|
||||
const config = new TestConfiguration()
|
||||
|
||||
beforeAll(async () => {
|
||||
await config.beforeAll()
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
await config.afterAll()
|
||||
})
|
||||
|
||||
it("POST - Create a user", async () => {
|
||||
const response = await api.post(`/users`, {
|
||||
body: require("./fixtures/user.json")
|
||||
})
|
||||
const json = await response.json()
|
||||
config.testContext.user = json.data
|
||||
expect(response).toHaveStatusCode(200)
|
||||
})
|
||||
|
||||
it("POST - Search users", async () => {
|
||||
const response = await api.post(`/users/search`, {
|
||||
body: {
|
||||
name: config.testContext.user.email
|
||||
}
|
||||
})
|
||||
expect(response).toHaveStatusCode(200)
|
||||
})
|
||||
|
||||
it("GET - Retrieve a user", async () => {
|
||||
const response = await api.get(`/users/${config.testContext.user._id}`)
|
||||
expect(response).toHaveStatusCode(200)
|
||||
})
|
||||
|
||||
|
||||
it("PUT - update a user", async () => {
|
||||
const response = await api.put(`/users/${config.testContext.user._id}`, {
|
||||
body: require("./fixtures/update_user.json")
|
||||
})
|
||||
expect(response).toHaveStatusCode(200)
|
||||
})
|
||||
})
|
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"lib": ["es2020"],
|
||||
"allowJs": true,
|
||||
"strict": true,
|
||||
"noImplicitAny": true,
|
||||
"esModuleInterop": true,
|
||||
"resolveJsonModule": true,
|
||||
"incremental": true,
|
||||
"types": ["node", "jest"],
|
||||
"outDir": "dist",
|
||||
"skipLibCheck": true,
|
||||
"paths": {
|
||||
"@budibase/types": ["../packages/types/src"],
|
||||
"@budibase/backend-core": ["../packages/backend-core/src"],
|
||||
"@budibase/backend-core/*": ["../packages/backend-core/*"]
|
||||
}
|
||||
},
|
||||
"ts-node": {
|
||||
"require": ["tsconfig-paths/register"]
|
||||
},
|
||||
"references": [
|
||||
{ "path": "../packages/types" },
|
||||
{ "path": "../packages/backend-core" },
|
||||
],
|
||||
"include": [
|
||||
"src/**/*",
|
||||
"package.json"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist"
|
||||
]
|
||||
}
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue