1
0
Fork 0
mirror of synced 2024-07-11 01:06:04 +12:00

Convert view.spec.js to TypeScript, remove reliace on TestConfiguration.

This commit is contained in:
Sam Rose 2024-03-13 17:42:24 +00:00
parent 64ea77237f
commit 3da2261735
No known key found for this signature in database
4 changed files with 201 additions and 198 deletions

View file

@ -1,38 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`/views query returns data for the created view 1`] = `
[
{
"avg": 2333.3333333333335,
"count": 3,
"group": null,
"max": 4000,
"min": 1000,
"sum": 7000,
"sumsqr": 21000000,
},
]
`;
exports[`/views query returns data for the created view using a group by 1`] = `
[
{
"avg": 1500,
"count": 2,
"group": "One",
"max": 2000,
"min": 1000,
"sum": 3000,
"sumsqr": 5000000,
},
{
"avg": 4000,
"count": 1,
"group": "Two",
"max": 4000,
"min": 4000,
"sum": 4000,
"sumsqr": 16000000,
},
]
`;

View file

@ -1,30 +1,38 @@
const setup = require("./utilities") import { events } from "@budibase/backend-core"
const { events } = require("@budibase/backend-core") import * as setup from "./utilities"
import {
FieldType,
INTERNAL_TABLE_SOURCE_ID,
SaveTableRequest,
Table,
TableSourceType,
View,
ViewCalculation,
} from "@budibase/types"
function priceTable() { const priceTable: SaveTableRequest = {
return {
name: "table", name: "table",
type: "table", type: "table",
key: "name", sourceId: INTERNAL_TABLE_SOURCE_ID,
sourceType: TableSourceType.INTERNAL,
schema: { schema: {
Price: { Price: {
type: "number", name: "Price",
constraints: {}, type: FieldType.NUMBER,
}, },
Category: { Category: {
type: "string", name: "Category",
type: FieldType.STRING,
constraints: { constraints: {
type: "string", type: "string",
}, },
}, },
}, },
} }
}
describe("/views", () => { describe("/views", () => {
let request = setup.getRequest()
let config = setup.getConfig() let config = setup.getConfig()
let table let table: Table
afterAll(setup.afterAll) afterAll(setup.afterAll)
@ -33,38 +41,34 @@ describe("/views", () => {
}) })
beforeEach(async () => { beforeEach(async () => {
table = await config.createTable(priceTable()) table = await config.api.table.save(priceTable)
}) })
const saveView = async view => { const saveView = async (view?: Partial<View>) => {
const viewToSave = { const viewToSave: View = {
name: "TestView", name: "TestView",
field: "Price", field: "Price",
calculation: "stats", calculation: ViewCalculation.STATISTICS,
tableId: table._id, tableId: table._id!,
filters: [],
schema: {},
...view, ...view,
} }
return request return config.api.legacyView.save(viewToSave)
.post(`/api/views`)
.send(viewToSave)
.set(config.defaultHeaders())
.expect("Content-Type", /json/)
.expect(200)
} }
describe("create", () => { describe("create", () => {
it("returns a success message when the view is successfully created", async () => { it("returns a success message when the view is successfully created", async () => {
const res = await saveView() const res = await saveView()
expect(res.body.tableId).toBe(table._id)
expect(events.view.created).toBeCalledTimes(1) expect(events.view.created).toBeCalledTimes(1)
}) })
it("creates a view with a calculation", async () => { it("creates a view with a calculation", async () => {
jest.clearAllMocks() jest.clearAllMocks()
const res = await saveView({ calculation: "count" }) const view = await saveView({ calculation: ViewCalculation.COUNT })
expect(res.body.tableId).toBe(table._id) expect(view.tableId).toBe(table._id)
expect(events.view.created).toBeCalledTimes(1) expect(events.view.created).toBeCalledTimes(1)
expect(events.view.updated).not.toBeCalled() expect(events.view.updated).not.toBeCalled()
expect(events.view.calculationCreated).toBeCalledTimes(1) expect(events.view.calculationCreated).toBeCalledTimes(1)
@ -78,8 +82,8 @@ describe("/views", () => {
it("creates a view with a filter", async () => { it("creates a view with a filter", async () => {
jest.clearAllMocks() jest.clearAllMocks()
const res = await saveView({ const view = await saveView({
calculation: null, calculation: undefined,
filters: [ filters: [
{ {
value: "1", value: "1",
@ -89,7 +93,7 @@ describe("/views", () => {
], ],
}) })
expect(res.body.tableId).toBe(table._id) expect(view.tableId).toBe(table._id)
expect(events.view.created).toBeCalledTimes(1) expect(events.view.created).toBeCalledTimes(1)
expect(events.view.updated).not.toBeCalled() expect(events.view.updated).not.toBeCalled()
expect(events.view.calculationCreated).not.toBeCalled() expect(events.view.calculationCreated).not.toBeCalled()
@ -101,21 +105,10 @@ describe("/views", () => {
}) })
it("updates the table row with the new view metadata", async () => { it("updates the table row with the new view metadata", async () => {
const res = await request await saveView()
.post(`/api/views`) const updatedTable = await config.api.table.get(table._id!)
.send({ expect(updatedTable.views).toEqual(
name: "TestView", expect.objectContaining({
field: "Price",
calculation: "stats",
tableId: table._id,
})
.set(config.defaultHeaders())
.expect("Content-Type", /json/)
.expect(200)
expect(res.body.tableId).toBe(table._id)
const updatedTable = await config.getTable(table._id)
const expectedObj = expect.objectContaining({
TestView: expect.objectContaining({ TestView: expect.objectContaining({
field: "Price", field: "Price",
calculation: "stats", calculation: "stats",
@ -146,7 +139,7 @@ describe("/views", () => {
}, },
}), }),
}) })
expect(updatedTable.views).toEqual(expectedObj) )
}) })
}) })
@ -168,10 +161,10 @@ describe("/views", () => {
}) })
it("updates a view calculation", async () => { it("updates a view calculation", async () => {
await saveView({ calculation: "sum" }) await saveView({ calculation: ViewCalculation.SUM })
jest.clearAllMocks() jest.clearAllMocks()
await saveView({ calculation: "count" }) await saveView({ calculation: ViewCalculation.COUNT })
expect(events.view.created).not.toBeCalled() expect(events.view.created).not.toBeCalled()
expect(events.view.updated).toBeCalledTimes(1) expect(events.view.updated).toBeCalledTimes(1)
@ -184,10 +177,10 @@ describe("/views", () => {
}) })
it("deletes a view calculation", async () => { it("deletes a view calculation", async () => {
await saveView({ calculation: "sum" }) await saveView({ calculation: ViewCalculation.SUM })
jest.clearAllMocks() jest.clearAllMocks()
await saveView({ calculation: null }) await saveView({ calculation: undefined })
expect(events.view.created).not.toBeCalled() expect(events.view.created).not.toBeCalled()
expect(events.view.updated).toBeCalledTimes(1) expect(events.view.updated).toBeCalledTimes(1)
@ -258,100 +251,98 @@ describe("/views", () => {
describe("fetch", () => { describe("fetch", () => {
beforeEach(async () => { beforeEach(async () => {
table = await config.createTable(priceTable()) table = await config.api.table.save(priceTable)
}) })
it("returns only custom views", async () => { it("returns only custom views", async () => {
await config.createLegacyView({ await saveView({
name: "TestView", name: "TestView",
field: "Price", field: "Price",
calculation: "stats", calculation: ViewCalculation.STATISTICS,
tableId: table._id, tableId: table._id,
}) })
const res = await request const views = await config.api.legacyView.fetch()
.get(`/api/views`) expect(views.length).toBe(1)
.set(config.defaultHeaders()) expect(views.find(({ name }) => name === "TestView")).toBeDefined()
.expect("Content-Type", /json/)
.expect(200)
expect(res.body.length).toBe(1)
expect(res.body.find(({ name }) => name === "TestView")).toBeDefined()
}) })
}) })
describe("query", () => { describe("query", () => {
it("returns data for the created view", async () => { it("returns data for the created view", async () => {
await config.createLegacyView({ await saveView({
name: "TestView", name: "TestView",
field: "Price", field: "Price",
calculation: "stats", calculation: ViewCalculation.STATISTICS,
tableId: table._id, tableId: table._id!,
}) })
await config.createRow({ await config.api.row.save(table._id!, {
tableId: table._id,
Price: 1000, Price: 1000,
}) })
await config.createRow({ await config.api.row.save(table._id!, {
tableId: table._id,
Price: 2000, Price: 2000,
}) })
await config.createRow({ await config.api.row.save(table._id!, {
tableId: table._id,
Price: 4000, Price: 4000,
}) })
const res = await request const rows = await config.api.legacyView.get("TestView", {
.get(`/api/views/TestView?calculation=stats`) calculation: ViewCalculation.STATISTICS,
.set(config.defaultHeaders()) })
.expect("Content-Type", /json/) expect(rows.length).toBe(1)
.expect(200) expect(rows[0]).toEqual({
expect(res.body.length).toBe(1) avg: 2333.3333333333335,
expect(res.body).toMatchSnapshot() count: 3,
group: null,
max: 4000,
min: 1000,
sum: 7000,
sumsqr: 21000000,
})
}) })
it("returns data for the created view using a group by", async () => { it("returns data for the created view using a group by", async () => {
await config.createLegacyView({ await saveView({
calculation: "stats", calculation: ViewCalculation.STATISTICS,
name: "TestView", name: "TestView",
field: "Price", field: "Price",
groupBy: "Category", groupBy: "Category",
tableId: table._id, tableId: table._id,
}) })
await config.createRow({ await config.api.row.save(table._id!, {
tableId: table._id,
Price: 1000, Price: 1000,
Category: "One", Category: "One",
}) })
await config.createRow({ await config.api.row.save(table._id!, {
tableId: table._id,
Price: 2000, Price: 2000,
Category: "One", Category: "One",
}) })
await config.createRow({ await config.api.row.save(table._id!, {
tableId: table._id,
Price: 4000, Price: 4000,
Category: "Two", Category: "Two",
}) })
const res = await request const rows = await config.api.legacyView.get("TestView", {
.get(`/api/views/TestView?calculation=stats&group=Category`) calculation: ViewCalculation.STATISTICS,
.set(config.defaultHeaders()) group: "Category",
.expect("Content-Type", /json/) })
.expect(200) expect(rows.length).toBe(2)
expect(rows[0]).toEqual({
expect(res.body.length).toBe(2) avg: 1500,
expect(res.body).toMatchSnapshot() count: 2,
group: "One",
max: 2000,
min: 1000,
sum: 3000,
sumsqr: 5000000,
})
}) })
}) })
describe("destroy", () => { describe("destroy", () => {
it("should be able to delete a view", async () => { it("should be able to delete a view", async () => {
const table = await config.createTable(priceTable()) const table = await config.api.table.save(priceTable)
const view = await config.createLegacyView() const view = await saveView({ tableId: table._id })
const res = await request const deletedView = await config.api.legacyView.destroy(view.name!)
.delete(`/api/views/${view.name}`) expect(deletedView.map).toBeDefined()
.set(config.defaultHeaders()) expect(deletedView.meta?.tableId).toEqual(table._id)
.expect("Content-Type", /json/)
.expect(200)
expect(res.body.map).toBeDefined()
expect(res.body.meta.tableId).toEqual(table._id)
expect(events.view.deleted).toBeCalledTimes(1) expect(events.view.deleted).toBeCalledTimes(1)
}) })
}) })
@ -362,33 +353,44 @@ describe("/views", () => {
}) })
const setupExport = async () => { const setupExport = async () => {
const table = await config.createTable() const table = await config.api.table.save({
await config.createRow({ name: "test-name", description: "ùúûü" }) name: "test-table",
type: "table",
sourceId: INTERNAL_TABLE_SOURCE_ID,
sourceType: TableSourceType.INTERNAL,
schema: {
name: {
name: "name",
type: FieldType.STRING,
},
description: {
name: "description",
type: FieldType.STRING,
},
},
})
await config.api.row.save(table._id!, {
name: "test-name",
description: "ùúûü",
})
return table return table
} }
const exportView = async (viewName, format) => { const assertJsonExport = (res: string) => {
return request const rows = JSON.parse(res)
.get(`/api/views/export?view=${viewName}&format=${format}`)
.set(config.defaultHeaders())
.expect(200)
}
const assertJsonExport = res => {
const rows = JSON.parse(res.text)
expect(rows.length).toBe(1) expect(rows.length).toBe(1)
expect(rows[0].name).toBe("test-name") expect(rows[0].name).toBe("test-name")
expect(rows[0].description).toBe("ùúûü") expect(rows[0].description).toBe("ùúûü")
} }
const assertCSVExport = res => { const assertCSVExport = (res: string) => {
expect(res.text).toBe(`"name","description"\n"test-name","ùúûü"`) expect(res).toBe(`"name","description"\n"test-name","ùúûü"`)
} }
it("should be able to export a table as JSON", async () => { it("should be able to export a table as JSON", async () => {
const table = await setupExport() const table = await setupExport()
const res = await exportView(table._id, "json") const res = await config.api.legacyView.export(table._id!, "json")
assertJsonExport(res) assertJsonExport(res)
expect(events.table.exported).toBeCalledTimes(1) expect(events.table.exported).toBeCalledTimes(1)
@ -398,7 +400,7 @@ describe("/views", () => {
it("should be able to export a table as CSV", async () => { it("should be able to export a table as CSV", async () => {
const table = await setupExport() const table = await setupExport()
const res = await exportView(table._id, "csv") const res = await config.api.legacyView.export(table._id!, "csv")
assertCSVExport(res) assertCSVExport(res)
expect(events.table.exported).toBeCalledTimes(1) expect(events.table.exported).toBeCalledTimes(1)
@ -407,10 +409,15 @@ describe("/views", () => {
it("should be able to export a view as JSON", async () => { it("should be able to export a view as JSON", async () => {
let table = await setupExport() let table = await setupExport()
const view = await config.createLegacyView() const view = await config.api.legacyView.save({
table = await config.getTable(table._id) name: "test-view",
tableId: table._id!,
filters: [],
schema: {},
})
table = await config.api.table.get(table._id!)
let res = await exportView(view.name, "json") let res = await config.api.legacyView.export(view.name!, "json")
assertJsonExport(res) assertJsonExport(res)
expect(events.view.exported).toBeCalledTimes(1) expect(events.view.exported).toBeCalledTimes(1)
@ -419,10 +426,15 @@ describe("/views", () => {
it("should be able to export a view as CSV", async () => { it("should be able to export a view as CSV", async () => {
let table = await setupExport() let table = await setupExport()
const view = await config.createLegacyView() const view = await config.api.legacyView.save({
table = await config.getTable(table._id) name: "test-view",
tableId: table._id!,
filters: [],
schema: {},
})
table = await config.api.table.get(table._id!)
let res = await exportView(view.name, "csv") let res = await config.api.legacyView.export(view.name!, "csv")
assertCSVExport(res) assertCSVExport(res)
expect(events.view.exported).toBeCalledTimes(1) expect(events.view.exported).toBeCalledTimes(1)

View file

@ -1,8 +1,36 @@
import { Expectations, TestAPI } from "./base" import { Expectations, TestAPI } from "./base"
import { Row } from "@budibase/types" import { Row, View, ViewCalculation } from "@budibase/types"
export class LegacyViewAPI extends TestAPI { export class LegacyViewAPI extends TestAPI {
get = async (id: string, expectations?: Expectations) => { get = async (
return await this._get<Row[]>(`/api/views/${id}`, { expectations }) id: string,
query: { calculation: ViewCalculation; group?: string },
expectations?: Expectations
) => {
return await this._get<Row[]>(`/api/views/${id}`, { query, expectations })
}
save = async (body: View, expectations?: Expectations) => {
return await this._post<View>(`/api/views/`, { body, expectations })
}
fetch = async (expectations?: Expectations) => {
return await this._get<View[]>(`/api/views`, { expectations })
}
destroy = async (id: string, expectations?: Expectations) => {
return await this._delete<View>(`/api/views/${id}`, { expectations })
}
export = async (
viewName: string,
format: "json" | "csv" | "jsonWithSchema",
expectations?: Expectations
) => {
const response = await this._requestRaw("get", `/api/views/export`, {
query: { view: viewName, format },
expectations,
})
return response.text
} }
} }

View file

@ -30,6 +30,7 @@ export interface View {
map?: string map?: string
reduce?: any reduce?: any
meta?: ViewTemplateOpts meta?: ViewTemplateOpts
groupBy?: string
} }
export interface ViewV2 { export interface ViewV2 {