Updating row tests, reducing console logging during tests for speed and clarity, testing some misc endpoints and updating search functionality to use a starts with operator when working with strings on rows.
This commit is contained in:
parent
f69e06870b
commit
163d24a767
|
@ -33,7 +33,7 @@
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "jest --testPathIgnorePatterns=routes && npm run test:integration",
|
"test": "jest --testPathIgnorePatterns=routes && npm run test:integration",
|
||||||
"test:integration": "jest routes --runInBand --coverage",
|
"test:integration": "jest --runInBand --coverage",
|
||||||
"test:watch": "jest --watch",
|
"test:watch": "jest --watch",
|
||||||
"run:docker": "node src/index",
|
"run:docker": "node src/index",
|
||||||
"dev:builder": "cross-env PORT=4001 nodemon src/index.js",
|
"dev:builder": "cross-env PORT=4001 nodemon src/index.js",
|
||||||
|
|
|
@ -3,21 +3,14 @@ const { join } = require("../../utilities/centralPath")
|
||||||
const readline = require("readline")
|
const readline = require("readline")
|
||||||
const { budibaseAppsDir } = require("../../utilities/budibaseDir")
|
const { budibaseAppsDir } = require("../../utilities/budibaseDir")
|
||||||
const env = require("../../environment")
|
const env = require("../../environment")
|
||||||
const selfhost = require("../../selfhost")
|
|
||||||
const ENV_FILE_PATH = "/.env"
|
const ENV_FILE_PATH = "/.env"
|
||||||
|
|
||||||
exports.fetch = async function(ctx) {
|
exports.fetch = async function(ctx) {
|
||||||
ctx.status = 200
|
ctx.status = 200
|
||||||
if (env.SELF_HOSTED) {
|
|
||||||
ctx.body = {
|
|
||||||
selfhost: await selfhost.getSelfHostAPIKey(),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
budibase: env.BUDIBASE_API_KEY,
|
budibase: env.BUDIBASE_API_KEY,
|
||||||
userId: env.USERID_API_KEY,
|
userId: env.USERID_API_KEY,
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.update = async function(ctx) {
|
exports.update = async function(ctx) {
|
||||||
|
|
|
@ -224,6 +224,7 @@ exports.fetchView = async function(ctx) {
|
||||||
try {
|
try {
|
||||||
table = await db.get(viewInfo.meta.tableId)
|
table = await db.get(viewInfo.meta.tableId)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
/* istanbul ignore next */
|
||||||
table = {
|
table = {
|
||||||
schema: {},
|
schema: {},
|
||||||
}
|
}
|
||||||
|
@ -255,16 +256,24 @@ exports.fetchView = async function(ctx) {
|
||||||
|
|
||||||
exports.search = async function(ctx) {
|
exports.search = async function(ctx) {
|
||||||
const appId = ctx.user.appId
|
const appId = ctx.user.appId
|
||||||
|
|
||||||
const db = new CouchDB(appId)
|
const db = new CouchDB(appId)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
query,
|
query,
|
||||||
pagination: { pageSize = 10, page },
|
pagination: { pageSize = 10, page },
|
||||||
} = ctx.request.body
|
} = ctx.request.body
|
||||||
|
|
||||||
query.tableId = ctx.params.tableId
|
// make all strings a starts with operation rather than pure equality
|
||||||
|
for (const [key, queryVal] of Object.entries(query)) {
|
||||||
|
if (typeof queryVal === "string") {
|
||||||
|
query[key] = {
|
||||||
|
$gt: queryVal,
|
||||||
|
$lt: `${queryVal}\uffff`,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pure equality for table
|
||||||
|
query.tableId = ctx.params.tableId
|
||||||
const response = await db.find({
|
const response = await db.find({
|
||||||
selector: query,
|
selector: query,
|
||||||
limit: pageSize,
|
limit: pageSize,
|
||||||
|
@ -324,7 +333,6 @@ exports.destroy = async function(ctx) {
|
||||||
const row = await db.get(ctx.params.rowId)
|
const row = await db.get(ctx.params.rowId)
|
||||||
if (row.tableId !== ctx.params.tableId) {
|
if (row.tableId !== ctx.params.tableId) {
|
||||||
ctx.throw(400, "Supplied tableId doesn't match the row's tableId")
|
ctx.throw(400, "Supplied tableId doesn't match the row's tableId")
|
||||||
return
|
|
||||||
}
|
}
|
||||||
await linkRows.updateLinks({
|
await linkRows.updateLinks({
|
||||||
appId,
|
appId,
|
||||||
|
@ -376,15 +384,6 @@ exports.fetchEnrichedRow = async function(ctx) {
|
||||||
const db = new CouchDB(appId)
|
const db = new CouchDB(appId)
|
||||||
const tableId = ctx.params.tableId
|
const tableId = ctx.params.tableId
|
||||||
const rowId = ctx.params.rowId
|
const rowId = ctx.params.rowId
|
||||||
if (appId == null || tableId == null || rowId == null) {
|
|
||||||
ctx.status = 400
|
|
||||||
ctx.body = {
|
|
||||||
status: 400,
|
|
||||||
error:
|
|
||||||
"Cannot handle request, URI params have not been successfully prepared.",
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// need table to work out where links go in row
|
// need table to work out where links go in row
|
||||||
let [table, row] = await Promise.all([
|
let [table, row] = await Promise.all([
|
||||||
db.get(tableId),
|
db.get(tableId),
|
||||||
|
|
|
@ -41,14 +41,16 @@ router.use(async (ctx, next) => {
|
||||||
try {
|
try {
|
||||||
await next()
|
await next()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
ctx.log.error(err)
|
|
||||||
ctx.status = err.status || err.statusCode || 500
|
ctx.status = err.status || err.statusCode || 500
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
message: err.message,
|
message: err.message,
|
||||||
status: ctx.status,
|
status: ctx.status,
|
||||||
}
|
}
|
||||||
|
if (env.NODE_ENV !== "jest") {
|
||||||
|
ctx.log.error(err)
|
||||||
console.trace(err)
|
console.trace(err)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
router.get("/health", ctx => (ctx.status = 200))
|
router.get("/health", ctx => (ctx.status = 200))
|
||||||
|
|
|
@ -8,6 +8,7 @@ const usage = require("../../middleware/usageQuota")
|
||||||
|
|
||||||
const router = Router()
|
const router = Router()
|
||||||
|
|
||||||
|
/* istanbul ignore next */
|
||||||
router.param("file", async (file, ctx, next) => {
|
router.param("file", async (file, ctx, next) => {
|
||||||
ctx.file = file && file.includes(".") ? file : "index.html"
|
ctx.file = file && file.includes(".") ? file : "index.html"
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ describe("/api/keys", () => {
|
||||||
|
|
||||||
describe("update", () => {
|
describe("update", () => {
|
||||||
it("should allow updating a value", async () => {
|
it("should allow updating a value", async () => {
|
||||||
fs.writeFileSync(path.join(budibaseAppsDir(), ".env"), "")
|
fs.writeFileSync(path.join(budibaseAppsDir(), ".env"), "TEST_API_KEY=thing")
|
||||||
const res = await request
|
const res = await request
|
||||||
.put(`/api/keys/TEST`)
|
.put(`/api/keys/TEST`)
|
||||||
.send({
|
.send({
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
const setup = require("./utilities")
|
||||||
|
|
||||||
|
describe("test things in the Cloud/Self hosted", () => {
|
||||||
|
describe("test self hosted static page", () => {
|
||||||
|
it("should be able to load the static page", async () => {
|
||||||
|
await setup.switchToCloudForFunction(async () => {
|
||||||
|
let request = setup.getRequest()
|
||||||
|
let config = setup.getConfig()
|
||||||
|
await config.init()
|
||||||
|
const res = await request.get(`/`).expect(200)
|
||||||
|
expect(res.text.includes("<title>Budibase self hosting️</title>")).toEqual(true)
|
||||||
|
setup.afterAll()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
|
@ -17,15 +17,15 @@ describe("/rows", () => {
|
||||||
row = basicRow(table._id)
|
row = basicRow(table._id)
|
||||||
})
|
})
|
||||||
|
|
||||||
const loadRow = async id =>
|
const loadRow = async (id, status = 200) =>
|
||||||
await request
|
await request
|
||||||
.get(`/api/${table._id}/rows/${id}`)
|
.get(`/api/${table._id}/rows/${id}`)
|
||||||
.set(config.defaultHeaders())
|
.set(config.defaultHeaders())
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(200)
|
.expect(status)
|
||||||
|
|
||||||
|
|
||||||
describe("save, load, update, delete", () => {
|
describe("save, load, update", () => {
|
||||||
it("returns a success message when the row is created", async () => {
|
it("returns a success message when the row is created", async () => {
|
||||||
const res = await request
|
const res = await request
|
||||||
.post(`/api/${row.tableId}/rows`)
|
.post(`/api/${row.tableId}/rows`)
|
||||||
|
@ -217,38 +217,152 @@ describe("/rows", () => {
|
||||||
|
|
||||||
expect(savedRow.body.description).toEqual(existing.description)
|
expect(savedRow.body.description).toEqual(existing.description)
|
||||||
expect(savedRow.body.name).toEqual("Updated Name")
|
expect(savedRow.body.name).toEqual("Updated Name")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should throw an error when given improper types", async () => {
|
||||||
|
const existing = await config.createRow()
|
||||||
|
await request
|
||||||
|
.patch(`/api/${table._id}/rows/${existing._id}`)
|
||||||
|
.send({
|
||||||
|
_id: existing._id,
|
||||||
|
_rev: existing._rev,
|
||||||
|
tableId: table._id,
|
||||||
|
name: 1,
|
||||||
|
})
|
||||||
|
.set(config.defaultHeaders())
|
||||||
|
.expect(400)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("destroy", () => {
|
||||||
|
it("should be able to delete a row", async () => {
|
||||||
|
const createdRow = await config.createRow(row)
|
||||||
|
const res = await request
|
||||||
|
.delete(`/api/${table._id}/rows/${createdRow._id}/${createdRow._rev}`)
|
||||||
|
.set(config.defaultHeaders())
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200)
|
||||||
|
expect(res.body.ok).toEqual(true)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("shouldn't allow deleting a row in a table which is different to the one the row was created on", async () => {
|
||||||
|
const createdRow = await config.createRow(row)
|
||||||
|
await request
|
||||||
|
.delete(`/api/wrong_table/rows/${createdRow._id}/${createdRow._rev}`)
|
||||||
|
.set(config.defaultHeaders())
|
||||||
|
.expect(400)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("validate", () => {
|
describe("validate", () => {
|
||||||
it("should return no errors on valid row", async () => {
|
it("should return no errors on valid row", async () => {
|
||||||
const result = await request
|
const res = await request
|
||||||
.post(`/api/${table._id}/rows/validate`)
|
.post(`/api/${table._id}/rows/validate`)
|
||||||
.send({ name: "ivan" })
|
.send({ name: "ivan" })
|
||||||
.set(config.defaultHeaders())
|
.set(config.defaultHeaders())
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
|
|
||||||
expect(result.body.valid).toBe(true)
|
expect(res.body.valid).toBe(true)
|
||||||
expect(Object.keys(result.body.errors)).toEqual([])
|
expect(Object.keys(res.body.errors)).toEqual([])
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should errors on invalid row", async () => {
|
it("should errors on invalid row", async () => {
|
||||||
const result = await request
|
const res = await request
|
||||||
.post(`/api/${table._id}/rows/validate`)
|
.post(`/api/${table._id}/rows/validate`)
|
||||||
.send({ name: 1 })
|
.send({ name: 1 })
|
||||||
.set(config.defaultHeaders())
|
.set(config.defaultHeaders())
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
|
|
||||||
expect(result.body.valid).toBe(false)
|
expect(res.body.valid).toBe(false)
|
||||||
expect(Object.keys(result.body.errors)).toEqual(["name"])
|
expect(Object.keys(res.body.errors)).toEqual(["name"])
|
||||||
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
describe("enrich row unit test", () => {
|
describe("bulkDelete", () => {
|
||||||
|
it("should be able to delete a bulk set of rows", async () => {
|
||||||
|
const row1 = await config.createRow()
|
||||||
|
const row2 = await config.createRow()
|
||||||
|
const res = await request
|
||||||
|
.post(`/api/${table._id}/rows`)
|
||||||
|
.send({
|
||||||
|
type: "delete",
|
||||||
|
rows: [
|
||||||
|
row1,
|
||||||
|
row2,
|
||||||
|
]
|
||||||
|
})
|
||||||
|
.set(config.defaultHeaders())
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200)
|
||||||
|
expect(res.body.length).toEqual(2)
|
||||||
|
await loadRow(row1._id, 404)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("search", () => {
|
||||||
|
it("should run a search on the table", async () => {
|
||||||
|
const row = await config.createRow()
|
||||||
|
// add another row that shouldn't be found
|
||||||
|
await config.createRow({
|
||||||
|
...basicRow(),
|
||||||
|
name: "Other Contact",
|
||||||
|
})
|
||||||
|
const res = await request
|
||||||
|
.post(`/api/${table._id}/rows/search`)
|
||||||
|
.send({
|
||||||
|
query: {
|
||||||
|
name: "Test",
|
||||||
|
},
|
||||||
|
pagination: { pageSize: 25, page: 0 }
|
||||||
|
})
|
||||||
|
.set(config.defaultHeaders())
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200)
|
||||||
|
expect(res.body.length).toEqual(1)
|
||||||
|
expect(res.body[0]._id).toEqual(row._id)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("fetchView", () => {
|
||||||
|
it("should be able to fetch tables contents via 'view'", async () => {
|
||||||
|
const row = await config.createRow()
|
||||||
|
const res = await request
|
||||||
|
.get(`/api/views/all_${table._id}`)
|
||||||
|
.set(config.defaultHeaders())
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200)
|
||||||
|
expect(res.body.length).toEqual(1)
|
||||||
|
expect(res.body[0]._id).toEqual(row._id)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should throw an error if view doesn't exist", async () => {
|
||||||
|
await request
|
||||||
|
.get(`/api/views/derp`)
|
||||||
|
.set(config.defaultHeaders())
|
||||||
|
.expect(400)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should be able to run on a view", async () => {
|
||||||
|
const view = await config.createView()
|
||||||
|
const row = await config.createRow()
|
||||||
|
const res = await request
|
||||||
|
.get(`/api/views/${view._id}`)
|
||||||
|
.set(config.defaultHeaders())
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200)
|
||||||
|
expect(res.body.length).toEqual(1)
|
||||||
|
expect(res.body[0]._id).toEqual(row._id)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("user testing", () => {
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("fetchEnrichedRows", () => {
|
||||||
it("should allow enriching some linked rows", async () => {
|
it("should allow enriching some linked rows", async () => {
|
||||||
const table = await config.createLinkedTable()
|
const table = await config.createLinkedTable()
|
||||||
const firstRow = await config.createRow({
|
const firstRow = await config.createRow({
|
||||||
|
@ -262,13 +376,30 @@ describe("/rows", () => {
|
||||||
link: [{_id: firstRow._id}],
|
link: [{_id: firstRow._id}],
|
||||||
tableId: table._id,
|
tableId: table._id,
|
||||||
})
|
})
|
||||||
const enriched = await outputProcessing(config.getAppId(), table, [secondRow])
|
|
||||||
expect(enriched[0].link.length).toBe(1)
|
// test basic enrichment
|
||||||
expect(enriched[0].link[0]._id).toBe(firstRow._id)
|
const resBasic = await request
|
||||||
expect(enriched[0].link[0].primaryDisplay).toBe("Test Contact")
|
.get(`/api/${table._id}/rows/${secondRow._id}`)
|
||||||
|
.set(config.defaultHeaders())
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200)
|
||||||
|
expect(resBasic.body.link[0]._id).toBe(firstRow._id)
|
||||||
|
expect(resBasic.body.link[0].primaryDisplay).toBe("Test Contact")
|
||||||
|
|
||||||
|
// test full enrichment
|
||||||
|
const resEnriched = await request
|
||||||
|
.get(`/api/${table._id}/${secondRow._id}/enrich`)
|
||||||
|
.set(config.defaultHeaders())
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200)
|
||||||
|
expect(resEnriched.body.link.length).toBe(1)
|
||||||
|
expect(resEnriched.body.link[0]._id).toBe(firstRow._id)
|
||||||
|
expect(resEnriched.body.link[0].name).toBe("Test Contact")
|
||||||
|
expect(resEnriched.body.link[0].description).toBe("original description")
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("attachments", () => {
|
||||||
it("should allow enriching attachment rows", async () => {
|
it("should allow enriching attachment rows", async () => {
|
||||||
const table = await config.createAttachmentTable()
|
const table = await config.createAttachmentTable()
|
||||||
const row = await config.createRow({
|
const row = await config.createRow({
|
||||||
|
@ -280,12 +411,10 @@ describe("/rows", () => {
|
||||||
tableId: table._id,
|
tableId: table._id,
|
||||||
})
|
})
|
||||||
// the environment needs configured for this
|
// the environment needs configured for this
|
||||||
env.CLOUD = 1
|
await setup.switchToCloudForFunction(async () => {
|
||||||
env.SELF_HOSTED = 1
|
|
||||||
const enriched = await outputProcessing(config.getAppId(), table, [row])
|
const enriched = await outputProcessing(config.getAppId(), table, [row])
|
||||||
expect(enriched[0].attachment[0].url).toBe(`/app-assets/assets/${config.getAppId()}/test/thing`)
|
expect(enriched[0].attachment[0].url).toBe(`/app-assets/assets/${config.getAppId()}/test/thing`)
|
||||||
// remove env config
|
})
|
||||||
env.CLOUD = undefined
|
})
|
||||||
env.SELF_HOSTED = undefined
|
|
||||||
})
|
})
|
||||||
})
|
})
|
|
@ -56,7 +56,11 @@ if (electron.app && electron.app.isPackaged) {
|
||||||
const server = http.createServer(app.callback())
|
const server = http.createServer(app.callback())
|
||||||
destroyable(server)
|
destroyable(server)
|
||||||
|
|
||||||
server.on("close", () => console.log("Server Closed"))
|
server.on("close", () => {
|
||||||
|
if (env.NODE_ENV !== "jest") {
|
||||||
|
console.log("Server Closed")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
module.exports = server.listen(env.PORT || 0, async () => {
|
module.exports = server.listen(env.PORT || 0, async () => {
|
||||||
console.log(`Budibase running on ${JSON.stringify(server.address())}`)
|
console.log(`Budibase running on ${JSON.stringify(server.address())}`)
|
||||||
|
|
|
@ -9,7 +9,6 @@ class TestConfiguration {
|
||||||
this.ctx = {
|
this.ctx = {
|
||||||
config: {},
|
config: {},
|
||||||
auth: {},
|
auth: {},
|
||||||
request: {},
|
|
||||||
cookies: {
|
cookies: {
|
||||||
set: jest.fn(),
|
set: jest.fn(),
|
||||||
get: jest.fn()
|
get: jest.fn()
|
||||||
|
|
Loading…
Reference in New Issue