Merge pull request #15574 from Budibase/remove-mocks-1

Remove mocking from sqlUtils.spec.ts.
This commit is contained in:
Sam Rose 2025-02-24 14:17:01 +00:00 committed by GitHub
commit 3517f8cbc1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 515 additions and 494 deletions

View File

@ -1,45 +1,49 @@
import { import {
AIOperationEnum, AIOperationEnum,
CalculationType, CalculationType,
Datasource,
FieldType, FieldType,
RelationshipType, RelationshipType,
SourceName,
Table, Table,
ViewV2, ViewV2,
ViewV2Type, ViewV2Type,
} from "@budibase/types" } from "@budibase/types"
import { buildSqlFieldList } from "../sqlUtils" import { buildSqlFieldList } from "../sqlUtils"
import { structures } from "../../../../routes/tests/utilities" import { structures } from "../../../../routes/tests/utilities"
import { sql } from "@budibase/backend-core"
import { generator } from "@budibase/backend-core/tests" import { generator } from "@budibase/backend-core/tests"
import { generateViewID } from "../../../../../db/utils" import { generateViewID } from "../../../../../db/utils"
import sdk from "../../../../../sdk"
import { cloneDeep } from "lodash"
import { utils } from "@budibase/shared-core" import { utils } from "@budibase/shared-core"
import {
DatabaseName,
datasourceDescribe,
} from "../../../../../integrations/tests/utils"
import { context } from "@budibase/backend-core"
jest.mock("../../../../../sdk/app/views", () => ({ const descriptions = datasourceDescribe({
...jest.requireActual("../../../../../sdk/app/views"), only: [DatabaseName.POSTGRES],
getTable: jest.fn(), })
}))
const getTableMock = sdk.views.getTable as jest.MockedFunction<
typeof sdk.views.getTable
>
describe("buildSqlFieldList", () => { if (descriptions.length) {
describe.each(descriptions)(
"buildSqlFieldList ($dbName)",
({ config, dsProvider }) => {
let allTables: Record<string, Table> let allTables: Record<string, Table>
let datasource: Datasource
beforeEach(async () => {
const ds = await dsProvider()
datasource = ds.datasource!
allTables = {}
})
class TableConfig { class TableConfig {
private _table: Table & { _id: string } private _table: Table
constructor(name: string) { constructor(name: string) {
this._table = { this._table = {
...structures.tableForDatasource({ ...structures.tableForDatasource(datasource),
type: "datasource",
source: SourceName.POSTGRES,
}),
name, name,
_id: sql.utils.buildExternalTableId("ds_id", name),
schema: { schema: {
name: { name: {
name: "name", name: "name",
@ -55,8 +59,6 @@ describe("buildSqlFieldList", () => {
}, },
}, },
} }
allTables[name] = this._table
} }
withHiddenField(field: string) { withHiddenField(field: string) {
@ -110,6 +112,7 @@ describe("buildSqlFieldList", () => {
type: FieldType.LINK, type: FieldType.LINK,
relationshipType: RelationshipType.ONE_TO_MANY, relationshipType: RelationshipType.ONE_TO_MANY,
fieldName: "link", fieldName: "link",
foreignKey: "link",
tableId: toTableId, tableId: toTableId,
} }
return this return this
@ -125,17 +128,17 @@ describe("buildSqlFieldList", () => {
return this return this
} }
create() { async create() {
return cloneDeep(this._table) const table = await config.api.table.save(this._table)
allTables[table.name] = table
return table
} }
} }
class ViewConfig { class ViewConfig {
private _table: Table
private _view: ViewV2 private _view: ViewV2
constructor(table: Table) { constructor(table: Table) {
this._table = table
this._view = { this._view = {
version: 2, version: 2,
id: generateViewID(table._id!), id: generateViewID(table._id!),
@ -183,197 +186,208 @@ describe("buildSqlFieldList", () => {
return this return this
} }
create() { async create() {
getTableMock.mockResolvedValueOnce(this._table) return await config.api.viewV2.create(this._view)
return cloneDeep(this._view)
} }
} }
beforeEach(() => { const buildSqlFieldListInApp: typeof buildSqlFieldList = async (
jest.clearAllMocks() table,
allTables = {} allTables,
}) opts
) => {
return context.doInAppContext(config.getAppId(), () =>
buildSqlFieldList(table, allTables, opts)
)
}
describe("table", () => { describe("table", () => {
it("extracts fields from table schema", async () => { it("extracts fields from table schema", async () => {
const table = new TableConfig("table").create() const table = await new TableConfig("table").create()
const result = await buildSqlFieldList(table, {}) const result = await buildSqlFieldListInApp(table, {})
expect(result).toEqual([ expect(result).toEqual([
"table.name", "table.name",
"table.description", "table.description",
"table.amount", "table.amount",
"table.id",
]) ])
}) })
it("excludes hidden fields", async () => { it("excludes hidden fields", async () => {
const table = new TableConfig("table") const table = await new TableConfig("table")
.withHiddenField("description") .withHiddenField("description")
.create() .create()
const result = await buildSqlFieldList(table, {}) const result = await buildSqlFieldListInApp(table, {})
expect(result).toEqual(["table.name", "table.amount"]) expect(result).toEqual(["table.name", "table.amount", "table.id"])
}) })
it("excludes non-sql fields fields", async () => { it("excludes non-sql fields fields", async () => {
const table = new TableConfig("table") const table = await new TableConfig("table")
.withField("formula", FieldType.FORMULA) .withField("formula", FieldType.FORMULA)
.withField("ai", FieldType.AI) .withField("ai", FieldType.AI)
.withRelation("link", "otherTableId")
.create() .create()
const result = await buildSqlFieldList(table, {}) const result = await buildSqlFieldListInApp(table, {})
expect(result).toEqual([ expect(result).toEqual([
"table.name", "table.name",
"table.description", "table.description",
"table.amount", "table.amount",
"table.id",
]) ])
}) })
it("includes hidden fields if there is a formula column", async () => { it("includes hidden fields if there is a formula column", async () => {
const table = new TableConfig("table") const table = await new TableConfig("table")
.withHiddenField("description") .withHiddenField("description")
.withField("formula", FieldType.FORMULA) .withField("formula", FieldType.FORMULA)
.create() .create()
const result = await buildSqlFieldList(table, {}) const result = await buildSqlFieldListInApp(table, {})
expect(result).toEqual([ expect(result).toEqual([
"table.name", "table.name",
"table.description", "table.description",
"table.amount", "table.amount",
"table.id",
]) ])
}) })
it("includes relationships fields when flagged", async () => { it("includes relationships fields when flagged", async () => {
const otherTable = new TableConfig("linkedTable") const otherTable = await new TableConfig("linkedTable")
.withField("id", FieldType.NUMBER) .withField("id", FieldType.NUMBER)
.withPrimary("id") .withPrimary("id")
.withDisplay("name") .withDisplay("name")
.create() .create()
const table = new TableConfig("table") const table = await new TableConfig("table")
.withRelation("link", otherTable._id) .withRelation("link", otherTable._id!)
.create() .create()
const result = await buildSqlFieldList(table, allTables, { const result = await buildSqlFieldListInApp(table, allTables, {
relationships: true, relationships: true,
}) })
expect(result).toEqual([ expect(result).toEqual([
"table.name", "table.name",
"table.description", "table.description",
"table.amount", "table.amount",
"table.id",
"linkedTable.id", "linkedTable.id",
"linkedTable.name", "linkedTable.name",
]) ])
}) })
it("includes all relationship fields if there is a formula column", async () => { it("includes all relationship fields if there is a formula column", async () => {
const otherTable = new TableConfig("linkedTable") const otherTable = await new TableConfig("linkedTable")
.withField("hidden", FieldType.STRING, { visible: false }) .withField("hidden", FieldType.STRING, { visible: false })
.create() .create()
const table = new TableConfig("table") const table = await new TableConfig("table")
.withRelation("link", otherTable._id) .withRelation("link", otherTable._id!)
.withField("formula", FieldType.FORMULA) .withField("formula", FieldType.FORMULA)
.create() .create()
const result = await buildSqlFieldList(table, allTables, { const result = await buildSqlFieldListInApp(table, allTables, {
relationships: true, relationships: true,
}) })
expect(result).toEqual([ expect(result).toEqual([
"table.name", "table.name",
"table.description", "table.description",
"table.amount", "table.amount",
"table.id",
"linkedTable.name", "linkedTable.name",
"linkedTable.description", "linkedTable.description",
"linkedTable.amount", "linkedTable.amount",
"linkedTable.hidden", "linkedTable.hidden",
"linkedTable.id",
]) ])
}) })
it("never includes non-sql columns from relationships", async () => { it("never includes non-sql columns from relationships", async () => {
const otherTable = new TableConfig("linkedTable") const otherTable = await new TableConfig("linkedTable")
.withField("id", FieldType.NUMBER)
.withField("hidden", FieldType.STRING, { visible: false }) .withField("hidden", FieldType.STRING, { visible: false })
.withField("formula", FieldType.FORMULA) .withField("formula", FieldType.FORMULA)
.withField("ai", FieldType.AI) .withField("ai", FieldType.AI)
.withRelation("link", "otherTableId")
.create() .create()
const table = new TableConfig("table") const table = await new TableConfig("table")
.withRelation("link", otherTable._id) .withRelation("link", otherTable._id!)
.withField("formula", FieldType.FORMULA) .withField("formula", FieldType.FORMULA)
.create() .create()
const result = await buildSqlFieldList(table, allTables, { const result = await buildSqlFieldListInApp(table, allTables, {
relationships: true, relationships: true,
}) })
expect(result).toEqual([ expect(result).toEqual([
"table.name", "table.name",
"table.description", "table.description",
"table.amount", "table.amount",
"table.id",
"linkedTable.name", "linkedTable.name",
"linkedTable.description", "linkedTable.description",
"linkedTable.amount", "linkedTable.amount",
"linkedTable.id",
"linkedTable.hidden", "linkedTable.hidden",
"linkedTable.id",
]) ])
}) })
}) })
describe("view", () => { describe("view", () => {
it("extracts fields from table schema", async () => { it("extracts fields from table schema", async () => {
const view = new ViewConfig(new TableConfig("table").create()) const view = await new ViewConfig(
await new TableConfig("table").create()
)
.withVisible("amount") .withVisible("amount")
.withHidden("name") .withHidden("name")
.create() .create()
const result = await buildSqlFieldList(view, {}) const result = await buildSqlFieldListInApp(view, {})
expect(result).toEqual(["table.amount"]) expect(result).toEqual(["table.amount", "table.id"])
}) })
it("includes all fields if there is a formula column", async () => { it("includes all fields if there is a formula column", async () => {
const table = new TableConfig("table") const table = await new TableConfig("table")
.withField("formula", FieldType.FORMULA) .withField("formula", FieldType.FORMULA)
.create() .create()
const view = new ViewConfig(table) const view = await new ViewConfig(table)
.withHidden("name") .withHidden("name")
.withVisible("amount") .withVisible("amount")
.withVisible("formula") .withVisible("formula")
.create() .create()
const result = await buildSqlFieldList(view, {}) const result = await buildSqlFieldListInApp(view, {})
expect(result).toEqual([ expect(result).toEqual([
"table.name", "table.name",
"table.description", "table.description",
"table.amount", "table.amount",
"table.id",
]) ])
}) })
it("does not includes all fields if the formula column is not included", async () => { it("does not includes all fields if the formula column is not included", async () => {
const table = new TableConfig("table") const table = await new TableConfig("table")
.withField("formula", FieldType.FORMULA) .withField("formula", FieldType.FORMULA)
.create() .create()
const view = new ViewConfig(table) const view = await new ViewConfig(table)
.withHidden("name") .withHidden("name")
.withVisible("amount") .withVisible("amount")
.withHidden("formula") .withHidden("formula")
.create() .create()
const result = await buildSqlFieldList(view, {}) const result = await buildSqlFieldListInApp(view, {})
expect(result).toEqual(["table.amount"]) expect(result).toEqual(["table.amount", "table.id"])
}) })
it("includes relationships columns", async () => { it("includes relationships columns", async () => {
const otherTable = new TableConfig("linkedTable") const otherTable = await new TableConfig("linkedTable")
.withField("id", FieldType.NUMBER) .withField("id", FieldType.NUMBER)
.withField("formula", FieldType.FORMULA) .withField("formula", FieldType.FORMULA)
.withPrimary("id") .withPrimary("id")
.create() .create()
const table = new TableConfig("table") const table = await new TableConfig("table")
.withRelation("link", otherTable._id) .withRelation("link", otherTable._id!)
.create() .create()
const view = new ViewConfig(table) const view = await new ViewConfig(table)
.withVisible("name") .withVisible("name")
.withVisible("link") .withVisible("link")
.withRelationshipColumns("link", { .withRelationshipColumns("link", {
@ -383,51 +397,52 @@ describe("buildSqlFieldList", () => {
}) })
.create() .create()
const result = await buildSqlFieldList(view, allTables, { const result = await buildSqlFieldListInApp(view, allTables, {
relationships: true, relationships: true,
}) })
expect(result).toEqual([ expect(result).toEqual([
"table.name", "table.name",
"table.id",
"linkedTable.id", "linkedTable.id",
"linkedTable.amount", "linkedTable.amount",
]) ])
}) })
it("excludes relationships fields when view is not included in the view", async () => { it("excludes relationships fields when view is not included in the view", async () => {
const otherTable = new TableConfig("linkedTable") const otherTable = await new TableConfig("linkedTable")
.withField("id", FieldType.NUMBER) .withField("id", FieldType.NUMBER)
.withPrimary("id") .withPrimary("id")
.withDisplay("name") .withDisplay("name")
.create() .create()
const table = new TableConfig("table") const table = await new TableConfig("table")
.withRelation("link", otherTable._id) .withRelation("link", otherTable._id!)
.withField("formula", FieldType.FORMULA) .withField("formula", FieldType.FORMULA)
.create() .create()
const view = new ViewConfig(table) const view = await new ViewConfig(table)
.withVisible("name") .withVisible("name")
.withHidden("amount") .withHidden("amount")
.create() .create()
const result = await buildSqlFieldList(view, allTables, { const result = await buildSqlFieldListInApp(view, allTables, {
relationships: true, relationships: true,
}) })
expect(result).toEqual(["table.name"]) expect(result).toEqual(["table.name", "table.id"])
}) })
it("does not include relationships columns for hidden links", async () => { it("does not include relationships columns for hidden links", async () => {
const otherTable = new TableConfig("linkedTable") const otherTable = await new TableConfig("linkedTable")
.withField("id", FieldType.NUMBER) .withField("id", FieldType.NUMBER)
.withField("formula", FieldType.FORMULA) .withField("formula", FieldType.FORMULA)
.withPrimary("id") .withPrimary("id")
.create() .create()
const table = new TableConfig("table") const table = await new TableConfig("table")
.withRelation("link", otherTable._id) .withRelation("link", otherTable._id!)
.create() .create()
const view = new ViewConfig(table) const view = await new ViewConfig(table)
.withVisible("name") .withVisible("name")
.withHidden("link") .withHidden("link")
.withRelationshipColumns("link", { .withRelationshipColumns("link", {
@ -437,28 +452,27 @@ describe("buildSqlFieldList", () => {
}) })
.create() .create()
const result = await buildSqlFieldList(view, allTables, { const result = await buildSqlFieldListInApp(view, allTables, {
relationships: true, relationships: true,
}) })
expect(result).toEqual(["table.name"]) expect(result).toEqual(["table.name", "table.id"])
}) })
it("includes all relationship fields if there is a formula column", async () => { it("includes all relationship fields if there is a formula column", async () => {
const otherTable = new TableConfig("linkedTable") const otherTable = await new TableConfig("linkedTable")
.withField("id", FieldType.NUMBER) .withField("id", FieldType.NUMBER)
.withField("hidden", FieldType.STRING, { visible: false }) .withField("hidden", FieldType.STRING, { visible: false })
.withField("formula", FieldType.FORMULA) .withField("formula", FieldType.FORMULA)
.withField("ai", FieldType.AI) .withField("ai", FieldType.AI)
.withRelation("link", "otherTableId")
.withPrimary("id") .withPrimary("id")
.create() .create()
const table = new TableConfig("table") const table = await new TableConfig("table")
.withRelation("link", otherTable._id) .withRelation("link", otherTable._id!)
.withField("formula", FieldType.FORMULA) .withField("formula", FieldType.FORMULA)
.create() .create()
const view = new ViewConfig(table) const view = await new ViewConfig(table)
.withVisible("name") .withVisible("name")
.withVisible("formula") .withVisible("formula")
.withHidden("link") .withHidden("link")
@ -469,13 +483,14 @@ describe("buildSqlFieldList", () => {
}) })
.create() .create()
const result = await buildSqlFieldList(view, allTables, { const result = await buildSqlFieldListInApp(view, allTables, {
relationships: true, relationships: true,
}) })
expect(result).toEqual([ expect(result).toEqual([
"table.name", "table.name",
"table.description", "table.description",
"table.amount", "table.amount",
"table.id",
"linkedTable.name", "linkedTable.name",
"linkedTable.description", "linkedTable.description",
"linkedTable.amount", "linkedTable.amount",
@ -487,25 +502,31 @@ describe("buildSqlFieldList", () => {
describe("calculation view", () => { describe("calculation view", () => {
it("does not include calculation fields", async () => { it("does not include calculation fields", async () => {
const view = new ViewConfig(new TableConfig("table").create()) const view = await new ViewConfig(
await new TableConfig("table").create()
)
.withCalculation("average", "amount", CalculationType.AVG) .withCalculation("average", "amount", CalculationType.AVG)
.create() .create()
const result = await buildSqlFieldList(view, {}) const result = await buildSqlFieldListInApp(view, {})
expect(result).toEqual([]) expect(result).toEqual([])
}) })
it("includes visible fields calculation fields", async () => { it("includes visible fields calculation fields", async () => {
const view = new ViewConfig(new TableConfig("table").create()) const view = await new ViewConfig(
await new TableConfig("table").create()
)
.withCalculation("average", "amount", CalculationType.AVG) .withCalculation("average", "amount", CalculationType.AVG)
.withHidden("name") .withHidden("name")
.withVisible("amount") .withVisible("amount")
.create() .create()
const result = await buildSqlFieldList(view, {}) const result = await buildSqlFieldListInApp(view, {})
expect(result).toEqual(["table.amount"]) expect(result).toEqual(["table.amount"])
}) })
}) })
}) }
)
}