budibase/packages/server/src/integration-test/postgres.spec.ts

681 lines
18 KiB
TypeScript
Raw Normal View History

2023-01-17 18:22:31 +01:00
import {
generateMakeRequest,
MakeRequestResponse,
} from "../api/routes/public/tests/utils"
import * as setup from "../api/routes/tests/utilities"
2023-01-19 21:09:39 +01:00
import {
Datasource,
FieldType,
RelationshipTypes,
Row,
SourceName,
Table,
} from "@budibase/types"
2023-01-18 18:07:09 +01:00
import _ from "lodash"
import { generator } from "@budibase/backend-core/tests"
2023-02-02 11:43:18 +01:00
import { utils } from "@budibase/backend-core"
2023-02-06 21:12:08 +01:00
import { GenericContainer } from "testcontainers"
2023-01-17 18:22:31 +01:00
2023-01-20 12:48:11 +01:00
const config = setup.getConfig()!
2023-01-18 14:55:24 +01:00
2023-02-06 21:12:08 +01:00
jest.setTimeout(30000)
2023-02-06 15:54:49 +01:00
jest.unmock("pg")
2023-01-19 12:00:51 +01:00
2023-02-02 11:43:18 +01:00
describe("row api - postgres", () => {
2023-02-06 15:54:49 +01:00
let makeRequest: MakeRequestResponse,
2023-01-18 18:07:09 +01:00
postgresDatasource: Datasource,
2023-02-07 11:46:34 +01:00
primaryPostgresTable: Table,
2023-01-19 21:09:39 +01:00
auxPostgresTable: Table
2023-01-18 18:07:09 +01:00
let host: string
let port: number
2023-02-02 11:43:18 +01:00
2023-02-06 15:54:49 +01:00
beforeAll(async () => {
2023-02-06 21:12:08 +01:00
const container = await new GenericContainer("postgres")
.withExposedPorts(5432)
.withEnv("POSTGRES_PASSWORD", "password")
.start()
2023-02-06 21:12:08 +01:00
host = container.getContainerIpAddress()
port = container.getMappedPort(5432)
2023-01-18 18:07:09 +01:00
await config.init()
2023-02-06 15:54:49 +01:00
const apiKey = await config.generateApiKey()
makeRequest = generateMakeRequest(apiKey, true)
})
beforeEach(async () => {
2023-01-18 18:07:09 +01:00
postgresDatasource = await config.createDatasource({
2023-01-20 12:48:11 +01:00
datasource: {
type: "datasource",
source: SourceName.POSTGRES,
plus: true,
config: {
2023-02-02 11:43:18 +01:00
host,
port,
2023-01-20 12:48:11 +01:00
database: "postgres",
2023-02-06 15:54:49 +01:00
user: "postgres",
2023-02-07 11:12:42 +01:00
password: "password",
2023-01-20 12:48:11 +01:00
schema: "public",
ssl: false,
rejectUnauthorized: false,
ca: false,
},
2023-01-18 18:07:09 +01:00
},
})
2023-01-18 17:46:40 +01:00
2023-02-06 15:54:49 +01:00
auxPostgresTable = await config.createTable({
name: generator.word({ length: 10 }),
type: "external",
primary: ["id"],
schema: {
id: {
name: "id",
type: FieldType.AUTO,
constraints: {
presence: true,
},
},
title: {
name: "title",
type: FieldType.STRING,
constraints: {
presence: true,
},
},
},
sourceId: postgresDatasource._id,
})
2023-01-18 18:07:09 +01:00
2023-02-07 11:46:34 +01:00
primaryPostgresTable = await config.createTable({
2023-02-06 15:54:49 +01:00
name: generator.word({ length: 10 }),
type: "external",
primary: ["id"],
2023-01-18 18:07:09 +01:00
schema: {
2023-02-06 15:54:49 +01:00
id: {
name: "id",
type: FieldType.AUTO,
constraints: {
presence: true,
},
},
2023-01-18 18:07:09 +01:00
name: {
name: "name",
type: FieldType.STRING,
constraints: {
presence: true,
},
},
description: {
name: "description",
type: FieldType.STRING,
},
value: {
name: "value",
type: FieldType.NUMBER,
2023-01-18 17:46:40 +01:00
},
2023-01-19 21:09:39 +01:00
linkedField: {
type: FieldType.LINK,
constraints: {
type: "array",
2023-02-06 15:54:49 +01:00
presence: false,
2023-01-19 21:09:39 +01:00
},
fieldName: "foreignField",
name: "linkedField",
2023-02-06 15:54:49 +01:00
relationshipType: RelationshipTypes.ONE_TO_MANY,
tableId: auxPostgresTable._id,
2023-01-19 21:09:39 +01:00
},
},
sourceId: postgresDatasource._id,
})
2023-01-18 17:46:40 +01:00
})
2023-01-17 18:22:31 +01:00
2023-01-18 18:07:09 +01:00
afterAll(async () => {
await config.end()
})
2023-02-07 11:46:34 +01:00
function generateRandomPrimaryRowData() {
2023-01-18 18:07:09 +01:00
return {
2023-02-02 11:43:18 +01:00
name: generator.name(),
description: generator.paragraph(),
2023-02-06 18:30:33 +01:00
value: generator.age(),
2023-01-18 18:07:09 +01:00
}
}
2023-01-17 18:22:31 +01:00
2023-02-07 11:46:34 +01:00
async function createPrimaryRow(opts: {
rowData: {
2023-01-19 12:35:00 +01:00
name: string
description: string
value: number
2023-02-07 11:46:34 +01:00
}
2023-02-06 15:54:49 +01:00
createForeignRow?: boolean
2023-02-07 11:46:34 +01:00
}) {
let { rowData } = opts
let foreignRow: Row | undefined
if (opts?.createForeignRow) {
foreignRow = await config.createRow({
2023-02-06 15:54:49 +01:00
tableId: auxPostgresTable._id,
title: generator.name(),
})
2023-02-07 11:46:34 +01:00
rowData = {
...rowData,
2023-02-06 15:54:49 +01:00
[`fk_${auxPostgresTable.name}_foreignField`]: foreignRow.id,
}
}
2023-02-07 11:46:34 +01:00
const row = await config.createRow({
tableId: primaryPostgresTable._id,
...rowData,
2023-01-19 12:35:00 +01:00
})
2023-02-07 11:46:34 +01:00
return { row, foreignRow }
2023-01-19 12:35:00 +01:00
}
2023-02-06 15:54:49 +01:00
async function createDefaultPgTable() {
return await config.createTable({
name: generator.word({ length: 10 }),
type: "external",
primary: ["id"],
schema: {
id: {
name: "id",
type: FieldType.AUTO,
constraints: {
presence: true,
},
},
},
sourceId: postgresDatasource._id,
})
}
2023-02-07 11:46:34 +01:00
async function populatePrimaryRows(count: number) {
2023-01-18 18:07:09 +01:00
return await Promise.all(
Array(count)
.fill({})
.map(async () => {
2023-02-07 11:46:34 +01:00
const rowData = generateRandomPrimaryRowData()
2023-01-18 18:07:09 +01:00
return {
rowData,
2023-02-07 11:46:34 +01:00
...(await createPrimaryRow({
rowData,
})),
2023-01-18 18:07:09 +01:00
}
})
)
2023-01-18 17:46:40 +01:00
}
2023-02-07 11:46:34 +01:00
it("validate table schema", async () => {
2023-01-19 17:21:37 +01:00
const res = await makeRequest(
"get",
2023-01-19 17:43:39 +01:00
`/api/datasources/${postgresDatasource._id}`
2023-01-19 17:21:37 +01:00
)
expect(res.status).toBe(200)
2023-01-19 17:43:39 +01:00
expect(res.body).toEqual({
config: {
ca: false,
database: "postgres",
2023-02-02 11:43:18 +01:00
host,
password: "--secret-value--",
port,
2023-01-19 17:43:39 +01:00
rejectUnauthorized: false,
schema: "public",
ssl: false,
2023-02-06 15:54:49 +01:00
user: "postgres",
2023-01-19 17:43:39 +01:00
},
plus: true,
source: "POSTGRES",
type: "datasource",
_id: expect.any(String),
_rev: expect.any(String),
createdAt: expect.any(String),
updatedAt: expect.any(String),
2023-02-06 15:54:49 +01:00
entities: expect.any(Object),
2023-01-19 17:43:39 +01:00
})
2023-01-19 17:21:37 +01:00
})
2023-02-07 11:46:34 +01:00
describe("POST /api/:tableId/rows", () => {
2023-01-19 18:23:48 +01:00
const createRow = (tableId: string | undefined, body: object) =>
makeRequest("post", `/api/${tableId}/rows`, body)
2023-02-07 11:46:34 +01:00
it("Given than no row exists, adding a new one persists it", async () => {
const newRow = generateRandomPrimaryRowData()
2023-01-17 18:22:31 +01:00
2023-02-07 11:46:34 +01:00
const res = await createRow(primaryPostgresTable._id, newRow)
2023-01-17 18:22:31 +01:00
expect(res.status).toBe(200)
2023-01-17 18:39:59 +01:00
2023-02-07 11:46:34 +01:00
const persistedRows = await config.getRows(primaryPostgresTable._id!)
2023-01-17 18:39:59 +01:00
expect(persistedRows).toHaveLength(1)
2023-02-06 15:54:49 +01:00
const expected = {
...res.body,
...newRow,
}
expect(persistedRows).toEqual([expect.objectContaining(expected)])
2023-01-17 18:22:31 +01:00
})
2023-01-18 13:26:26 +01:00
2023-02-07 11:46:34 +01:00
it("Given than no row exists, multiple rows can be persisted", async () => {
2023-01-18 13:26:26 +01:00
const numberOfRows = 10
2023-02-07 11:46:34 +01:00
const newRows = Array(numberOfRows).fill(generateRandomPrimaryRowData())
2023-01-18 13:26:26 +01:00
for (const newRow of newRows) {
2023-02-07 11:46:34 +01:00
const res = await createRow(primaryPostgresTable._id, newRow)
2023-01-18 13:26:26 +01:00
expect(res.status).toBe(200)
}
2023-02-07 11:46:34 +01:00
const persistedRows = await config.getRows(primaryPostgresTable._id!)
2023-01-18 13:26:26 +01:00
expect(persistedRows).toHaveLength(numberOfRows)
2023-01-18 17:06:45 +01:00
expect(persistedRows).toEqual(
expect.arrayContaining(newRows.map(expect.objectContaining))
)
2023-01-18 13:26:26 +01:00
})
2023-01-17 18:22:31 +01:00
})
2023-01-18 17:46:40 +01:00
2023-02-07 11:46:34 +01:00
describe("PATCH /api/:tableId/rows", () => {
2023-01-19 18:23:48 +01:00
const updateRow = (tableId: string | undefined, body: Row) =>
makeRequest("patch", `/api/${tableId}/rows`, body)
2023-02-07 11:46:34 +01:00
it("Given than a row exists, updating it persists it", async () => {
let { row } = _.sample(await populatePrimaryRows(10))!
2023-01-18 18:11:52 +01:00
2023-02-02 11:43:18 +01:00
const newName = generator.name()
2023-02-06 18:30:33 +01:00
const newValue = generator.age()
2023-01-19 18:23:48 +01:00
const updatedRow = {
...row,
2023-01-18 18:11:52 +01:00
name: newName,
value: newValue,
}
2023-02-07 11:46:34 +01:00
const res = await updateRow(primaryPostgresTable._id, updatedRow)
2023-01-18 18:11:52 +01:00
expect(res.status).toBe(200)
expect(res.body).toEqual(updatedRow)
2023-01-18 18:11:52 +01:00
2023-02-07 11:46:34 +01:00
const persistedRow = await config.getRow(
primaryPostgresTable._id!,
row.id
)
2023-01-18 18:11:52 +01:00
2023-01-18 18:21:17 +01:00
expect(persistedRow).toEqual(
2023-01-18 18:11:52 +01:00
expect.objectContaining({
2023-02-06 15:54:49 +01:00
id: row.id,
2023-01-19 18:23:48 +01:00
name: newName,
value: newValue,
2023-01-18 18:11:52 +01:00
})
)
})
})
2023-02-07 11:46:34 +01:00
describe("DELETE /api/:tableId/rows", () => {
2023-01-19 18:23:48 +01:00
const deleteRow = (
tableId: string | undefined,
body: Row | { rows: Row[] }
) => makeRequest("delete", `/api/${tableId}/rows`, body)
2023-02-07 11:46:34 +01:00
it("Given than a row exists, delete request removes it", async () => {
2023-01-18 18:21:17 +01:00
const numberOfInitialRows = 5
2023-02-07 11:46:34 +01:00
let { row } = _.sample(await populatePrimaryRows(numberOfInitialRows))!
2023-01-18 18:21:17 +01:00
2023-02-07 11:46:34 +01:00
const res = await deleteRow(primaryPostgresTable._id, row)
2023-01-18 18:21:17 +01:00
expect(res.status).toBe(200)
2023-02-07 11:46:34 +01:00
const persistedRows = await config.getRows(primaryPostgresTable._id!)
2023-01-18 18:21:17 +01:00
expect(persistedRows).toHaveLength(numberOfInitialRows - 1)
2023-02-06 15:54:49 +01:00
expect(row.id).toBeDefined()
2023-01-18 18:21:17 +01:00
expect(persistedRows).not.toContain(
2023-02-06 15:54:49 +01:00
expect.objectContaining({ _id: row.id })
2023-01-18 18:21:17 +01:00
)
})
2023-01-19 18:23:48 +01:00
2023-02-07 11:46:34 +01:00
it("Given than multiple rows exist, multiple rows can be removed at once", async () => {
2023-01-19 18:28:42 +01:00
const numberOfInitialRows = 5
2023-02-07 11:46:34 +01:00
let rows = _.sampleSize(
await populatePrimaryRows(numberOfInitialRows),
3
)!.map(x => x.row)
2023-01-19 18:28:42 +01:00
2023-02-07 11:46:34 +01:00
const res = await deleteRow(primaryPostgresTable._id, { rows })
2023-01-19 18:28:42 +01:00
expect(res.status).toBe(200)
2023-02-07 11:46:34 +01:00
const persistedRows = await config.getRows(primaryPostgresTable._id!)
2023-01-19 18:28:42 +01:00
expect(persistedRows).toHaveLength(numberOfInitialRows - 3)
for (const row of rows) {
expect(persistedRows).not.toContain(
2023-02-06 15:54:49 +01:00
expect.objectContaining({ _id: row.id })
2023-01-19 18:28:42 +01:00
)
}
})
2023-01-18 18:21:17 +01:00
})
2023-02-07 11:46:34 +01:00
describe("GET /api/:tableId/rows/:rowId", () => {
2023-01-19 18:23:48 +01:00
const getRow = (tableId: string | undefined, rowId?: string | undefined) =>
makeRequest("get", `/api/${tableId}/rows/${rowId}`)
2023-02-07 11:46:34 +01:00
it("Given than a table have a single row, that row can be retrieved successfully", async () => {
const [{ rowData, row }] = await populatePrimaryRows(1)
2023-01-18 17:46:40 +01:00
2023-02-07 11:46:34 +01:00
const res = await getRow(primaryPostgresTable._id, row.id)
2023-01-18 17:46:40 +01:00
expect(res.status).toBe(200)
2023-01-19 18:23:48 +01:00
expect(res.body).toEqual(expect.objectContaining(rowData))
2023-01-18 17:46:40 +01:00
})
2023-01-18 17:48:18 +01:00
2023-02-07 11:46:34 +01:00
it("Given than a table have a multiple rows, a single row can be retrieved successfully", async () => {
const rows = await populatePrimaryRows(10)
2023-01-18 18:07:09 +01:00
const { rowData, row } = _.sample(rows)!
2023-01-18 17:48:18 +01:00
2023-02-07 11:46:34 +01:00
const res = await getRow(primaryPostgresTable._id, row.id)
2023-01-18 17:48:18 +01:00
expect(res.status).toBe(200)
2023-01-19 18:23:48 +01:00
expect(res.body).toEqual(expect.objectContaining(rowData))
2023-01-18 17:48:18 +01:00
})
2023-01-19 21:09:39 +01:00
2023-02-07 11:46:34 +01:00
it("Given a rows with relation data, foreign key fields are not retrieved", async () => {
let [{ row }] = await populatePrimaryRows(1)
2023-01-19 21:09:39 +01:00
2023-02-06 15:54:49 +01:00
await config.createRow({
2023-01-19 21:09:39 +01:00
tableId: auxPostgresTable._id,
2023-02-02 11:43:18 +01:00
title: generator.sentence(),
2023-02-06 15:54:49 +01:00
linkedField: row.id,
2023-01-19 21:09:39 +01:00
})
2023-02-07 11:46:34 +01:00
const res = await getRow(primaryPostgresTable._id, row.id)
2023-01-19 21:09:39 +01:00
expect(res.status).toBe(200)
expect(res.body).toEqual({
2023-02-06 18:30:33 +01:00
...row,
2023-02-06 15:54:49 +01:00
_id: expect.any(String),
_rev: expect.any(String),
2023-01-19 21:09:39 +01:00
})
2023-02-06 15:54:49 +01:00
expect(res.body.foreignField).toBeUndefined()
2023-01-19 21:09:39 +01:00
})
2023-01-18 17:46:40 +01:00
})
2023-01-19 12:00:51 +01:00
2023-02-07 11:46:34 +01:00
describe("POST /api/:tableId/search", () => {
2023-01-19 12:44:48 +01:00
const search = (tableId: string | undefined, body?: object) =>
2023-01-19 18:23:48 +01:00
makeRequest("post", `/api/${tableId}/search`, body)
2023-01-19 12:44:48 +01:00
2023-01-19 12:20:20 +01:00
describe("empty search", () => {
2023-02-07 11:46:34 +01:00
it("Given than a table has no rows, search without query returns empty", async () => {
const res = await search(primaryPostgresTable._id)
2023-01-19 12:06:41 +01:00
2023-01-19 12:20:20 +01:00
expect(res.status).toBe(200)
2023-01-19 12:06:41 +01:00
2023-02-06 15:54:49 +01:00
expect(res.body).toEqual({
rows: [],
bookmark: null,
hasNextPage: false,
})
2023-01-19 12:20:20 +01:00
})
2023-01-19 12:06:41 +01:00
2023-02-07 11:46:34 +01:00
it("Given than a table has multiple rows, search without query returns all of them", async () => {
2023-01-19 12:20:20 +01:00
const rowsCount = 6
2023-02-07 11:46:34 +01:00
const rows = await populatePrimaryRows(rowsCount)
2023-01-19 12:00:51 +01:00
2023-02-07 11:46:34 +01:00
const res = await search(primaryPostgresTable._id)
2023-01-19 12:00:51 +01:00
2023-01-19 12:20:20 +01:00
expect(res.status).toBe(200)
2023-01-19 12:00:51 +01:00
2023-01-19 18:23:48 +01:00
expect(res.body).toEqual({
rows: expect.arrayContaining(
2023-01-19 12:20:20 +01:00
rows.map(r => expect.objectContaining(r.rowData))
2023-01-19 18:23:48 +01:00
),
2023-02-06 15:54:49 +01:00
bookmark: null,
hasNextPage: false,
2023-01-19 18:23:48 +01:00
})
expect(res.body.rows).toHaveLength(rowsCount)
2023-01-19 12:20:20 +01:00
})
2023-02-07 11:46:34 +01:00
it("Given than multiple tables have multiple rows, search only return the requested ones", async () => {
const createRandomTableWithRows = async () =>
await config.createRow({
tableId: (await createDefaultPgTable())._id,
title: generator.name(),
})
await createRandomTableWithRows()
await createRandomTableWithRows()
2023-01-19 12:20:20 +01:00
const rowsCount = 6
2023-02-07 11:46:34 +01:00
await populatePrimaryRows(rowsCount)
2023-01-19 12:20:20 +01:00
2023-02-07 11:46:34 +01:00
await createRandomTableWithRows()
const res = await search(primaryPostgresTable._id)
2023-01-19 12:20:20 +01:00
expect(res.status).toBe(200)
2023-01-19 18:23:48 +01:00
expect(res.body.rows).toHaveLength(rowsCount)
2023-01-19 12:20:20 +01:00
})
2023-01-19 12:00:51 +01:00
})
2023-01-19 12:06:41 +01:00
2023-02-07 11:46:34 +01:00
it("Querying by a string field returns the rows with field containing or starting by that value", async () => {
2023-02-02 11:43:18 +01:00
const name = generator.name()
2023-01-19 12:20:20 +01:00
const rowsToFilter = [
...Array(2).fill({
name,
2023-02-02 11:43:18 +01:00
description: generator.paragraph(),
2023-02-06 18:30:33 +01:00
value: generator.age(),
2023-01-19 12:20:20 +01:00
}),
...Array(2).fill({
2023-02-02 11:43:18 +01:00
name: `${name}${utils.newid()}`,
description: generator.paragraph(),
2023-02-06 18:30:33 +01:00
value: generator.age(),
2023-01-19 12:20:20 +01:00
}),
]
2023-02-07 11:46:34 +01:00
await populatePrimaryRows(3)
2023-01-19 12:20:20 +01:00
for (const row of rowsToFilter) {
2023-02-07 11:46:34 +01:00
await createPrimaryRow({
rowData: row,
})
2023-01-19 12:20:20 +01:00
}
2023-02-07 11:46:34 +01:00
await populatePrimaryRows(1)
2023-01-19 12:06:41 +01:00
2023-02-07 11:46:34 +01:00
const res = await search(primaryPostgresTable._id, {
2023-01-19 12:44:48 +01:00
query: {
string: {
name,
2023-01-19 12:20:20 +01:00
},
2023-01-19 12:44:48 +01:00
},
})
2023-01-19 12:06:41 +01:00
expect(res.status).toBe(200)
2023-01-19 18:23:48 +01:00
expect(res.body).toEqual({
rows: expect.arrayContaining(rowsToFilter.map(expect.objectContaining)),
2023-02-06 15:54:49 +01:00
bookmark: null,
hasNextPage: false,
2023-01-19 18:23:48 +01:00
})
expect(res.body.rows).toHaveLength(4)
2023-01-19 12:06:41 +01:00
})
2023-01-19 12:35:00 +01:00
2023-02-07 11:46:34 +01:00
it("Querying respects the limit fields", async () => {
await populatePrimaryRows(6)
2023-01-19 12:35:00 +01:00
2023-02-07 11:46:34 +01:00
const res = await search(primaryPostgresTable._id, {
2023-01-19 12:44:48 +01:00
limit: 2,
})
2023-01-19 12:35:00 +01:00
expect(res.status).toBe(200)
2023-01-19 18:23:48 +01:00
expect(res.body.rows).toHaveLength(2)
2023-01-19 12:35:00 +01:00
})
describe("sort", () => {
beforeEach(async () => {
2023-02-07 11:46:34 +01:00
const defaultValue = generateRandomPrimaryRowData()
2023-01-19 12:35:00 +01:00
2023-02-07 11:46:34 +01:00
await createPrimaryRow({
rowData: {
2023-01-19 12:35:00 +01:00
...defaultValue,
name: "d",
value: 3,
},
2023-02-07 11:46:34 +01:00
})
await createPrimaryRow({
rowData: { ...defaultValue, name: "aaa", value: 40 },
})
await createPrimaryRow({
rowData: { ...defaultValue, name: "ccccc", value: -5 },
})
await createPrimaryRow({
rowData: { ...defaultValue, name: "bb", value: 0 },
})
2023-01-19 12:35:00 +01:00
})
2023-02-07 11:46:34 +01:00
it("Querying respects the sort order when sorting ascending by a string value", async () => {
const res = await search(primaryPostgresTable._id, {
2023-01-19 18:23:48 +01:00
sort: "name",
sortOrder: "ascending",
sortType: "string",
2023-01-19 12:44:48 +01:00
})
2023-01-19 12:35:00 +01:00
expect(res.status).toBe(200)
2023-01-19 18:23:48 +01:00
expect(res.body.rows).toEqual([
2023-01-19 12:35:00 +01:00
expect.objectContaining({ name: "aaa" }),
expect.objectContaining({ name: "bb" }),
expect.objectContaining({ name: "ccccc" }),
expect.objectContaining({ name: "d" }),
])
})
2023-02-07 11:46:34 +01:00
it("Querying respects the sort order when sorting descending by a string value", async () => {
const res = await search(primaryPostgresTable._id, {
2023-01-19 18:23:48 +01:00
sort: "name",
sortOrder: "descending",
sortType: "string",
2023-01-19 12:44:48 +01:00
})
2023-01-19 12:35:00 +01:00
expect(res.status).toBe(200)
2023-01-19 18:23:48 +01:00
expect(res.body.rows).toEqual([
2023-01-19 12:35:00 +01:00
expect.objectContaining({ name: "d" }),
expect.objectContaining({ name: "ccccc" }),
expect.objectContaining({ name: "bb" }),
expect.objectContaining({ name: "aaa" }),
])
})
2023-02-07 11:46:34 +01:00
it("Querying respects the sort order when sorting ascending by a numeric value", async () => {
const res = await search(primaryPostgresTable._id, {
2023-01-19 18:23:48 +01:00
sort: "value",
sortOrder: "ascending",
sortType: "number",
2023-01-19 12:44:48 +01:00
})
2023-01-19 12:35:00 +01:00
expect(res.status).toBe(200)
2023-01-19 18:23:48 +01:00
expect(res.body.rows).toEqual([
2023-01-19 12:35:00 +01:00
expect.objectContaining({ value: -5 }),
expect.objectContaining({ value: 0 }),
expect.objectContaining({ value: 3 }),
expect.objectContaining({ value: 40 }),
])
})
2023-02-07 11:46:34 +01:00
it("Querying respects the sort order when sorting descending by a numeric value", async () => {
const res = await search(primaryPostgresTable._id, {
2023-01-19 18:23:48 +01:00
sort: "value",
sortOrder: "descending",
sortType: "number",
2023-01-19 12:44:48 +01:00
})
2023-01-19 12:35:00 +01:00
expect(res.status).toBe(200)
2023-01-19 18:23:48 +01:00
expect(res.body.rows).toEqual([
2023-01-19 12:35:00 +01:00
expect.objectContaining({ value: 40 }),
expect.objectContaining({ value: 3 }),
expect.objectContaining({ value: 0 }),
expect.objectContaining({ value: -5 }),
])
})
})
2023-01-19 12:00:51 +01:00
})
2023-01-19 12:44:48 +01:00
2023-02-07 11:46:34 +01:00
describe("GET /api/:tableId/:rowId/enrich", () => {
2023-01-19 21:09:39 +01:00
const getAll = (tableId: string | undefined, rowId: string | undefined) =>
makeRequest("get", `/api/${tableId}/${rowId}/enrich`)
2023-02-07 11:46:34 +01:00
it("Given a row with relation data, enrich populates the foreign field", async () => {
const { row, foreignRow } = await createPrimaryRow({
rowData: generateRandomPrimaryRowData(),
createForeignRow: true,
2023-01-19 21:09:39 +01:00
})
2023-02-07 11:46:34 +01:00
const res = await getAll(primaryPostgresTable._id, row.id)
2023-01-19 21:09:39 +01:00
expect(res.status).toBe(200)
2023-02-07 11:46:34 +01:00
expect(foreignRow).toBeDefined()
2023-01-19 21:09:39 +01:00
expect(res.body).toEqual({
...row,
2023-02-06 15:54:49 +01:00
linkedField: [
2023-01-19 21:09:39 +01:00
{
...foreignRow,
},
],
})
})
})
2023-02-07 11:46:34 +01:00
describe("GET /api/:tableId/rows", () => {
2023-01-19 17:46:05 +01:00
const getAll = (tableId: string | undefined) =>
makeRequest("get", `/api/${tableId}/rows`)
2023-01-19 12:44:48 +01:00
2023-02-07 11:46:34 +01:00
it("Given than a table has no rows, get returns empty", async () => {
const res = await getAll(primaryPostgresTable._id)
2023-01-19 12:44:48 +01:00
2023-01-19 17:46:05 +01:00
expect(res.status).toBe(200)
2023-01-19 12:44:48 +01:00
2023-01-19 17:46:05 +01:00
expect(res.body).toHaveLength(0)
})
2023-01-19 12:44:48 +01:00
2023-02-07 11:46:34 +01:00
it("Given than a table has multiple rows, get returns all of them", async () => {
2023-01-19 17:46:05 +01:00
const rowsCount = 6
2023-02-07 11:46:34 +01:00
const rows = await populatePrimaryRows(rowsCount)
2023-01-19 12:44:48 +01:00
2023-02-07 11:46:34 +01:00
const res = await getAll(primaryPostgresTable._id)
2023-01-19 12:44:48 +01:00
2023-01-19 17:46:05 +01:00
expect(res.status).toBe(200)
2023-01-19 12:44:48 +01:00
2023-01-19 17:46:05 +01:00
expect(res.body).toHaveLength(rowsCount)
expect(res.body).toEqual(
expect.arrayContaining(
rows.map(r => expect.objectContaining(r.rowData))
)
)
})
2023-01-19 12:44:48 +01:00
2023-02-07 11:46:34 +01:00
it("Given than multiple tables have multiple rows, get returns the requested ones", async () => {
const createRandomTableWithRows = async () =>
await config.createRow({
tableId: (await createDefaultPgTable())._id,
title: generator.name(),
})
await createRandomTableWithRows()
2023-01-19 17:46:05 +01:00
const rowsCount = 6
2023-02-07 11:46:34 +01:00
await populatePrimaryRows(rowsCount)
await createRandomTableWithRows()
2023-01-19 12:44:48 +01:00
2023-02-07 11:46:34 +01:00
const res = await getAll(primaryPostgresTable._id)
2023-01-19 12:44:48 +01:00
2023-01-19 17:46:05 +01:00
expect(res.status).toBe(200)
2023-01-19 12:44:48 +01:00
2023-01-19 17:46:05 +01:00
expect(res.body).toHaveLength(rowsCount)
})
})
2023-01-17 18:22:31 +01:00
})