2023-01-26 12:55:11 +01:00
|
|
|
const tk = require( "timekeeper")
|
|
|
|
const timestamp = new Date("2023-01-26T11:48:57.597Z").toISOString()
|
|
|
|
tk.freeze(timestamp)
|
|
|
|
|
|
|
|
|
2021-02-16 17:46:18 +01:00
|
|
|
const { outputProcessing } = require("../../../utilities/rowProcessor")
|
2021-03-05 13:11:44 +01:00
|
|
|
const setup = require("./utilities")
|
2021-03-11 19:29:48 +01:00
|
|
|
const { basicRow } = setup.structures
|
2022-11-22 20:49:59 +01:00
|
|
|
const { context, tenancy } = require("@budibase/backend-core")
|
2022-09-28 09:56:45 +02:00
|
|
|
const {
|
|
|
|
quotas,
|
|
|
|
} = require("@budibase/pro")
|
|
|
|
const {
|
|
|
|
QuotaUsageType,
|
|
|
|
StaticQuotaName,
|
|
|
|
MonthlyQuotaName,
|
|
|
|
} = require("@budibase/types")
|
2022-12-15 12:35:22 +01:00
|
|
|
const { structures } = require("@budibase/backend-core/tests");
|
2021-03-26 15:11:24 +01:00
|
|
|
|
2020-10-09 20:10:28 +02:00
|
|
|
describe("/rows", () => {
|
2021-03-05 13:11:44 +01:00
|
|
|
let request = setup.getRequest()
|
|
|
|
let config = setup.getConfig()
|
2020-10-09 19:49:23 +02:00
|
|
|
let table
|
2020-10-09 20:10:28 +02:00
|
|
|
let row
|
2020-04-22 17:35:20 +02:00
|
|
|
|
2021-03-05 13:11:44 +01:00
|
|
|
afterAll(setup.afterAll)
|
2020-04-22 17:35:20 +02:00
|
|
|
|
2023-02-03 18:55:40 +01:00
|
|
|
beforeAll(async () => {
|
2021-03-05 13:11:44 +01:00
|
|
|
await config.init()
|
2023-02-03 18:55:40 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
beforeEach(async()=>{
|
2021-03-04 14:07:33 +01:00
|
|
|
table = await config.createTable()
|
|
|
|
row = basicRow(table._id)
|
2020-05-27 18:23:01 +02:00
|
|
|
})
|
2020-04-24 19:02:51 +02:00
|
|
|
|
2021-03-10 18:55:42 +01:00
|
|
|
const loadRow = async (id, status = 200) =>
|
2020-09-10 10:36:14 +02:00
|
|
|
await request
|
2020-10-09 20:10:28 +02:00
|
|
|
.get(`/api/${table._id}/rows/${id}`)
|
2021-03-04 14:07:33 +01:00
|
|
|
.set(config.defaultHeaders())
|
2022-09-28 09:56:45 +02:00
|
|
|
.expect("Content-Type", /json/)
|
2021-03-10 18:55:42 +01:00
|
|
|
.expect(status)
|
2020-09-10 10:36:14 +02:00
|
|
|
|
2022-05-11 12:32:53 +02:00
|
|
|
const getRowUsage = async () => {
|
2022-09-28 12:57:58 +02:00
|
|
|
const { total } = await config.doInContext(null, () => quotas.getCurrentUsageValues(QuotaUsageType.STATIC, StaticQuotaName.ROWS))
|
|
|
|
return total
|
2022-05-11 12:32:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const getQueryUsage = async () => {
|
2022-09-28 12:57:58 +02:00
|
|
|
const { total } = await config.doInContext(null, () => quotas.getCurrentUsageValues(QuotaUsageType.MONTHLY, MonthlyQuotaName.QUERIES))
|
2022-05-26 18:31:57 +02:00
|
|
|
return total
|
2022-05-11 12:32:53 +02:00
|
|
|
}
|
|
|
|
|
2022-09-28 09:56:45 +02:00
|
|
|
const assertRowUsage = async expected => {
|
2022-05-11 12:32:53 +02:00
|
|
|
const usage = await getRowUsage()
|
|
|
|
expect(usage).toBe(expected)
|
|
|
|
}
|
|
|
|
|
2022-09-28 09:56:45 +02:00
|
|
|
const assertQueryUsage = async expected => {
|
2022-05-11 12:32:53 +02:00
|
|
|
const usage = await getQueryUsage()
|
|
|
|
expect(usage).toBe(expected)
|
|
|
|
}
|
2020-09-10 10:36:14 +02:00
|
|
|
|
2021-03-10 18:55:42 +01:00
|
|
|
describe("save, load, update", () => {
|
2020-10-09 20:10:28 +02:00
|
|
|
it("returns a success message when the row is created", async () => {
|
2022-09-28 13:33:39 +02:00
|
|
|
const rowUsage = await getRowUsage()
|
|
|
|
const queryUsage = await getQueryUsage()
|
|
|
|
|
|
|
|
const res = await request
|
|
|
|
.post(`/api/${row.tableId}/rows`)
|
|
|
|
.send(row)
|
|
|
|
.set(config.defaultHeaders())
|
|
|
|
.expect('Content-Type', /json/)
|
|
|
|
.expect(200)
|
|
|
|
expect(res.res.statusMessage).toEqual(`${table.name} saved successfully`)
|
|
|
|
expect(res.body.name).toEqual("Test Contact")
|
|
|
|
expect(res.body._rev).toBeDefined()
|
|
|
|
await assertRowUsage(rowUsage + 1)
|
|
|
|
await assertQueryUsage(queryUsage + 1)
|
2020-04-22 17:35:20 +02:00
|
|
|
})
|
|
|
|
|
2020-10-09 20:10:28 +02:00
|
|
|
it("updates a row successfully", async () => {
|
2021-03-04 14:07:33 +01:00
|
|
|
const existing = await config.createRow()
|
2022-09-28 13:33:39 +02:00
|
|
|
const rowUsage = await getRowUsage()
|
|
|
|
const queryUsage = await getQueryUsage()
|
2020-04-24 19:02:51 +02:00
|
|
|
|
2020-04-22 17:35:20 +02:00
|
|
|
const res = await request
|
2020-10-09 20:10:28 +02:00
|
|
|
.post(`/api/${table._id}/rows`)
|
2020-04-24 19:02:51 +02:00
|
|
|
.send({
|
2020-05-14 16:12:30 +02:00
|
|
|
_id: existing._id,
|
|
|
|
_rev: existing._rev,
|
2020-10-09 19:49:23 +02:00
|
|
|
tableId: table._id,
|
2020-04-24 19:02:51 +02:00
|
|
|
name: "Updated Name",
|
|
|
|
})
|
2021-03-04 14:07:33 +01:00
|
|
|
.set(config.defaultHeaders())
|
2022-09-28 09:56:45 +02:00
|
|
|
.expect("Content-Type", /json/)
|
2020-04-22 17:35:20 +02:00
|
|
|
.expect(200)
|
2022-09-28 09:56:45 +02:00
|
|
|
|
|
|
|
expect(res.res.statusMessage).toEqual(
|
|
|
|
`${table.name} updated successfully.`
|
|
|
|
)
|
2020-05-14 16:12:30 +02:00
|
|
|
expect(res.body.name).toEqual("Updated Name")
|
2022-09-28 13:33:39 +02:00
|
|
|
await assertRowUsage(rowUsage)
|
|
|
|
await assertQueryUsage(queryUsage + 1)
|
2020-04-22 17:35:20 +02:00
|
|
|
})
|
|
|
|
|
2020-10-09 20:10:28 +02:00
|
|
|
it("should load a row", async () => {
|
2021-03-04 14:07:33 +01:00
|
|
|
const existing = await config.createRow()
|
2022-05-11 12:32:53 +02:00
|
|
|
const queryUsage = await getQueryUsage()
|
2020-04-24 19:02:51 +02:00
|
|
|
|
2020-04-22 17:35:20 +02:00
|
|
|
const res = await request
|
2020-10-09 20:10:28 +02:00
|
|
|
.get(`/api/${table._id}/rows/${existing._id}`)
|
2021-03-04 14:07:33 +01:00
|
|
|
.set(config.defaultHeaders())
|
2022-09-28 09:56:45 +02:00
|
|
|
.expect("Content-Type", /json/)
|
2020-04-22 17:35:20 +02:00
|
|
|
.expect(200)
|
2020-04-24 19:02:51 +02:00
|
|
|
|
|
|
|
expect(res.body).toEqual({
|
2020-10-09 20:10:28 +02:00
|
|
|
...row,
|
2020-05-14 16:12:30 +02:00
|
|
|
_id: existing._id,
|
|
|
|
_rev: existing._rev,
|
2020-10-09 20:10:28 +02:00
|
|
|
type: "row",
|
2023-01-26 12:55:11 +01:00
|
|
|
createdAt: timestamp,
|
|
|
|
updatedAt: timestamp,
|
2020-04-24 19:02:51 +02:00
|
|
|
})
|
2022-05-11 12:32:53 +02:00
|
|
|
await assertQueryUsage(queryUsage + 1)
|
2020-04-22 17:35:20 +02:00
|
|
|
})
|
|
|
|
|
2020-10-09 20:10:28 +02:00
|
|
|
it("should list all rows for given tableId", async () => {
|
|
|
|
const newRow = {
|
2020-10-09 19:49:23 +02:00
|
|
|
tableId: table._id,
|
2020-04-24 19:02:51 +02:00
|
|
|
name: "Second Contact",
|
2022-09-28 09:56:45 +02:00
|
|
|
status: "new",
|
2020-04-24 19:02:51 +02:00
|
|
|
}
|
2021-03-04 14:07:33 +01:00
|
|
|
await config.createRow()
|
|
|
|
await config.createRow(newRow)
|
2022-05-11 12:32:53 +02:00
|
|
|
const queryUsage = await getQueryUsage()
|
2020-04-22 17:35:20 +02:00
|
|
|
|
|
|
|
const res = await request
|
2020-10-09 20:10:28 +02:00
|
|
|
.get(`/api/${table._id}/rows`)
|
2021-03-04 14:07:33 +01:00
|
|
|
.set(config.defaultHeaders())
|
2022-09-28 09:56:45 +02:00
|
|
|
.expect("Content-Type", /json/)
|
2020-04-22 17:35:20 +02:00
|
|
|
.expect(200)
|
|
|
|
|
2020-05-14 16:12:30 +02:00
|
|
|
expect(res.body.length).toBe(2)
|
2020-10-09 20:10:28 +02:00
|
|
|
expect(res.body.find(r => r.name === newRow.name)).toBeDefined()
|
|
|
|
expect(res.body.find(r => r.name === row.name)).toBeDefined()
|
2022-05-11 12:32:53 +02:00
|
|
|
await assertQueryUsage(queryUsage + 1)
|
2020-04-22 17:35:20 +02:00
|
|
|
})
|
|
|
|
|
2020-10-09 20:10:28 +02:00
|
|
|
it("load should return 404 when row does not exist", async () => {
|
2021-03-04 14:07:33 +01:00
|
|
|
await config.createRow()
|
2022-05-11 12:32:53 +02:00
|
|
|
const queryUsage = await getQueryUsage()
|
|
|
|
|
2020-05-27 18:23:01 +02:00
|
|
|
await request
|
2020-10-09 20:10:28 +02:00
|
|
|
.get(`/api/${table._id}/rows/not-a-valid-id`)
|
2021-03-04 14:07:33 +01:00
|
|
|
.set(config.defaultHeaders())
|
2022-09-28 09:56:45 +02:00
|
|
|
.expect("Content-Type", /json/)
|
2020-04-22 17:35:20 +02:00
|
|
|
.expect(404)
|
2022-05-11 12:32:53 +02:00
|
|
|
await assertQueryUsage(queryUsage) // no change
|
2020-04-22 17:35:20 +02:00
|
|
|
})
|
2020-10-05 18:28:23 +02:00
|
|
|
|
2020-10-09 20:10:28 +02:00
|
|
|
it("row values are coerced", async () => {
|
2022-09-28 09:56:45 +02:00
|
|
|
const str = {
|
|
|
|
type: "string",
|
|
|
|
constraints: { type: "string", presence: false },
|
|
|
|
}
|
|
|
|
const attachment = {
|
|
|
|
type: "attachment",
|
|
|
|
constraints: { type: "array", presence: false },
|
|
|
|
}
|
|
|
|
const bool = {
|
|
|
|
type: "boolean",
|
|
|
|
constraints: { type: "boolean", presence: false },
|
|
|
|
}
|
|
|
|
const number = {
|
|
|
|
type: "number",
|
|
|
|
constraints: { type: "number", presence: false },
|
|
|
|
}
|
|
|
|
const datetime = {
|
|
|
|
type: "datetime",
|
|
|
|
constraints: {
|
|
|
|
type: "string",
|
|
|
|
presence: false,
|
|
|
|
datetime: { earliest: "", latest: "" },
|
|
|
|
},
|
|
|
|
}
|
2020-10-05 18:28:23 +02:00
|
|
|
|
2021-03-04 14:07:33 +01:00
|
|
|
table = await config.createTable({
|
2020-10-09 19:49:23 +02:00
|
|
|
name: "TestTable2",
|
|
|
|
type: "table",
|
2020-10-05 18:28:23 +02:00
|
|
|
key: "name",
|
|
|
|
schema: {
|
|
|
|
name: str,
|
|
|
|
stringUndefined: str,
|
|
|
|
stringNull: str,
|
|
|
|
stringString: str,
|
|
|
|
numberEmptyString: number,
|
|
|
|
numberNull: number,
|
|
|
|
numberUndefined: number,
|
|
|
|
numberString: number,
|
2021-06-07 15:08:49 +02:00
|
|
|
numberNumber: number,
|
2020-10-05 18:28:23 +02:00
|
|
|
datetimeEmptyString: datetime,
|
|
|
|
datetimeNull: datetime,
|
|
|
|
datetimeUndefined: datetime,
|
|
|
|
datetimeString: datetime,
|
|
|
|
datetimeDate: datetime,
|
|
|
|
boolNull: bool,
|
|
|
|
boolEmpty: bool,
|
|
|
|
boolUndefined: bool,
|
|
|
|
boolString: bool,
|
|
|
|
boolBool: bool,
|
2022-09-28 09:56:45 +02:00
|
|
|
attachmentNull: attachment,
|
|
|
|
attachmentUndefined: attachment,
|
|
|
|
attachmentEmpty: attachment,
|
2023-05-04 13:58:45 +02:00
|
|
|
attachmentEmptyArrayStr: attachment
|
2020-10-05 18:28:23 +02:00
|
|
|
},
|
|
|
|
})
|
|
|
|
|
2020-10-09 20:10:28 +02:00
|
|
|
row = {
|
|
|
|
name: "Test Row",
|
2020-10-05 18:28:23 +02:00
|
|
|
stringUndefined: undefined,
|
|
|
|
stringNull: null,
|
|
|
|
stringString: "i am a string",
|
|
|
|
numberEmptyString: "",
|
|
|
|
numberNull: null,
|
|
|
|
numberUndefined: undefined,
|
|
|
|
numberString: "123",
|
|
|
|
numberNumber: 123,
|
|
|
|
datetimeEmptyString: "",
|
|
|
|
datetimeNull: null,
|
|
|
|
datetimeUndefined: undefined,
|
|
|
|
datetimeString: "1984-04-20T00:00:00.000Z",
|
|
|
|
datetimeDate: new Date("1984-04-20"),
|
|
|
|
boolNull: null,
|
|
|
|
boolEmpty: "",
|
|
|
|
boolUndefined: undefined,
|
|
|
|
boolString: "true",
|
|
|
|
boolBool: true,
|
2020-10-09 19:49:23 +02:00
|
|
|
tableId: table._id,
|
2022-09-28 09:56:45 +02:00
|
|
|
attachmentNull: null,
|
|
|
|
attachmentUndefined: undefined,
|
|
|
|
attachmentEmpty: "",
|
2023-05-04 13:58:45 +02:00
|
|
|
attachmentEmptyArrayStr: "[]",
|
2020-10-05 18:28:23 +02:00
|
|
|
}
|
|
|
|
|
2021-03-04 14:07:33 +01:00
|
|
|
const id = (await config.createRow(row))._id
|
2020-10-05 18:28:23 +02:00
|
|
|
|
2020-10-09 20:10:28 +02:00
|
|
|
const saved = (await loadRow(id)).body
|
2020-10-05 18:28:23 +02:00
|
|
|
|
|
|
|
expect(saved.stringUndefined).toBe(undefined)
|
|
|
|
expect(saved.stringNull).toBe("")
|
|
|
|
expect(saved.stringString).toBe("i am a string")
|
|
|
|
expect(saved.numberEmptyString).toBe(null)
|
|
|
|
expect(saved.numberNull).toBe(null)
|
|
|
|
expect(saved.numberUndefined).toBe(undefined)
|
|
|
|
expect(saved.numberString).toBe(123)
|
|
|
|
expect(saved.numberNumber).toBe(123)
|
|
|
|
expect(saved.datetimeEmptyString).toBe(null)
|
|
|
|
expect(saved.datetimeNull).toBe(null)
|
|
|
|
expect(saved.datetimeUndefined).toBe(undefined)
|
2022-09-28 09:56:45 +02:00
|
|
|
expect(saved.datetimeString).toBe(
|
|
|
|
new Date(row.datetimeString).toISOString()
|
|
|
|
)
|
2020-10-09 20:10:28 +02:00
|
|
|
expect(saved.datetimeDate).toBe(row.datetimeDate.toISOString())
|
2020-10-05 18:28:23 +02:00
|
|
|
expect(saved.boolNull).toBe(null)
|
|
|
|
expect(saved.boolEmpty).toBe(null)
|
|
|
|
expect(saved.boolUndefined).toBe(undefined)
|
|
|
|
expect(saved.boolString).toBe(true)
|
|
|
|
expect(saved.boolBool).toBe(true)
|
|
|
|
expect(saved.attachmentNull).toEqual([])
|
|
|
|
expect(saved.attachmentUndefined).toBe(undefined)
|
|
|
|
expect(saved.attachmentEmpty).toEqual([])
|
2023-05-04 13:58:45 +02:00
|
|
|
expect(saved.attachmentEmptyArrayStr).toEqual([])
|
2020-10-05 18:28:23 +02:00
|
|
|
})
|
2020-04-22 17:35:20 +02:00
|
|
|
})
|
2020-05-28 16:39:29 +02:00
|
|
|
|
2020-09-10 10:36:14 +02:00
|
|
|
describe("patch", () => {
|
|
|
|
it("should update only the fields that are supplied", async () => {
|
2021-03-04 14:07:33 +01:00
|
|
|
const existing = await config.createRow()
|
2020-09-10 10:36:14 +02:00
|
|
|
|
2022-05-11 12:32:53 +02:00
|
|
|
const rowUsage = await getRowUsage()
|
|
|
|
const queryUsage = await getQueryUsage()
|
|
|
|
|
2020-09-10 10:36:14 +02:00
|
|
|
const res = await request
|
2021-06-14 20:05:39 +02:00
|
|
|
.patch(`/api/${table._id}/rows`)
|
2020-09-10 10:36:14 +02:00
|
|
|
.send({
|
|
|
|
_id: existing._id,
|
|
|
|
_rev: existing._rev,
|
2020-10-09 19:49:23 +02:00
|
|
|
tableId: table._id,
|
2020-09-10 10:36:14 +02:00
|
|
|
name: "Updated Name",
|
|
|
|
})
|
2021-03-04 14:07:33 +01:00
|
|
|
.set(config.defaultHeaders())
|
2022-09-28 09:56:45 +02:00
|
|
|
.expect("Content-Type", /json/)
|
2020-09-10 10:36:14 +02:00
|
|
|
.expect(200)
|
2022-09-28 09:56:45 +02:00
|
|
|
|
|
|
|
expect(res.res.statusMessage).toEqual(
|
|
|
|
`${table.name} updated successfully.`
|
|
|
|
)
|
2020-09-10 10:36:14 +02:00
|
|
|
expect(res.body.name).toEqual("Updated Name")
|
2020-09-11 10:29:23 +02:00
|
|
|
expect(res.body.description).toEqual(existing.description)
|
2020-09-10 10:36:14 +02:00
|
|
|
|
2020-10-09 20:10:28 +02:00
|
|
|
const savedRow = await loadRow(res.body._id)
|
2020-09-10 10:36:14 +02:00
|
|
|
|
2020-10-09 20:10:28 +02:00
|
|
|
expect(savedRow.body.description).toEqual(existing.description)
|
|
|
|
expect(savedRow.body.name).toEqual("Updated Name")
|
2022-05-11 12:32:53 +02:00
|
|
|
await assertRowUsage(rowUsage)
|
|
|
|
await assertQueryUsage(queryUsage + 2) // account for the second load
|
2021-03-10 18:55:42 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
it("should throw an error when given improper types", async () => {
|
|
|
|
const existing = await config.createRow()
|
2022-05-11 12:32:53 +02:00
|
|
|
const rowUsage = await getRowUsage()
|
|
|
|
const queryUsage = await getQueryUsage()
|
|
|
|
|
2021-03-10 18:55:42 +01:00
|
|
|
await request
|
2021-06-14 20:05:39 +02:00
|
|
|
.patch(`/api/${table._id}/rows`)
|
2021-03-10 18:55:42 +01:00
|
|
|
.send({
|
|
|
|
_id: existing._id,
|
|
|
|
_rev: existing._rev,
|
|
|
|
tableId: table._id,
|
|
|
|
name: 1,
|
|
|
|
})
|
|
|
|
.set(config.defaultHeaders())
|
|
|
|
.expect(400)
|
2022-05-11 12:32:53 +02:00
|
|
|
|
|
|
|
await assertRowUsage(rowUsage)
|
|
|
|
await assertQueryUsage(queryUsage)
|
2021-03-10 18:55:42 +01:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
describe("destroy", () => {
|
|
|
|
it("should be able to delete a row", async () => {
|
|
|
|
const createdRow = await config.createRow(row)
|
2022-05-11 12:32:53 +02:00
|
|
|
const rowUsage = await getRowUsage()
|
|
|
|
const queryUsage = await getQueryUsage()
|
|
|
|
|
2021-03-10 18:55:42 +01:00
|
|
|
const res = await request
|
2021-06-17 17:52:52 +02:00
|
|
|
.delete(`/api/${table._id}/rows`)
|
|
|
|
.send({
|
2022-09-28 09:56:45 +02:00
|
|
|
rows: [createdRow],
|
2021-06-17 17:52:52 +02:00
|
|
|
})
|
2021-03-10 18:55:42 +01:00
|
|
|
.set(config.defaultHeaders())
|
2022-09-28 09:56:45 +02:00
|
|
|
.expect("Content-Type", /json/)
|
2021-03-10 18:55:42 +01:00
|
|
|
.expect(200)
|
2021-06-17 17:52:52 +02:00
|
|
|
expect(res.body[0]._id).toEqual(createdRow._id)
|
2022-09-28 09:56:45 +02:00
|
|
|
await assertRowUsage(rowUsage - 1)
|
|
|
|
await assertQueryUsage(queryUsage + 1)
|
2020-09-10 10:36:14 +02:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2020-05-28 16:39:29 +02:00
|
|
|
describe("validate", () => {
|
2020-10-09 20:10:28 +02:00
|
|
|
it("should return no errors on valid row", async () => {
|
2022-05-11 12:32:53 +02:00
|
|
|
const rowUsage = await getRowUsage()
|
|
|
|
const queryUsage = await getQueryUsage()
|
|
|
|
|
2021-03-10 18:55:42 +01:00
|
|
|
const res = await request
|
2020-10-09 20:10:28 +02:00
|
|
|
.post(`/api/${table._id}/rows/validate`)
|
2020-05-28 16:39:29 +02:00
|
|
|
.send({ name: "ivan" })
|
2021-03-04 14:07:33 +01:00
|
|
|
.set(config.defaultHeaders())
|
2022-09-28 09:56:45 +02:00
|
|
|
.expect("Content-Type", /json/)
|
2020-05-28 16:39:29 +02:00
|
|
|
.expect(200)
|
2022-09-28 09:56:45 +02:00
|
|
|
|
2021-03-10 18:55:42 +01:00
|
|
|
expect(res.body.valid).toBe(true)
|
|
|
|
expect(Object.keys(res.body.errors)).toEqual([])
|
2022-05-11 12:32:53 +02:00
|
|
|
await assertRowUsage(rowUsage)
|
|
|
|
await assertQueryUsage(queryUsage)
|
2020-05-28 16:39:29 +02:00
|
|
|
})
|
|
|
|
|
2020-10-09 20:10:28 +02:00
|
|
|
it("should errors on invalid row", async () => {
|
2022-05-11 12:32:53 +02:00
|
|
|
const rowUsage = await getRowUsage()
|
|
|
|
const queryUsage = await getQueryUsage()
|
|
|
|
|
2021-03-10 18:55:42 +01:00
|
|
|
const res = await request
|
2020-10-09 20:10:28 +02:00
|
|
|
.post(`/api/${table._id}/rows/validate`)
|
2020-05-28 16:39:29 +02:00
|
|
|
.send({ name: 1 })
|
2021-03-04 14:07:33 +01:00
|
|
|
.set(config.defaultHeaders())
|
2022-09-28 09:56:45 +02:00
|
|
|
.expect("Content-Type", /json/)
|
2020-05-28 16:39:29 +02:00
|
|
|
.expect(200)
|
2022-09-28 09:56:45 +02:00
|
|
|
|
2021-03-10 18:55:42 +01:00
|
|
|
expect(res.body.valid).toBe(false)
|
|
|
|
expect(Object.keys(res.body.errors)).toEqual(["name"])
|
2022-05-11 12:32:53 +02:00
|
|
|
await assertRowUsage(rowUsage)
|
|
|
|
await assertQueryUsage(queryUsage)
|
2020-05-28 16:39:29 +02:00
|
|
|
})
|
|
|
|
})
|
2021-02-02 12:46:10 +01:00
|
|
|
|
2021-03-10 18:55:42 +01:00
|
|
|
describe("bulkDelete", () => {
|
|
|
|
it("should be able to delete a bulk set of rows", async () => {
|
|
|
|
const row1 = await config.createRow()
|
|
|
|
const row2 = await config.createRow()
|
2022-05-11 12:32:53 +02:00
|
|
|
const rowUsage = await getRowUsage()
|
|
|
|
const queryUsage = await getQueryUsage()
|
|
|
|
|
2021-03-10 18:55:42 +01:00
|
|
|
const res = await request
|
2021-06-17 17:52:52 +02:00
|
|
|
.delete(`/api/${table._id}/rows`)
|
2021-03-10 18:55:42 +01:00
|
|
|
.send({
|
2022-09-28 09:56:45 +02:00
|
|
|
rows: [row1, row2],
|
2021-03-10 18:55:42 +01:00
|
|
|
})
|
|
|
|
.set(config.defaultHeaders())
|
2022-09-28 09:56:45 +02:00
|
|
|
.expect("Content-Type", /json/)
|
2021-03-10 18:55:42 +01:00
|
|
|
.expect(200)
|
2022-05-11 12:32:53 +02:00
|
|
|
|
2021-03-10 18:55:42 +01:00
|
|
|
expect(res.body.length).toEqual(2)
|
|
|
|
await loadRow(row1._id, 404)
|
2022-05-11 12:32:53 +02:00
|
|
|
await assertRowUsage(rowUsage - 2)
|
2022-09-28 09:56:45 +02:00
|
|
|
await assertQueryUsage(queryUsage + 1)
|
2021-03-10 18:55:42 +01:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
describe("fetchView", () => {
|
|
|
|
it("should be able to fetch tables contents via 'view'", async () => {
|
|
|
|
const row = await config.createRow()
|
2022-05-11 12:32:53 +02:00
|
|
|
const rowUsage = await getRowUsage()
|
|
|
|
const queryUsage = await getQueryUsage()
|
|
|
|
|
2021-03-10 18:55:42 +01:00
|
|
|
const res = await request
|
2021-06-15 14:32:11 +02:00
|
|
|
.get(`/api/views/${table._id}`)
|
2021-03-10 18:55:42 +01:00
|
|
|
.set(config.defaultHeaders())
|
2022-09-28 09:56:45 +02:00
|
|
|
.expect("Content-Type", /json/)
|
2021-03-10 18:55:42 +01:00
|
|
|
.expect(200)
|
|
|
|
expect(res.body.length).toEqual(1)
|
|
|
|
expect(res.body[0]._id).toEqual(row._id)
|
2022-05-11 12:32:53 +02:00
|
|
|
await assertRowUsage(rowUsage)
|
2022-09-28 09:56:45 +02:00
|
|
|
await assertQueryUsage(queryUsage + 1)
|
2021-03-10 18:55:42 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
it("should throw an error if view doesn't exist", async () => {
|
2022-05-11 12:32:53 +02:00
|
|
|
const rowUsage = await getRowUsage()
|
|
|
|
const queryUsage = await getQueryUsage()
|
|
|
|
|
2021-03-10 18:55:42 +01:00
|
|
|
await request
|
|
|
|
.get(`/api/views/derp`)
|
|
|
|
.set(config.defaultHeaders())
|
2021-09-30 13:55:21 +02:00
|
|
|
.expect(404)
|
2022-05-11 12:32:53 +02:00
|
|
|
|
|
|
|
await assertRowUsage(rowUsage)
|
|
|
|
await assertQueryUsage(queryUsage)
|
2021-03-10 18:55:42 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
it("should be able to run on a view", async () => {
|
|
|
|
const view = await config.createView()
|
|
|
|
const row = await config.createRow()
|
2022-05-11 12:32:53 +02:00
|
|
|
const rowUsage = await getRowUsage()
|
|
|
|
const queryUsage = await getQueryUsage()
|
|
|
|
|
2021-03-10 18:55:42 +01:00
|
|
|
const res = await request
|
2021-03-15 17:36:38 +01:00
|
|
|
.get(`/api/views/${view.name}`)
|
2021-03-10 18:55:42 +01:00
|
|
|
.set(config.defaultHeaders())
|
2022-09-28 09:56:45 +02:00
|
|
|
.expect("Content-Type", /json/)
|
2021-03-10 18:55:42 +01:00
|
|
|
.expect(200)
|
|
|
|
expect(res.body.length).toEqual(1)
|
|
|
|
expect(res.body[0]._id).toEqual(row._id)
|
|
|
|
|
2022-05-11 12:32:53 +02:00
|
|
|
await assertRowUsage(rowUsage)
|
|
|
|
await assertQueryUsage(queryUsage + 1)
|
|
|
|
})
|
2021-03-10 18:55:42 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
describe("fetchEnrichedRows", () => {
|
2021-02-02 12:46:10 +01:00
|
|
|
it("should allow enriching some linked rows", async () => {
|
2022-11-22 20:49:59 +01:00
|
|
|
const { table, firstRow, secondRow } = await tenancy.doInTenant(
|
2022-09-28 09:56:45 +02:00
|
|
|
setup.structures.TENANT_ID,
|
|
|
|
async () => {
|
|
|
|
const table = await config.createLinkedTable()
|
|
|
|
const firstRow = await config.createRow({
|
|
|
|
name: "Test Contact",
|
|
|
|
description: "original description",
|
|
|
|
tableId: table._id,
|
|
|
|
})
|
|
|
|
const secondRow = await config.createRow({
|
|
|
|
name: "Test 2",
|
|
|
|
description: "og desc",
|
|
|
|
link: [{ _id: firstRow._id }],
|
|
|
|
tableId: table._id,
|
|
|
|
})
|
|
|
|
return { table, firstRow, secondRow }
|
|
|
|
}
|
|
|
|
)
|
2022-05-11 12:32:53 +02:00
|
|
|
const rowUsage = await getRowUsage()
|
|
|
|
const queryUsage = await getQueryUsage()
|
2021-03-10 18:55:42 +01:00
|
|
|
|
|
|
|
// test basic enrichment
|
|
|
|
const resBasic = await request
|
|
|
|
.get(`/api/${table._id}/rows/${secondRow._id}`)
|
|
|
|
.set(config.defaultHeaders())
|
2022-09-28 09:56:45 +02:00
|
|
|
.expect("Content-Type", /json/)
|
2021-03-10 18:55:42 +01:00
|
|
|
.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())
|
2022-09-28 09:56:45 +02:00
|
|
|
.expect("Content-Type", /json/)
|
2021-03-10 18:55:42 +01:00
|
|
|
.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")
|
2022-05-11 12:32:53 +02:00
|
|
|
await assertRowUsage(rowUsage)
|
2022-09-28 09:56:45 +02:00
|
|
|
await assertQueryUsage(queryUsage + 2)
|
2021-02-02 12:46:10 +01:00
|
|
|
})
|
|
|
|
})
|
|
|
|
|
2021-03-10 18:55:42 +01:00
|
|
|
describe("attachments", () => {
|
|
|
|
it("should allow enriching attachment rows", async () => {
|
|
|
|
const table = await config.createAttachmentTable()
|
2022-12-15 12:35:22 +01:00
|
|
|
const attachmentId = `${structures.uuid()}.csv`
|
2021-03-10 18:55:42 +01:00
|
|
|
const row = await config.createRow({
|
|
|
|
name: "test",
|
|
|
|
description: "test",
|
2022-09-28 09:56:45 +02:00
|
|
|
attachment: [
|
|
|
|
{
|
2022-12-15 12:35:22 +01:00
|
|
|
key: `${config.getAppId()}/attachments/${attachmentId}`,
|
2022-09-28 09:56:45 +02:00
|
|
|
},
|
|
|
|
],
|
2021-03-10 18:55:42 +01:00
|
|
|
tableId: table._id,
|
|
|
|
})
|
|
|
|
// the environment needs configured for this
|
2021-03-24 19:21:23 +01:00
|
|
|
await setup.switchToSelfHosted(async () => {
|
2022-11-22 20:49:59 +01:00
|
|
|
context.doInAppContext(config.getAppId(), async () => {
|
2022-01-31 18:00:22 +01:00
|
|
|
const enriched = await outputProcessing(table, [row])
|
|
|
|
expect(enriched[0].attachment[0].url).toBe(
|
2022-12-15 12:35:22 +01:00
|
|
|
`/files/signed/prod-budi-app-assets/${config.getProdAppId()}/attachments/${attachmentId}`
|
2022-01-31 18:00:22 +01:00
|
|
|
)
|
|
|
|
})
|
2021-03-10 18:55:42 +01:00
|
|
|
})
|
2021-03-04 14:07:33 +01:00
|
|
|
})
|
2021-02-02 12:46:10 +01:00
|
|
|
})
|
2022-09-28 09:56:45 +02:00
|
|
|
|
|
|
|
describe("exportData", () => {
|
|
|
|
it("should allow exporting all columns", async () => {
|
|
|
|
const existing = await config.createRow()
|
|
|
|
const res = await request
|
|
|
|
.post(`/api/${table._id}/rows/exportRows?format=json`)
|
|
|
|
.set(config.defaultHeaders())
|
|
|
|
.send({
|
|
|
|
rows: [existing._id],
|
|
|
|
})
|
|
|
|
.expect("Content-Type", /json/)
|
|
|
|
.expect(200)
|
|
|
|
const results = JSON.parse(res.text)
|
|
|
|
expect(results.length).toEqual(1)
|
|
|
|
const row = results[0]
|
|
|
|
|
|
|
|
// Ensure all original columns were exported
|
|
|
|
expect(Object.keys(row).length).toBeGreaterThanOrEqual(
|
|
|
|
Object.keys(existing).length
|
|
|
|
)
|
|
|
|
Object.keys(existing).forEach(key => {
|
|
|
|
expect(row[key]).toEqual(existing[key])
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
it("should allow exporting only certain columns", async () => {
|
|
|
|
const existing = await config.createRow()
|
|
|
|
const res = await request
|
|
|
|
.post(`/api/${table._id}/rows/exportRows?format=json`)
|
|
|
|
.set(config.defaultHeaders())
|
|
|
|
.send({
|
|
|
|
rows: [existing._id],
|
|
|
|
columns: ["_id"],
|
|
|
|
})
|
|
|
|
.expect("Content-Type", /json/)
|
|
|
|
.expect(200)
|
|
|
|
const results = JSON.parse(res.text)
|
|
|
|
expect(results.length).toEqual(1)
|
|
|
|
const row = results[0]
|
|
|
|
|
|
|
|
// Ensure only the _id column was exported
|
|
|
|
expect(Object.keys(row).length).toEqual(1)
|
|
|
|
expect(row._id).toEqual(existing._id)
|
|
|
|
})
|
|
|
|
})
|
2021-09-30 13:55:21 +02:00
|
|
|
})
|