Merge branch 'master' of github.com:Budibase/budibase

This commit is contained in:
mike12345567 2023-11-20 15:59:31 +00:00
commit a2adc5eff4
41 changed files with 773 additions and 612 deletions

View File

@ -1,13 +1,11 @@
node_modules
dist
*.spec.js
packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte
packages/server/builder
packages/server/coverage
packages/worker/coverage
packages/backend-core/coverage
packages/server/client
packages/server/src/definitions/openapi.ts
packages/worker/coverage
packages/backend-core/coverage
packages/builder/.routify
packages/sdk/sdk
packages/pro/coverage

View File

@ -5,7 +5,6 @@ const { getDB } = require("../db")
describe("db", () => {
describe("getDB", () => {
it("returns a db", async () => {
const dbName = structures.db.id()
const db = getDB(dbName)
expect(db).toBeDefined()

View File

@ -75,10 +75,12 @@ export function getRedisConnectionDetails() {
}
const [host, port] = url.split(":")
const portNumber = parseInt(port)
return {
host,
password,
port: parseInt(port),
// assume default port for redis if invalid found
port: isNaN(portNumber) ? 6379 : portNumber,
}
}

View File

@ -1,5 +1,5 @@
const _ = require('lodash/fp')
const {structures} = require("../../../tests")
const _ = require("lodash/fp")
const { structures } = require("../../../tests")
jest.mock("../../../src/context")
jest.mock("../../../src/db")
@ -7,10 +7,9 @@ jest.mock("../../../src/db")
const context = require("../../../src/context")
const db = require("../../../src/db")
const {getCreatorCount} = require('../../../src/users/users')
const { getCreatorCount } = require("../../../src/users/users")
describe("Users", () => {
let getGlobalDBMock
let getGlobalUserParamsMock
let paginationMock
@ -26,26 +25,26 @@ describe("Users", () => {
it("Retrieves the number of creators", async () => {
const getUsers = (offset, limit, creators = false) => {
const range = _.range(offset, limit)
const opts = creators ? {builder: {global: true}} : undefined
const opts = creators ? { builder: { global: true } } : undefined
return range.map(() => structures.users.user(opts))
}
const page1Data = getUsers(0, 8)
const page2Data = getUsers(8, 12, true)
getGlobalDBMock.mockImplementation(() => ({
name : "fake-db",
name: "fake-db",
allDocs: () => ({
rows: [...page1Data, ...page2Data]
})
rows: [...page1Data, ...page2Data],
}),
}))
paginationMock.mockImplementationOnce(() => ({
data: page1Data,
hasNextPage: true,
nextPage: "1"
nextPage: "1",
}))
paginationMock.mockImplementation(() => ({
data: page2Data,
hasNextPage: false,
nextPage: undefined
nextPage: undefined,
}))
const creatorsCount = await getCreatorCount()
expect(creatorsCount).toBe(4)

View File

@ -1,8 +1,8 @@
const { Curl } = require("../../curl")
const fs = require("fs")
const path = require('path')
const path = require("path")
const getData = (file) => {
const getData = file => {
return fs.readFileSync(path.join(__dirname, `./data/${file}.txt`), "utf8")
}
@ -28,7 +28,7 @@ describe("Curl Import", () => {
expect(supported).toBe(false)
})
const init = async (file) => {
const init = async file => {
await curl.isSupported(getData(file))
}
@ -39,8 +39,7 @@ describe("Curl Import", () => {
})
describe("Returns queries", () => {
const getQueries = async (file) => {
const getQueries = async file => {
await init(file)
const queries = await curl.getQueries()
expect(queries.length).toBe(1)
@ -66,8 +65,8 @@ describe("Curl Import", () => {
}
it("populates path", async () => {
await testPath("get", "http://example.com/")
await testPath("path", "http://example.com/paths/abc")
await testPath("get", "http://example.com/")
await testPath("path", "http://example.com/paths/abc")
})
const testHeaders = async (file, headers) => {
@ -77,7 +76,10 @@ describe("Curl Import", () => {
it("populates headers", async () => {
await testHeaders("get", {})
await testHeaders("headers", { "x-bb-header-1" : "123", "x-bb-header-2" : "456"} )
await testHeaders("headers", {
"x-bb-header-1": "123",
"x-bb-header-2": "456",
})
})
const testQuery = async (file, queryString) => {
@ -91,12 +93,14 @@ describe("Curl Import", () => {
const testBody = async (file, body) => {
const queries = await getQueries(file)
expect(queries[0].fields.requestBody).toStrictEqual(JSON.stringify(body, null, 2))
expect(queries[0].fields.requestBody).toStrictEqual(
JSON.stringify(body, null, 2)
)
}
it("populates body", async () => {
await testBody("get", undefined)
await testBody("post", { "key" : "val" })
await testBody("post", { key: "val" })
await testBody("empty-body", {})
})
})

View File

@ -1,9 +1,12 @@
const { OpenAPI2 } = require("../../openapi2")
const fs = require("fs")
const path = require('path')
const path = require("path")
const getData = (file, extension) => {
return fs.readFileSync(path.join(__dirname, `./data/${file}/${file}.${extension}`), "utf8")
return fs.readFileSync(
path.join(__dirname, `./data/${file}/${file}.${extension}`),
"utf8"
)
}
describe("OpenAPI2 Import", () => {
@ -49,7 +52,7 @@ describe("OpenAPI2 Import", () => {
})
describe("Returns queries", () => {
const indexQueries = (queries) => {
const indexQueries = queries => {
return queries.reduce((acc, query) => {
acc[query.name] = query
return acc
@ -72,12 +75,12 @@ describe("OpenAPI2 Import", () => {
it("populates verb", async () => {
const assertions = {
"createEntity" : "create",
"getEntities" : "read",
"getEntity" : "read",
"updateEntity" : "update",
"patchEntity" : "patch",
"deleteEntity" : "delete"
createEntity: "create",
getEntities: "read",
getEntity: "read",
updateEntity: "update",
patchEntity: "patch",
deleteEntity: "delete",
}
await runTests("crud", testVerb, assertions)
})
@ -91,12 +94,12 @@ describe("OpenAPI2 Import", () => {
it("populates path", async () => {
const assertions = {
"createEntity" : "http://example.com/entities",
"getEntities" : "http://example.com/entities",
"getEntity" : "http://example.com/entities/{{entityId}}",
"updateEntity" : "http://example.com/entities/{{entityId}}",
"patchEntity" : "http://example.com/entities/{{entityId}}",
"deleteEntity" : "http://example.com/entities/{{entityId}}"
createEntity: "http://example.com/entities",
getEntities: "http://example.com/entities",
getEntity: "http://example.com/entities/{{entityId}}",
updateEntity: "http://example.com/entities/{{entityId}}",
patchEntity: "http://example.com/entities/{{entityId}}",
deleteEntity: "http://example.com/entities/{{entityId}}",
}
await runTests("crud", testPath, assertions)
})
@ -109,27 +112,25 @@ describe("OpenAPI2 Import", () => {
}
const contentTypeHeader = {
"Content-Type" : "application/json",
"Content-Type": "application/json",
}
it("populates headers", async () => {
const assertions = {
"createEntity" : {
...contentTypeHeader
createEntity: {
...contentTypeHeader,
},
"getEntities" : {
getEntities: {},
getEntity: {},
updateEntity: {
...contentTypeHeader,
},
"getEntity" : {
patchEntity: {
...contentTypeHeader,
},
"updateEntity" : {
...contentTypeHeader
deleteEntity: {
"x-api-key": "{{x-api-key}}",
},
"patchEntity" : {
...contentTypeHeader
},
"deleteEntity" : {
"x-api-key" : "{{x-api-key}}",
}
}
await runTests("crud", testHeaders, assertions)
@ -138,18 +139,20 @@ describe("OpenAPI2 Import", () => {
const testQuery = async (file, extension, assertions) => {
const queries = await getQueries(file, extension)
for (let [operationId, queryString] of Object.entries(assertions)) {
expect(queries[operationId].fields.queryString).toStrictEqual(queryString)
expect(queries[operationId].fields.queryString).toStrictEqual(
queryString
)
}
}
it("populates query", async () => {
const assertions = {
"createEntity" : "",
"getEntities" : "page={{page}}&size={{size}}",
"getEntity" : "",
"updateEntity" : "",
"patchEntity" : "",
"deleteEntity" : ""
createEntity: "",
getEntities: "page={{page}}&size={{size}}",
getEntity: "",
updateEntity: "",
patchEntity: "",
deleteEntity: "",
}
await runTests("crud", testQuery, assertions)
})
@ -163,45 +166,45 @@ describe("OpenAPI2 Import", () => {
it("populates parameters", async () => {
const assertions = {
"createEntity" : [],
"getEntities" : [
createEntity: [],
getEntities: [
{
"name" : "page",
"default" : "",
name: "page",
default: "",
},
{
"name" : "size",
"default" : "",
}
name: "size",
default: "",
},
],
"getEntity" : [
getEntity: [
{
"name" : "entityId",
"default" : "",
}
name: "entityId",
default: "",
},
],
"updateEntity" : [
updateEntity: [
{
"name" : "entityId",
"default" : "",
}
name: "entityId",
default: "",
},
],
"patchEntity" : [
patchEntity: [
{
"name" : "entityId",
"default" : "",
}
name: "entityId",
default: "",
},
],
"deleteEntity" : [
deleteEntity: [
{
"name" : "entityId",
"default" : "",
name: "entityId",
default: "",
},
{
"name" : "x-api-key",
"default" : "",
}
]
name: "x-api-key",
default: "",
},
],
}
await runTests("crud", testParameters, assertions)
})
@ -209,28 +212,30 @@ describe("OpenAPI2 Import", () => {
const testBody = async (file, extension, assertions) => {
const queries = await getQueries(file, extension)
for (let [operationId, body] of Object.entries(assertions)) {
expect(queries[operationId].fields.requestBody).toStrictEqual(JSON.stringify(body, null, 2))
expect(queries[operationId].fields.requestBody).toStrictEqual(
JSON.stringify(body, null, 2)
)
}
}
it("populates body", async () => {
const assertions = {
"createEntity" : {
"name" : "name",
"type" : "type",
createEntity: {
name: "name",
type: "type",
},
"getEntities" : undefined,
"getEntity" : undefined,
"updateEntity" : {
"id": 1,
"name" : "name",
"type" : "type",
getEntities: undefined,
getEntity: undefined,
updateEntity: {
id: 1,
name: "name",
type: "type",
},
"patchEntity" : {
"id": 1,
"name" : "name",
"type" : "type",
patchEntity: {
id: 1,
name: "name",
type: "type",
},
"deleteEntity" : undefined
deleteEntity: undefined,
}
await runTests("crud", testBody, assertions)
})

View File

@ -1,11 +1,14 @@
const TestConfig = require("../../../../../tests/utilities/TestConfiguration")
const { RestImporter } = require("../index")
const fs = require("fs")
const path = require('path')
const { events} = require("@budibase/backend-core")
const path = require("path")
const { events } = require("@budibase/backend-core")
const getData = (file) => {
return fs.readFileSync(path.join(__dirname, `../sources/tests/${file}`), "utf8")
const getData = file => {
return fs.readFileSync(
path.join(__dirname, `../sources/tests/${file}`),
"utf8"
)
}
// openapi2 (swagger)
@ -35,7 +38,7 @@ const datasets = {
oapi3PetstoreJson,
oapi3PetstoreYaml,
// curl
curl
curl,
}
describe("Rest Importer", () => {
@ -47,7 +50,7 @@ describe("Rest Importer", () => {
let restImporter
const init = async (data) => {
const init = async data => {
restImporter = new RestImporter(data)
await restImporter.init()
}
@ -69,35 +72,35 @@ describe("Rest Importer", () => {
it("gets info", async () => {
const assertions = {
// openapi2 (swagger)
"oapi2CrudJson" : {
oapi2CrudJson: {
name: "CRUD",
},
"oapi2CrudYaml" : {
oapi2CrudYaml: {
name: "CRUD",
},
"oapi2PetstoreJson" : {
oapi2PetstoreJson: {
name: "Swagger Petstore",
},
"oapi2PetstoreYaml" :{
oapi2PetstoreYaml: {
name: "Swagger Petstore",
},
// openapi3
"oapi3CrudJson" : {
oapi3CrudJson: {
name: "CRUD",
},
"oapi3CrudYaml" : {
oapi3CrudYaml: {
name: "CRUD",
},
"oapi3PetstoreJson" : {
oapi3PetstoreJson: {
name: "Swagger Petstore - OpenAPI 3.0",
},
"oapi3PetstoreYaml" :{
oapi3PetstoreYaml: {
name: "Swagger Petstore - OpenAPI 3.0",
},
// curl
"curl": {
curl: {
name: "example.com",
}
},
}
await runTest(testGetInfo, assertions)
})
@ -109,7 +112,11 @@ describe("Rest Importer", () => {
expect(importResult.errorQueries.length).toBe(0)
expect(importResult.queries.length).toBe(assertions[key].count)
expect(events.query.imported).toBeCalledTimes(1)
expect(events.query.imported).toBeCalledWith(datasource, assertions[key].source, assertions[key].count)
expect(events.query.imported).toBeCalledWith(
datasource,
assertions[key].source,
assertions[key].count
)
jest.clearAllMocks()
}
@ -118,44 +125,44 @@ describe("Rest Importer", () => {
// makes it through the importer
const assertions = {
// openapi2 (swagger)
"oapi2CrudJson" : {
oapi2CrudJson: {
count: 6,
source: "openapi2.0",
},
"oapi2CrudYaml" :{
oapi2CrudYaml: {
count: 6,
source: "openapi2.0"
source: "openapi2.0",
},
"oapi2PetstoreJson" : {
oapi2PetstoreJson: {
count: 20,
source: "openapi2.0"
source: "openapi2.0",
},
"oapi2PetstoreYaml" :{
oapi2PetstoreYaml: {
count: 20,
source: "openapi2.0"
source: "openapi2.0",
},
// openapi3
"oapi3CrudJson" : {
oapi3CrudJson: {
count: 6,
source: "openapi3.0"
source: "openapi3.0",
},
"oapi3CrudYaml" :{
oapi3CrudYaml: {
count: 6,
source: "openapi3.0"
source: "openapi3.0",
},
"oapi3PetstoreJson" : {
oapi3PetstoreJson: {
count: 19,
source: "openapi3.0"
source: "openapi3.0",
},
"oapi3PetstoreYaml" :{
oapi3PetstoreYaml: {
count: 19,
source: "openapi3.0"
source: "openapi3.0",
},
// curl
"curl": {
curl: {
count: 1,
source: "curl"
}
source: "curl",
},
}
await runTest(testImportQueries, assertions)
})

View File

@ -1,65 +1,75 @@
const viewTemplate = require("../viewBuilder").default;
const viewTemplate = require("../viewBuilder").default
describe("viewBuilder", () => {
describe("Filter", () => {
it("creates a view with multiple filters and conjunctions", () => {
expect(viewTemplate({
"name": "Test View",
"tableId": "14f1c4e94d6a47b682ce89d35d4c78b0",
"filters": [{
"value": "Test",
"condition": "EQUALS",
"key": "Name"
}, {
"value": "Value",
"condition": "MT",
"key": "Yes",
"conjunction": "OR"
}]
})).toMatchSnapshot()
expect(
viewTemplate({
name: "Test View",
tableId: "14f1c4e94d6a47b682ce89d35d4c78b0",
filters: [
{
value: "Test",
condition: "EQUALS",
key: "Name",
},
{
value: "Value",
condition: "MT",
key: "Yes",
conjunction: "OR",
},
],
})
).toMatchSnapshot()
})
})
describe("Calculate", () => {
it("creates a view with the calculation statistics schema", () => {
expect(viewTemplate({
"name": "Calculate View",
"field": "myField",
"calculation": "stats",
"tableId": "14f1c4e94d6a47b682ce89d35d4c78b0",
"filters": []
})).toMatchSnapshot()
expect(
viewTemplate({
name: "Calculate View",
field: "myField",
calculation: "stats",
tableId: "14f1c4e94d6a47b682ce89d35d4c78b0",
filters: [],
})
).toMatchSnapshot()
})
})
describe("Group By", () => {
it("creates a view emitting the group by field", () => {
expect(viewTemplate({
"name": "Test Scores Grouped By Age",
"tableId": "14f1c4e94d6a47b682ce89d35d4c78b0",
"groupBy": "age",
"field": "score",
"filters": [],
})).toMatchSnapshot()
expect(
viewTemplate({
name: "Test Scores Grouped By Age",
tableId: "14f1c4e94d6a47b682ce89d35d4c78b0",
groupBy: "age",
field: "score",
filters: [],
})
).toMatchSnapshot()
})
})
describe("Calculate and filter", () => {
it("creates a view with the calculation statistics and filter schema", () => {
expect(viewTemplate({
"name": "Calculate View",
"field": "myField",
"calculation": "stats",
"tableId": "14f1c4e94d6a47b682ce89d35d4c78b0",
"filters": [
{
"value": 17,
"condition": "MT",
"key": "age",
}
]
})).toMatchSnapshot()
expect(
viewTemplate({
name: "Calculate View",
field: "myField",
calculation: "stats",
tableId: "14f1c4e94d6a47b682ce89d35d4c78b0",
filters: [
{
value: 17,
condition: "MT",
key: "age",
},
],
})
).toMatchSnapshot()
})
})
});
})

View File

@ -25,10 +25,9 @@ describe("/metrics", () => {
it("endpoint should not be publicly exposed", async () => {
await request
.get(`/api/public/v1/metrics`)
.set(config.publicHeaders())
.expect(403)
.get(`/api/public/v1/metrics`)
.set(config.publicHeaders())
.expect(403)
})
})
})

View File

@ -14,7 +14,7 @@ describe("/static", () => {
app = await config.init()
})
beforeEach(()=>{
beforeEach(() => {
jest.clearAllMocks()
})
@ -22,7 +22,7 @@ describe("/static", () => {
it("should ping from builder", async () => {
await request
.post("/api/bbtel/ping")
.send({source: "builder", timezone})
.send({ source: "builder", timezone })
.set(config.defaultHeaders())
.expect(200)
@ -35,12 +35,15 @@ describe("/static", () => {
it("should ping from app preview", async () => {
await request
.post("/api/bbtel/ping")
.send({source: "app", timezone})
.send({ source: "app", timezone })
.set(config.defaultHeaders())
.expect(200)
expect(events.serve.servedAppPreview).toBeCalledTimes(1)
expect(events.serve.servedAppPreview).toBeCalledWith(config.getApp(), timezone)
expect(events.serve.servedAppPreview).toBeCalledWith(
config.getApp(),
timezone
)
expect(events.serve.servedApp).not.toBeCalled()
})
@ -50,12 +53,16 @@ describe("/static", () => {
await request
.post("/api/bbtel/ping")
.send({source: "app", timezone})
.send({ source: "app", timezone })
.set(headers)
.expect(200)
expect(events.serve.servedApp).toBeCalledTimes(1)
expect(events.serve.servedApp).toBeCalledWith(config.getProdApp(), timezone, undefined)
expect(events.serve.servedApp).toBeCalledWith(
config.getProdApp(),
timezone,
undefined
)
expect(events.serve.servedAppPreview).not.toBeCalled()
})
@ -65,12 +72,16 @@ describe("/static", () => {
await request
.post("/api/bbtel/ping")
.send({source: "app", timezone, embedded: true})
.send({ source: "app", timezone, embedded: true })
.set(headers)
.expect(200)
expect(events.serve.servedApp).toBeCalledTimes(1)
expect(events.serve.servedApp).toBeCalledWith(config.getProdApp(), timezone, true)
expect(events.serve.servedApp).toBeCalledWith(
config.getProdApp(),
timezone,
true
)
expect(events.serve.servedAppPreview).not.toBeCalled()
})
})

View File

@ -38,7 +38,7 @@ describe("/api/keys", () => {
const res = await request
.put(`/api/keys/TEST`)
.send({
value: "test"
value: "test",
})
.set(config.defaultHeaders())
.expect("Content-Type", /json/)

View File

@ -1,7 +1,6 @@
const setup = require("./utilities")
const { events } = require("@budibase/backend-core")
describe("/dev", () => {
let request = setup.getRequest()
let config = setup.getConfig()
@ -32,9 +31,9 @@ describe("/dev", () => {
.expect("Content-Type", /json/)
.expect(200)
expect(res.body.version).toBe('0.0.0+jest')
expect(res.body.version).toBe("0.0.0+jest")
expect(events.installation.versionChecked).toBeCalledTimes(1)
expect(events.installation.versionChecked).toBeCalledWith('0.0.0+jest')
expect(events.installation.versionChecked).toBeCalledWith("0.0.0+jest")
})
})
})

View File

@ -14,7 +14,10 @@ describe("/metadata", () => {
automation = await config.createAutomation()
})
async function createMetadata(data, type = MetadataTypes.AUTOMATION_TEST_INPUT) {
async function createMetadata(
data,
type = MetadataTypes.AUTOMATION_TEST_INPUT
) {
const res = await request
.post(`/api/metadata/${type}/${automation._id}`)
.send(data)
@ -53,7 +56,9 @@ describe("/metadata", () => {
describe("destroy", () => {
it("should be able to delete some test inputs", async () => {
const res = await request
.delete(`/api/metadata/${MetadataTypes.AUTOMATION_TEST_INPUT}/${automation._id}`)
.delete(
`/api/metadata/${MetadataTypes.AUTOMATION_TEST_INPUT}/${automation._id}`
)
.set(config.defaultHeaders())
.expect("Content-Type", /json/)
.expect(200)

View File

@ -1,4 +1,4 @@
const tk = require( "timekeeper")
const tk = require("timekeeper")
tk.freeze(Date.now())
// Mock out postgres for this
@ -14,7 +14,7 @@ jest.mock("@budibase/backend-core", () => {
db: {
...core.db,
isProdAppID: jest.fn(),
}
},
}
})
const setup = require("./utilities")
@ -30,8 +30,7 @@ describe("/queries", () => {
afterAll(setup.afterAll)
const setupTest = async()=>{
const setupTest = async () => {
await config.init()
datasource = await config.createDatasource()
query = await config.createQuery()
@ -52,7 +51,7 @@ describe("/queries", () => {
return { datasource, query }
}
const createQuery = async (query) => {
const createQuery = async query => {
return request
.post(`/api/queries`)
.send(query)
@ -76,7 +75,7 @@ describe("/queries", () => {
_id: res.body._id,
...query,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
updatedAt: new Date().toISOString(),
})
expect(events.query.created).toBeCalledTimes(1)
expect(events.query.updated).not.toBeCalled()
@ -101,7 +100,7 @@ describe("/queries", () => {
_id: res.body._id,
...query,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString()
updatedAt: new Date().toISOString(),
})
expect(events.query.created).not.toBeCalled()
expect(events.query.updated).toBeCalledTimes(1)
@ -109,7 +108,7 @@ describe("/queries", () => {
})
describe("fetch", () => {
beforeEach(async() => {
beforeEach(async () => {
await setupTest()
})
@ -190,7 +189,7 @@ describe("/queries", () => {
})
describe("destroy", () => {
beforeEach(async() => {
beforeEach(async () => {
await setupTest()
})
@ -237,8 +236,8 @@ describe("/queries", () => {
.expect(200)
// these responses come from the mock
expect(res.body.schemaFields).toEqual({
"a": "string",
"b": "number",
a: "string",
b: "number",
})
expect(res.body.rows.length).toEqual(1)
expect(events.query.previewed).toBeCalledTimes(1)
@ -256,7 +255,7 @@ describe("/queries", () => {
})
describe("execute", () => {
beforeEach(async() => {
beforeEach(async () => {
await setupTest()
})
@ -302,9 +301,9 @@ describe("/queries", () => {
})
// these responses come from the mock
expect(res.body.schemaFields).toEqual({
"opts": "json",
"url": "string",
"value": "string",
opts: "json",
url: "string",
value: "string",
})
expect(res.body.rows[0].url).toEqual("http://www.google.com?test=1")
})
@ -316,9 +315,9 @@ describe("/queries", () => {
queryString: "test={{ variable3 }}",
})
expect(res.body.schemaFields).toEqual({
"opts": "json",
"url": "string",
"value": "string"
opts: "json",
url: "string",
value: "string",
})
expect(res.body.rows[0].url).toContain("doctype%20html")
})
@ -339,9 +338,9 @@ describe("/queries", () => {
queryString: "test={{ variable3 }}",
})
expect(res.body.schemaFields).toEqual({
"fails": "number",
"opts": "json",
"url": "string"
fails: "number",
opts: "json",
url: "string",
})
expect(res.body.rows[0].fails).toEqual(1)
})
@ -371,13 +370,19 @@ describe("/queries", () => {
})
describe("Current User Request Mapping", () => {
async function previewGet(datasource, fields, params) {
return config.previewQuery(request, config, datasource, fields, params)
}
async function previewPost(datasource, fields, params) {
return config.previewQuery(request, config, datasource, fields, params, "create")
return config.previewQuery(
request,
config,
datasource,
fields,
params,
"create"
)
}
it("should parse global and query level header mappings", async () => {
@ -385,27 +390,29 @@ describe("/queries", () => {
const datasource = await config.restDatasource({
defaultHeaders: {
"test": "headerVal",
"emailHdr": "{{[user].[email]}}"
}
test: "headerVal",
emailHdr: "{{[user].[email]}}",
},
})
const res = await previewGet(datasource, {
path: "www.google.com",
queryString: "email={{[user].[email]}}",
headers: {
queryHdr : "{{[user].[firstName]}}",
secondHdr : "1234"
}
queryHdr: "{{[user].[firstName]}}",
secondHdr: "1234",
},
})
const parsedRequest = JSON.parse(res.body.extra.raw)
expect(parsedRequest.opts.headers).toEqual({
"test": "headerVal",
"emailHdr": userDetails.email,
"queryHdr": userDetails.firstName,
"secondHdr" : "1234"
test: "headerVal",
emailHdr: userDetails.email,
queryHdr: userDetails.firstName,
secondHdr: "1234",
})
expect(res.body.rows[0].url).toEqual("http://www.google.com?email=" + userDetails.email.replace("@", "%40"))
expect(res.body.rows[0].url).toEqual(
"http://www.google.com?email=" + userDetails.email.replace("@", "%40")
)
})
it("should bind the current user to query parameters", async () => {
@ -413,92 +420,130 @@ describe("/queries", () => {
const datasource = await config.restDatasource()
const res = await previewGet(datasource, {
path: "www.google.com",
queryString: "test={{myEmail}}&testName={{myName}}&testParam={{testParam}}",
}, {
"myEmail" : "{{[user].[email]}}",
"myName" : "{{[user].[firstName]}}",
"testParam" : "1234"
})
const res = await previewGet(
datasource,
{
path: "www.google.com",
queryString:
"test={{myEmail}}&testName={{myName}}&testParam={{testParam}}",
},
{
myEmail: "{{[user].[email]}}",
myName: "{{[user].[firstName]}}",
testParam: "1234",
}
)
expect(res.body.rows[0].url).toEqual("http://www.google.com?test=" + userDetails.email.replace("@", "%40") +
"&testName=" + userDetails.firstName + "&testParam=1234")
expect(res.body.rows[0].url).toEqual(
"http://www.google.com?test=" +
userDetails.email.replace("@", "%40") +
"&testName=" +
userDetails.firstName +
"&testParam=1234"
)
})
it("should bind the current user the request body - plain text", async () => {
const userDetails = config.getUserDetails()
const datasource = await config.restDatasource()
const res = await previewPost(datasource, {
path: "www.google.com",
queryString: "testParam={{testParam}}",
requestBody: "This is plain text and this is my email: {{[user].[email]}}. This is a test param: {{testParam}}",
bodyType: "text"
}, {
"testParam" : "1234"
})
const res = await previewPost(
datasource,
{
path: "www.google.com",
queryString: "testParam={{testParam}}",
requestBody:
"This is plain text and this is my email: {{[user].[email]}}. This is a test param: {{testParam}}",
bodyType: "text",
},
{
testParam: "1234",
}
)
const parsedRequest = JSON.parse(res.body.extra.raw)
expect(parsedRequest.opts.body).toEqual(`This is plain text and this is my email: ${userDetails.email}. This is a test param: 1234`)
expect(res.body.rows[0].url).toEqual("http://www.google.com?testParam=1234")
expect(parsedRequest.opts.body).toEqual(
`This is plain text and this is my email: ${userDetails.email}. This is a test param: 1234`
)
expect(res.body.rows[0].url).toEqual(
"http://www.google.com?testParam=1234"
)
})
it("should bind the current user the request body - json", async () => {
const userDetails = config.getUserDetails()
const datasource = await config.restDatasource()
const res = await previewPost(datasource, {
path: "www.google.com",
queryString: "testParam={{testParam}}",
requestBody: "{\"email\":\"{{[user].[email]}}\",\"queryCode\":{{testParam}},\"userRef\":\"{{userRef}}\"}",
bodyType: "json"
}, {
"testParam" : "1234",
"userRef" : "{{[user].[firstName]}}"
})
const res = await previewPost(
datasource,
{
path: "www.google.com",
queryString: "testParam={{testParam}}",
requestBody:
'{"email":"{{[user].[email]}}","queryCode":{{testParam}},"userRef":"{{userRef}}"}',
bodyType: "json",
},
{
testParam: "1234",
userRef: "{{[user].[firstName]}}",
}
)
const parsedRequest = JSON.parse(res.body.extra.raw)
const test = `{"email":"${userDetails.email}","queryCode":1234,"userRef":"${userDetails.firstName}"}`
expect(parsedRequest.opts.body).toEqual(test)
expect(res.body.rows[0].url).toEqual("http://www.google.com?testParam=1234")
expect(res.body.rows[0].url).toEqual(
"http://www.google.com?testParam=1234"
)
})
it("should bind the current user the request body - xml", async () => {
const userDetails = config.getUserDetails()
const datasource = await config.restDatasource()
const res = await previewPost(datasource, {
path: "www.google.com",
queryString: "testParam={{testParam}}",
requestBody: "<note> <email>{{[user].[email]}}</email> <code>{{testParam}}</code> " +
"<ref>{{userId}}</ref> <somestring>testing</somestring> </note>",
bodyType: "xml"
}, {
"testParam" : "1234",
"userId" : "{{[user].[firstName]}}"
})
const res = await previewPost(
datasource,
{
path: "www.google.com",
queryString: "testParam={{testParam}}",
requestBody:
"<note> <email>{{[user].[email]}}</email> <code>{{testParam}}</code> " +
"<ref>{{userId}}</ref> <somestring>testing</somestring> </note>",
bodyType: "xml",
},
{
testParam: "1234",
userId: "{{[user].[firstName]}}",
}
)
const parsedRequest = JSON.parse(res.body.extra.raw)
const test = `<note> <email>${userDetails.email}</email> <code>1234</code> <ref>${userDetails.firstName}</ref> <somestring>testing</somestring> </note>`
expect(parsedRequest.opts.body).toEqual(test)
expect(res.body.rows[0].url).toEqual("http://www.google.com?testParam=1234")
expect(res.body.rows[0].url).toEqual(
"http://www.google.com?testParam=1234"
)
})
it("should bind the current user the request body - form-data", async () => {
const userDetails = config.getUserDetails()
const datasource = await config.restDatasource()
const res = await previewPost(datasource, {
path: "www.google.com",
queryString: "testParam={{testParam}}",
requestBody: "{\"email\":\"{{[user].[email]}}\",\"queryCode\":{{testParam}},\"userRef\":\"{{userRef}}\"}",
bodyType: "form"
}, {
"testParam" : "1234",
"userRef" : "{{[user].[firstName]}}"
})
const res = await previewPost(
datasource,
{
path: "www.google.com",
queryString: "testParam={{testParam}}",
requestBody:
'{"email":"{{[user].[email]}}","queryCode":{{testParam}},"userRef":"{{userRef}}"}',
bodyType: "form",
},
{
testParam: "1234",
userRef: "{{[user].[firstName]}}",
}
)
const parsedRequest = JSON.parse(res.body.extra.raw)
@ -511,28 +556,34 @@ describe("/queries", () => {
const userRef = parsedRequest.opts.body._streams[7]
expect(userRef).toEqual(userDetails.firstName)
expect(res.body.rows[0].url).toEqual("http://www.google.com?testParam=1234")
expect(res.body.rows[0].url).toEqual(
"http://www.google.com?testParam=1234"
)
})
it("should bind the current user the request body - encoded", async () => {
const userDetails = config.getUserDetails()
const datasource = await config.restDatasource()
const res = await previewPost(datasource, {
path: "www.google.com",
queryString: "testParam={{testParam}}",
requestBody: "{\"email\":\"{{[user].[email]}}\",\"queryCode\":{{testParam}},\"userRef\":\"{{userRef}}\"}",
bodyType: "encoded"
}, {
"testParam" : "1234",
"userRef" : "{{[user].[firstName]}}"
})
const res = await previewPost(
datasource,
{
path: "www.google.com",
queryString: "testParam={{testParam}}",
requestBody:
'{"email":"{{[user].[email]}}","queryCode":{{testParam}},"userRef":"{{userRef}}"}',
bodyType: "encoded",
},
{
testParam: "1234",
userRef: "{{[user].[firstName]}}",
}
)
const parsedRequest = JSON.parse(res.body.extra.raw)
expect(parsedRequest.opts.body.email).toEqual(userDetails.email)
expect(parsedRequest.opts.body.queryCode).toEqual("1234")
expect(parsedRequest.opts.body.userRef).toEqual(userDetails.firstName)
})
});
})
})

View File

@ -170,7 +170,7 @@ describe("/roles", () => {
.get("/api/roles/accessible")
.set({
...config.defaultHeaders(),
"x-budibase-role": "CUSTOM_ROLE"
"x-budibase-role": "CUSTOM_ROLE",
})
.expect(200)
expect(res.body.length).toBe(3)

View File

@ -37,19 +37,23 @@ describe("/routing", () => {
await runInProd(async () => {
return request
.get(`/api/routing/client`)
.set(await config.roleHeaders({
roleId: BUILTIN_ROLE_IDS.BASIC,
prodApp: false
}))
.set(
await config.roleHeaders({
roleId: BUILTIN_ROLE_IDS.BASIC,
prodApp: false,
})
)
.expect(302)
})
})
it("returns the correct routing for basic user", async () => {
const res = await request
.get(`/api/routing/client`)
.set(await config.roleHeaders({
roleId: BUILTIN_ROLE_IDS.BASIC
}))
.set(
await config.roleHeaders({
roleId: BUILTIN_ROLE_IDS.BASIC,
})
)
.expect("Content-Type", /json/)
.expect(200)
expect(res.body.routes).toBeDefined()
@ -57,18 +61,20 @@ describe("/routing", () => {
subpaths: {
[route]: {
screenId: basic._id,
roleId: basic.routing.roleId
}
}
roleId: basic.routing.roleId,
},
},
})
})
it("returns the correct routing for power user", async () => {
const res = await request
.get(`/api/routing/client`)
.set(await config.roleHeaders({
roleId: BUILTIN_ROLE_IDS.POWER
}))
.set(
await config.roleHeaders({
roleId: BUILTIN_ROLE_IDS.POWER,
})
)
.expect("Content-Type", /json/)
.expect(200)
expect(res.body.routes).toBeDefined()
@ -76,9 +82,9 @@ describe("/routing", () => {
subpaths: {
[route]: {
screenId: power._id,
roleId: power.routing.roleId
}
}
roleId: power.routing.roleId,
},
},
})
})
})
@ -87,10 +93,12 @@ describe("/routing", () => {
it("should fetch all routes for builder", async () => {
const res = await request
.get(`/api/routing`)
.set(await config.roleHeaders({
roleId: BUILTIN_ROLE_IDS.POWER,
builder: true,
}))
.set(
await config.roleHeaders({
roleId: BUILTIN_ROLE_IDS.POWER,
builder: true,
})
)
.expect(200)
.expect("Content-Type", /json/)
expect(res.body.routes).toBeDefined()

View File

@ -36,7 +36,7 @@ describe("/screens", () => {
})
describe("save", () => {
const saveScreen = async (screen) => {
const saveScreen = async screen => {
const res = await request
.post(`/api/screens`)
.send(screen)

View File

@ -32,17 +32,17 @@ describe("/views", () => {
await config.init()
})
beforeEach(async() => {
beforeEach(async () => {
table = await config.createTable(priceTable())
})
const saveView = async (view) => {
const saveView = async view => {
const viewToSave = {
name: "TestView",
field: "Price",
calculation: "stats",
tableId: table._id,
...view
...view,
}
return request
.post(`/api/views`)
@ -53,7 +53,6 @@ describe("/views", () => {
}
describe("create", () => {
it("returns a success message when the view is successfully created", async () => {
const res = await saveView()
expect(res.body.tableId).toBe(table._id)
@ -81,11 +80,13 @@ describe("/views", () => {
const res = await saveView({
calculation: null,
filters: [{
value: "1",
condition: "EQUALS",
key: "price"
}],
filters: [
{
value: "1",
condition: "EQUALS",
key: "price",
},
],
})
expect(res.body.tableId).toBe(table._id)
@ -199,18 +200,26 @@ describe("/views", () => {
})
it("updates a view filter", async () => {
await saveView({ filters: [{
value: "1",
condition: "EQUALS",
key: "price"
}] })
await saveView({
filters: [
{
value: "1",
condition: "EQUALS",
key: "price",
},
],
})
jest.clearAllMocks()
await saveView({ filters: [{
value: "2",
condition: "EQUALS",
key: "price"
}] })
await saveView({
filters: [
{
value: "2",
condition: "EQUALS",
key: "price",
},
],
})
expect(events.view.created).not.toBeCalled()
expect(events.view.updated).toBeCalledTimes(1)
@ -223,11 +232,15 @@ describe("/views", () => {
})
it("deletes a view filter", async () => {
await saveView({ filters: [{
value: "1",
condition: "EQUALS",
key: "price"
}] })
await saveView({
filters: [
{
value: "1",
condition: "EQUALS",
key: "price",
},
],
})
jest.clearAllMocks()
await saveView({ filters: [] })
@ -344,7 +357,6 @@ describe("/views", () => {
})
describe("exportView", () => {
beforeEach(() => {
jest.clearAllMocks()
})
@ -362,14 +374,14 @@ describe("/views", () => {
.expect(200)
}
const assertJsonExport = (res) => {
const assertJsonExport = res => {
const rows = JSON.parse(res.text)
expect(rows.length).toBe(1)
expect(rows[0].name).toBe("test-name")
expect(rows[0].description).toBe("ùúûü")
}
const assertCSVExport = (res) => {
const assertCSVExport = res => {
expect(res.text).toBe(`"name","description"\n"test-name","ùúûü"`)
}

View File

@ -1,34 +1,33 @@
const setup = require("./utilities")
describe("test the bash action", () => {
let config = setup.getConfig()
let config = setup.getConfig()
beforeAll(async () => {
await config.init()
})
afterAll(setup.afterAll)
beforeAll(async () => {
await config.init()
})
afterAll(setup.afterAll)
it("should be able to execute a script", async () => {
it("should be able to execute a script", async () => {
let res = await setup.runStep(
"EXECUTE_BASH",
(inputs = {
code: "echo 'test'",
})
)
expect(res.stdout).toEqual("test\n")
expect(res.success).toEqual(true)
})
let res = await setup.runStep("EXECUTE_BASH",
inputs = {
code: "echo 'test'"
}
)
expect(res.stdout).toEqual("test\n")
expect(res.success).toEqual(true)
})
it("should handle a null value", async () => {
let res = await setup.runStep("EXECUTE_BASH",
inputs = {
code: null
}
)
expect(res.stdout).toEqual("Budibase bash automation failed: Invalid inputs")
})
it("should handle a null value", async () => {
let res = await setup.runStep(
"EXECUTE_BASH",
(inputs = {
code: null,
})
)
expect(res.stdout).toEqual(
"Budibase bash automation failed: Invalid inputs"
)
})
})

View File

@ -1,7 +1,7 @@
const setup = require("./utilities")
// need real Date for this test
const tk = require('timekeeper');
const tk = require("timekeeper")
tk.reset()
describe("test the delay logic", () => {

View File

@ -4,24 +4,23 @@ const fetch = require("node-fetch")
jest.mock("node-fetch")
describe("test the outgoing webhook action", () => {
let inputs
let config = setup.getConfig()
let inputs
let config = setup.getConfig()
beforeAll(async () => {
await config.init()
inputs = {
username: "joe_bloggs",
url: "http://www.test.com",
}
})
beforeAll(async () => {
await config.init()
inputs = {
username: "joe_bloggs",
url: "http://www.test.com",
}
})
afterAll(setup.afterAll)
it("should be able to run the action", async () => {
const res = await setup.runStep(setup.actions.discord.stepId, inputs)
expect(res.response.url).toEqual("http://www.test.com")
expect(res.response.method).toEqual("post")
expect(res.success).toEqual(true)
})
afterAll(setup.afterAll)
it("should be able to run the action", async () => {
const res = await setup.runStep(setup.actions.discord.stepId, inputs)
expect(res.response.url).toEqual("http://www.test.com")
expect(res.response.method).toEqual("post")
expect(res.success).toEqual(true)
})
})

View File

@ -1,48 +1,47 @@
const setup = require("./utilities")
describe("test the execute query action", () => {
let config = setup.getConfig()
let config = setup.getConfig()
beforeAll(async () => {
await config.init()
beforeAll(async () => {
await config.init()
await config.createDatasource()
query = await config.createQuery()
await config.createDatasource()
query = await config.createQuery()
})
})
afterAll(setup.afterAll)
afterAll(setup.afterAll)
it("should be able to execute a query", async () => {
let res = await setup.runStep(setup.actions.EXECUTE_QUERY.stepId,
inputs = {
query: { queryId: query._id }
}
)
expect(res.response).toEqual([{ a: 'string', b: 1 }])
expect(res.success).toEqual(true)
})
it("should handle a null query value", async () => {
let res = await setup.runStep(setup.actions.EXECUTE_QUERY.stepId,
inputs = {
query: null
}
)
expect(res.response.message).toEqual("Invalid inputs")
expect(res.success).toEqual(false)
})
it("should handle an error executing a query", async () => {
let res = await setup.runStep(setup.actions.EXECUTE_QUERY.stepId,
inputs = {
query: { queryId: "wrong_id" }
}
)
expect(res.response).toEqual('Error: missing')
expect(res.success).toEqual(false)
})
it("should be able to execute a query", async () => {
let res = await setup.runStep(
setup.actions.EXECUTE_QUERY.stepId,
(inputs = {
query: { queryId: query._id },
})
)
expect(res.response).toEqual([{ a: "string", b: 1 }])
expect(res.success).toEqual(true)
})
it("should handle a null query value", async () => {
let res = await setup.runStep(
setup.actions.EXECUTE_QUERY.stepId,
(inputs = {
query: null,
})
)
expect(res.response.message).toEqual("Invalid inputs")
expect(res.success).toEqual(false)
})
it("should handle an error executing a query", async () => {
let res = await setup.runStep(
setup.actions.EXECUTE_QUERY.stepId,
(inputs = {
query: { queryId: "wrong_id" },
})
)
expect(res.response).toEqual("Error: missing")
expect(res.success).toEqual(false)
})
})

View File

@ -1,48 +1,43 @@
const setup = require("./utilities")
describe("test the execute script action", () => {
let config = setup.getConfig()
let config = setup.getConfig()
beforeAll(async () => {
await config.init()
})
afterAll(setup.afterAll)
beforeAll(async () => {
await config.init()
})
afterAll(setup.afterAll)
it("should be able to execute a script", async () => {
it("should be able to execute a script", async () => {
let res = await setup.runStep(
setup.actions.EXECUTE_SCRIPT.stepId,
(inputs = {
code: "return 1 + 1",
})
)
expect(res.value).toEqual(2)
expect(res.success).toEqual(true)
})
let res = await setup.runStep(setup.actions.EXECUTE_SCRIPT.stepId,
inputs = {
code: "return 1 + 1"
}
)
expect(res.value).toEqual(2)
expect(res.success).toEqual(true)
})
it("should handle a null value", async () => {
let res = await setup.runStep(setup.actions.EXECUTE_SCRIPT.stepId,
inputs = {
code: null
}
)
expect(res.response.message).toEqual("Invalid inputs")
expect(res.success).toEqual(false)
})
it("should be able to handle an error gracefully", async () => {
let res = await setup.runStep(setup.actions.EXECUTE_SCRIPT.stepId,
inputs = {
code: "return something.map(x => x.name)"
}
)
expect(res.response).toEqual("ReferenceError: something is not defined")
expect(res.success).toEqual(false)
})
it("should handle a null value", async () => {
let res = await setup.runStep(
setup.actions.EXECUTE_SCRIPT.stepId,
(inputs = {
code: null,
})
)
expect(res.response.message).toEqual("Invalid inputs")
expect(res.success).toEqual(false)
})
it("should be able to handle an error gracefully", async () => {
let res = await setup.runStep(
setup.actions.EXECUTE_SCRIPT.stepId,
(inputs = {
code: "return something.map(x => x.name)",
})
)
expect(res.response).toEqual("ReferenceError: something is not defined")
expect(res.success).toEqual(false)
})
})

View File

@ -21,7 +21,10 @@ describe("test the outgoing webhook action", () => {
afterAll(setup.afterAll)
it("should be able to run the action", async () => {
const res = await setup.runStep(setup.actions.OUTGOING_WEBHOOK.stepId, inputs)
const res = await setup.runStep(
setup.actions.OUTGOING_WEBHOOK.stepId,
inputs
)
expect(res.success).toEqual(true)
expect(res.response.url).toEqual("http://www.test.com")
expect(res.response.method).toEqual("POST")
@ -31,9 +34,8 @@ describe("test the outgoing webhook action", () => {
it("should return an error if something goes wrong in fetch", async () => {
const res = await setup.runStep(setup.actions.OUTGOING_WEBHOOK.stepId, {
requestMethod: "GET",
url: "www.invalid.com"
url: "www.invalid.com",
})
expect(res.success).toEqual(false)
})
})

View File

@ -1,22 +1,19 @@
const setup = require("./utilities")
describe("test the server log action", () => {
let config = setup.getConfig()
let config = setup.getConfig()
beforeAll(async () => {
await config.init()
inputs = {
text: "log message",
}
})
afterAll(setup.afterAll)
beforeAll(async () => {
await config.init()
inputs = {
text: "log message",
}
})
afterAll(setup.afterAll)
it("should be able to log the text", async () => {
let res = await setup.runStep(setup.actions.SERVER_LOG.stepId,
inputs
)
expect(res.message).toEqual(`App ${config.getAppId()} - ${inputs.text}`)
expect(res.success).toEqual(true)
})
it("should be able to log the text", async () => {
let res = await setup.runStep(setup.actions.SERVER_LOG.stepId, inputs)
expect(res.message).toEqual(`App ${config.getAppId()} - ${inputs.text}`)
expect(res.success).toEqual(true)
})
})

View File

@ -1,5 +1,9 @@
const TestConfig = require("../../tests/utilities/TestConfiguration")
const { basicRow, basicLinkedRow, basicTable } = require("../../tests/utilities/structures")
const {
basicRow,
basicLinkedRow,
basicTable,
} = require("../../tests/utilities/structures")
const LinkController = require("../linkedRows/LinkController").default
const { context } = require("@budibase/backend-core")
const { RelationshipType } = require("../../constants")
@ -16,7 +20,10 @@ describe("test the link controller", () => {
beforeEach(async () => {
const { _id } = await config.createTable()
table2 = await config.createLinkedTable(RelationshipType.MANY_TO_MANY, ["link", "link2"])
table2 = await config.createLinkedTable(RelationshipType.MANY_TO_MANY, [
"link",
"link2",
])
// update table after creating link
table1 = await config.getTable(_id)
})
@ -41,15 +48,23 @@ describe("test the link controller", () => {
async function createLinkedRow(linkField = "link", t1 = table1, t2 = table2) {
const row = await config.createRow(basicRow(t2._id))
const { _id } = await config.createRow(basicLinkedRow(t1._id, row._id, linkField))
const { _id } = await config.createRow(
basicLinkedRow(t1._id, row._id, linkField)
)
return config.getRow(t1._id, _id)
}
it("should be able to confirm if two table schemas are equal", async () => {
const controller = await createLinkController(table1)
let equal = controller.areLinkSchemasEqual(table2.schema.link, table2.schema.link)
let equal = controller.areLinkSchemasEqual(
table2.schema.link,
table2.schema.link
)
expect(equal).toEqual(true)
equal = controller.areLinkSchemasEqual(table1.schema.link, table2.schema.link)
equal = controller.areLinkSchemasEqual(
table1.schema.link,
table2.schema.link
)
expect(equal).toEqual(false)
})
@ -57,17 +72,42 @@ describe("test the link controller", () => {
const controller = await createLinkController(table1)
// empty case
let output = controller.handleRelationshipType({}, {})
expect(output.linkedField.relationshipType).toEqual(RelationshipType.MANY_TO_MANY)
expect(output.linkerField.relationshipType).toEqual(RelationshipType.MANY_TO_MANY)
output = controller.handleRelationshipType({ relationshipType: RelationshipType.MANY_TO_MANY }, {})
expect(output.linkedField.relationshipType).toEqual(RelationshipType.MANY_TO_MANY)
expect(output.linkerField.relationshipType).toEqual(RelationshipType.MANY_TO_MANY)
output = controller.handleRelationshipType({ relationshipType: RelationshipType.MANY_TO_ONE }, {})
expect(output.linkedField.relationshipType).toEqual(RelationshipType.ONE_TO_MANY)
expect(output.linkerField.relationshipType).toEqual(RelationshipType.MANY_TO_ONE)
output = controller.handleRelationshipType({ relationshipType: RelationshipType.ONE_TO_MANY }, {})
expect(output.linkedField.relationshipType).toEqual(RelationshipType.MANY_TO_ONE)
expect(output.linkerField.relationshipType).toEqual(RelationshipType.ONE_TO_MANY)
expect(output.linkedField.relationshipType).toEqual(
RelationshipType.MANY_TO_MANY
)
expect(output.linkerField.relationshipType).toEqual(
RelationshipType.MANY_TO_MANY
)
output = controller.handleRelationshipType(
{ relationshipType: RelationshipType.MANY_TO_MANY },
{}
)
expect(output.linkedField.relationshipType).toEqual(
RelationshipType.MANY_TO_MANY
)
expect(output.linkerField.relationshipType).toEqual(
RelationshipType.MANY_TO_MANY
)
output = controller.handleRelationshipType(
{ relationshipType: RelationshipType.MANY_TO_ONE },
{}
)
expect(output.linkedField.relationshipType).toEqual(
RelationshipType.ONE_TO_MANY
)
expect(output.linkerField.relationshipType).toEqual(
RelationshipType.MANY_TO_ONE
)
output = controller.handleRelationshipType(
{ relationshipType: RelationshipType.ONE_TO_MANY },
{}
)
expect(output.linkedField.relationshipType).toEqual(
RelationshipType.MANY_TO_ONE
)
expect(output.linkerField.relationshipType).toEqual(
RelationshipType.ONE_TO_MANY
)
})
it("should be able to delete a row", async () => {
@ -100,7 +140,7 @@ describe("test the link controller", () => {
it("should throw an error when validating a table which is invalid", async () => {
const controller = await createLinkController(table1)
const copyTable = {
...table1
...table1,
}
copyTable.schema.otherTableLink = {
type: "link",
@ -114,7 +154,9 @@ describe("test the link controller", () => {
error = err
}
expect(error).toBeDefined()
expect(error.message).toEqual("Cannot re-use the linked column name for a linked table.")
expect(error.message).toEqual(
"Cannot re-use the linked column name for a linked table."
)
})
it("should be able to remove a link when saving/updating the row", async () => {
@ -183,7 +225,10 @@ describe("test the link controller", () => {
it("shouldn't allow one to many having many relationships against it", async () => {
const firstTable = await config.createTable()
const { _id } = await config.createLinkedTable(RelationshipType.MANY_TO_ONE, ["link"])
const { _id } = await config.createLinkedTable(
RelationshipType.MANY_TO_ONE,
["link"]
)
const linkTable = await config.getTable(_id)
// an initial row to link around
const row = await createLinkedRow("link", linkTable, firstTable)

View File

@ -45,7 +45,9 @@ describe("test link functionality", () => {
})
it("should get the field from the link", () => {
expect(linkUtils.getRelatedTableForField(link, "otherLink")).toBe("tableID")
expect(linkUtils.getRelatedTableForField(link, "otherLink")).toBe(
"tableID"
)
})
})

View File

@ -3,7 +3,7 @@ const {
paramSubResource,
bodyResource,
bodySubResource,
ResourceIdGetter
ResourceIdGetter,
} = require("../resourceId")
class TestConfiguration {
@ -41,7 +41,7 @@ describe("resourceId middleware", () => {
it("generates a resourceId middleware for context query parameters", () => {
const config = new TestConfiguration(paramResource("main"))
config.setParams({
main: "test"
main: "test",
})
config.executeMiddleware()
@ -53,7 +53,7 @@ describe("resourceId middleware", () => {
const config = new TestConfiguration(paramSubResource("main", "sub"))
config.setParams({
main: "main",
sub: "test"
sub: "test",
})
config.executeMiddleware()
@ -65,7 +65,7 @@ describe("resourceId middleware", () => {
it("generates a resourceId middleware for context request body", () => {
const config = new TestConfiguration(bodyResource("main"))
config.setBody({
main: "test"
main: "test",
})
config.executeMiddleware()
@ -77,7 +77,7 @@ describe("resourceId middleware", () => {
const config = new TestConfiguration(bodySubResource("main", "sub"))
config.setBody({
main: "main",
sub: "test"
sub: "test",
})
config.executeMiddleware()
@ -94,7 +94,7 @@ describe("resourceId middleware", () => {
let config = new TestConfiguration(middleware)
config.setBody({
custom: "test",
customSub: "subtest"
customSub: "subtest",
})
config.executeMiddleware()

View File

@ -10,7 +10,7 @@ class TestConfiguration {
this.ctx = {
next: this.next,
throw: this.throw
throw: this.throw,
}
}

View File

@ -4,8 +4,8 @@ jest.mock("@budibase/backend-core", () => {
...core,
db: {
...core.db,
createNewUserEmailView: jest.fn()
}
createNewUserEmailView: jest.fn(),
},
}
})
const { context, db: dbCore } = require("@budibase/backend-core")
@ -16,19 +16,19 @@ const TestConfig = require("../../../tests/utilities/TestConfiguration")
const migration = require("../userEmailViewCasing")
describe("run", () => {
let config = new TestConfig(false)
let config = new TestConfig(false)
beforeAll(async () => {
await config.init()
})
afterAll(config.end)
it("runs successfully", async () => {
await config.doInTenant(async () => {
const globalDb = context.getGlobalDB()
await migration.run(globalDb)
expect(dbCore.createNewUserEmailView).toHaveBeenCalledTimes(1)
})
beforeAll(async () => {
await config.init()
})
afterAll(config.end)
it("runs successfully", async () => {
await config.doInTenant(async () => {
const globalDb = context.getGlobalDB()
await migration.run(globalDb)
expect(dbCore.createNewUserEmailView).toHaveBeenCalledTimes(1)
})
})
})

View File

@ -86,11 +86,11 @@ describe("Test that the object processing works correctly", () => {
})
it("check objects get converted to string JSON automatically", async () => {
const row = {a: 1}
const row = { a: 1 }
const output = await processString("{{ trigger.row }}", {
trigger: {
row,
}
},
})
expect(JSON.parse(output)).toEqual(row)
})
@ -108,9 +108,9 @@ describe("Test that the object processing works correctly", () => {
describe("check returning objects", () => {
it("should handle an array of objects", async () => {
const json = [{a: 1},{a: 2}]
const json = [{ a: 1 }, { a: 2 }]
const output = await processString("{{ testing }}", {
testing: json
testing: json,
})
expect(output).toEqual(JSON.stringify(json))
})
@ -164,9 +164,12 @@ describe("check manifest", () => {
describe("check full stops that are safe", () => {
it("should allow using an escaped full stop", async () => {
const data = {
"c53a4a604fa754d33baaafd5bca4d3658-YXuUBqt5vI": { "persons.firstname": "1" }
"c53a4a604fa754d33baaafd5bca4d3658-YXuUBqt5vI": {
"persons.firstname": "1",
},
}
const template = "{{ [c53a4a604fa754d33baaafd5bca4d3658-YXuUBqt5vI].[persons.firstname] }}"
const template =
"{{ [c53a4a604fa754d33baaafd5bca4d3658-YXuUBqt5vI].[persons.firstname] }}"
const output = await processString(template, data)
expect(output).toEqual("1")
})
@ -195,7 +198,9 @@ describe("check that disabling escaping function works", () => {
})
it("should work for two statements", () => {
expect(disableEscaping("{{ name }} welcome to {{ platform }}")).toEqual("{{{ name }}} welcome to {{{ platform }}}")
expect(disableEscaping("{{ name }} welcome to {{ platform }}")).toEqual(
"{{{ name }}} welcome to {{{ platform }}}"
)
})
it("shouldn't convert triple braces", () => {
@ -203,11 +208,15 @@ describe("check that disabling escaping function works", () => {
})
it("should work with a combination", () => {
expect(disableEscaping("{{ name }} welcome to {{{ platform }}}")).toEqual("{{{ name }}} welcome to {{{ platform }}}")
expect(disableEscaping("{{ name }} welcome to {{{ platform }}}")).toEqual(
"{{{ name }}} welcome to {{{ platform }}}"
)
})
it("should work with multiple escaped", () => {
expect(disableEscaping("{{ name }} welcome to {{ name }}")).toEqual("{{{ name }}} welcome to {{{ name }}}")
expect(disableEscaping("{{ name }} welcome to {{ name }}")).toEqual(
"{{{ name }}} welcome to {{{ name }}}"
)
})
})
@ -217,13 +226,20 @@ describe("check find hbs blocks function", () => {
})
it("should find two", () => {
expect(findHBSBlocks("{{ hello }} there {{{ name }}}")).toEqual(["{{ hello }}", "{{{ name }}}"])
expect(findHBSBlocks("{{ hello }} there {{{ name }}}")).toEqual([
"{{ hello }}",
"{{{ name }}}",
])
})
})
describe("should leave HBS blocks if not found using option", () => {
it("should replace one, leave one", async () => {
const output = await processString("{{ a }}, {{ b }}", { b: 1 }, { onlyFound: true })
const output = await processString(
"{{ a }}, {{ b }}",
{ b: 1 },
{ onlyFound: true }
)
expect(output).toBe("{{ a }}, 1")
})
})

View File

@ -68,11 +68,11 @@ describe("attempt some complex problems", () => {
describe("check behaviour with newlines", () => {
const context = {
binding: `Hello
there`
there`,
}
it("should escape new line to \\n with double brace", async () => {
const hbs = JSON.stringify({
body: "{{ binding }}"
body: "{{ binding }}",
})
const output = await processString(hbs, context, { escapeNewlines: true })
expect(JSON.parse(output).body).toBe(context.binding)
@ -80,7 +80,7 @@ describe("check behaviour with newlines", () => {
it("should work the same with triple brace", async () => {
const hbs = JSON.stringify({
body: "{{{ binding }}}"
body: "{{{ binding }}}",
})
const output = await processString(hbs, context, { escapeNewlines: true })
expect(JSON.parse(output).body).toBe(context.binding)
@ -88,9 +88,12 @@ describe("check behaviour with newlines", () => {
it("should still work with helpers disabled", async () => {
const hbs = JSON.stringify({
body: "{{ binding }}"
body: "{{ binding }}",
})
const output = await processString(hbs, context, {
escapeNewlines: true,
noHelpers: true,
})
const output = await processString(hbs, context, { escapeNewlines: true, noHelpers: true })
expect(JSON.parse(output).body).toBe(context.binding)
})
})

View File

@ -1,6 +1,4 @@
const {
convertToJS
} = require("../src/index.cjs")
const { convertToJS } = require("../src/index.cjs")
function checkLines(response, lines) {
const toCheck = response.split("\n")
@ -18,25 +16,19 @@ describe("Test that the string processing works correctly", () => {
it("basic example with square brackets", () => {
const response = convertToJS("{{ [query] }}")
checkLines(response, [
"const var1 = $(\"[query]\");",
"return `${var1}`;",
])
checkLines(response, ['const var1 = $("[query]");', "return `${var1}`;"])
})
it("handle properties", () => {
const response = convertToJS("{{ [query].id }}")
checkLines(response, [
"const var1 = $(\"[query].id\");",
"return `${var1}`;",
])
checkLines(response, ['const var1 = $("[query].id");', "return `${var1}`;"])
})
it("should convert some basic HBS strings", () => {
const response = convertToJS("Hello {{ name }}, welcome to {{ company }}!")
checkLines(response, [
"const var1 = $(\"name\");",
"const var2 = $(\"company\");",
'const var1 = $("name");',
'const var2 = $("company");',
"return `Hello ${var1}, welcome to ${var2}`;",
])
})
@ -44,7 +36,7 @@ describe("Test that the string processing works correctly", () => {
it("should handle many square brackets in helpers", () => {
const response = convertToJS("Hello {{ avg [user].[_id] [user].[_rev] }}")
checkLines(response, [
"const var1 = helpers.avg($(\"[user].[_id]\"), $(\"[user].[_rev]\"));",
'const var1 = helpers.avg($("[user].[_id]"), $("[user].[_rev]"));',
"return `Hello ${var1}`;",
])
})
@ -61,7 +53,7 @@ describe("Test that the string processing works correctly", () => {
const response = convertToJS("{{equalsLength '[1,2,3]' 3}}")
checkLines(response, [
"const var1 = helpers.equalsLength('[1,2,3]', 3);",
"return `${var1}`;"
"return `${var1}`;",
])
})
@ -84,23 +76,27 @@ describe("Test that the string processing works correctly", () => {
it("should handle a helper block", () => {
const response = convertToJS("This is the average: {{ avg array }}")
checkLines(response, [
"const var1 = helpers.avg($(\"array\"));",
'const var1 = helpers.avg($("array"));',
"return `This is the average: ${var1}`;",
])
})
it("should handle multi-variable helper", () => {
const response = convertToJS("This is the average: {{ join ( avg val1 val2 val3 ) }}")
const response = convertToJS(
"This is the average: {{ join ( avg val1 val2 val3 ) }}"
)
checkLines(response, [
"const var1 = helpers.join(helpers.avg($(\"val1\"), $(\"val2\"), $(\"val3\")));",
'const var1 = helpers.join(helpers.avg($("val1"), $("val2"), $("val3")));',
"return `This is the average: ${var1}`;",
])
})
it("should handle a complex statement", () => {
const response = convertToJS("This is the average: {{ join ( avg val1 val2 val3 ) val4 }}")
const response = convertToJS(
"This is the average: {{ join ( avg val1 val2 val3 ) val4 }}"
)
checkLines(response, [
"const var1 = helpers.join(helpers.avg($(\"val1\"), $(\"val2\"), $(\"val3\")), $(\"val4\"));",
'const var1 = helpers.join(helpers.avg($("val1"), $("val2"), $("val3")), $("val4"));',
"return `This is the average: ${var1}`;",
])
})
@ -108,7 +104,7 @@ describe("Test that the string processing works correctly", () => {
it("should handle square brackets", () => {
const response = convertToJS("This is: {{ [val thing] }}")
checkLines(response, [
"const var1 = $(\"[val thing]\");",
'const var1 = $("[val thing]");',
"return `This is: ${var1}`;",
])
})
@ -116,15 +112,17 @@ describe("Test that the string processing works correctly", () => {
it("should handle square brackets with properties", () => {
const response = convertToJS("{{ [user].[_id] }}")
checkLines(response, [
"const var1 = $(\"[user].[_id]\");",
'const var1 = $("[user].[_id]");',
"return `${var1}`;",
])
})
it("should handle multiple complex statements", () => {
const response = convertToJS("average: {{ avg ( abs val1 ) val2 }} add: {{ add 1 2 }}")
const response = convertToJS(
"average: {{ avg ( abs val1 ) val2 }} add: {{ add 1 2 }}"
)
checkLines(response, [
"const var1 = helpers.avg(helpers.abs($(\"val1\")), $(\"val2\"));",
'const var1 = helpers.avg(helpers.abs($("val1")), $("val2"));',
"const var2 = helpers.add(1, 2);",
"return `average: ${var1} add: ${var2}`;",
])

View File

@ -266,10 +266,7 @@ describe("test the string helpers", () => {
})
it("should allow use of the ellipsis helper", async () => {
const output = await processString(
"{{ ellipsis \"adfasdfasdfasf\" 7 }}",
{},
)
const output = await processString('{{ ellipsis "adfasdfasdfasf" 7 }}', {})
expect(output).toBe("adfasdf…")
})
})