budibase/packages/server/src/sdk/app/views/tests/views.spec.ts

577 lines
15 KiB
TypeScript

import _ from "lodash"
import {
FieldSchema,
FieldType,
INTERNAL_TABLE_SOURCE_ID,
Table,
TableSchema,
TableSourceType,
ViewV2,
} from "@budibase/types"
import { generator } from "@budibase/backend-core/tests"
import { enrichSchema, syncSchema } from ".."
describe("table sdk", () => {
const basicTable: Table = {
_id: generator.guid(),
name: "TestTable",
type: "table",
sourceId: INTERNAL_TABLE_SOURCE_ID,
sourceType: TableSourceType.INTERNAL,
schema: {
name: {
type: FieldType.STRING,
name: "name",
visible: true,
width: 80,
order: 2,
constraints: {
type: "string",
},
},
description: {
type: FieldType.STRING,
name: "description",
visible: true,
width: 200,
constraints: {
type: "string",
},
},
id: {
type: FieldType.NUMBER,
name: "id",
visible: true,
order: 1,
constraints: {
type: "number",
},
},
hiddenField: {
type: FieldType.STRING,
name: "hiddenField",
visible: false,
constraints: {
type: "string",
},
},
},
}
describe("enrichViewSchemas", () => {
it("should fetch the default schema if not overridden", async () => {
const tableId = basicTable._id!
const view: ViewV2 = {
version: 2,
id: generator.guid(),
name: generator.guid(),
tableId,
}
const res = enrichSchema(view, basicTable.schema)
expect(res).toEqual({
...view,
schema: {
name: {
type: "string",
name: "name",
visible: false,
order: 2,
width: 80,
constraints: {
type: "string",
},
},
description: {
type: "string",
name: "description",
visible: false,
width: 200,
constraints: {
type: "string",
},
},
id: {
type: "number",
name: "id",
visible: false,
order: 1,
constraints: {
type: "number",
},
},
hiddenField: {
type: "string",
name: "hiddenField",
visible: false,
constraints: {
type: "string",
},
},
},
})
})
it("if view schema only defines columns, should only fetch the selected fields", async () => {
const tableId = basicTable._id!
const view: ViewV2 = {
version: 2,
id: generator.guid(),
name: generator.guid(),
tableId,
schema: {
name: { visible: true },
id: { visible: true },
},
}
const res = enrichSchema(view, basicTable.schema)
expect(res).toEqual({
...view,
schema: {
name: {
...basicTable.schema.name,
visible: true,
},
description: {
...basicTable.schema.description,
visible: false,
},
id: {
...basicTable.schema.id,
visible: true,
},
hiddenField: {
...basicTable.schema.hiddenField,
visible: false,
},
},
})
})
it("schema does not break if the view has corrupted columns", async () => {
const tableId = basicTable._id!
const view: ViewV2 = {
version: 2,
id: generator.guid(),
name: generator.guid(),
tableId,
schema: {
unnexisting: { visible: true },
name: { visible: true },
},
}
const res = enrichSchema(view, basicTable.schema)
expect(res).toEqual({
...view,
schema: {
name: {
...basicTable.schema.name,
visible: true,
},
description: {
...basicTable.schema.description,
visible: false,
},
id: {
...basicTable.schema.id,
visible: false,
},
hiddenField: {
...basicTable.schema.hiddenField,
visible: false,
},
},
})
})
it("if the view schema overrides the schema UI, the table schema should be overridden", async () => {
const tableId = basicTable._id!
const view: ViewV2 = {
version: 2,
id: generator.guid(),
name: generator.guid(),
tableId,
schema: {
name: { visible: true, width: 100 },
id: { visible: true, width: 20 },
description: { visible: false },
},
}
const res = enrichSchema(view, basicTable.schema)
expect(res).toEqual(
expect.objectContaining({
...view,
schema: {
...basicTable.schema,
name: {
type: "string",
name: "name",
order: 2,
visible: true,
width: 100,
constraints: {
type: "string",
},
},
id: {
type: "number",
name: "id",
order: 1,
visible: true,
width: 20,
constraints: {
type: "number",
},
},
description: {
type: "string",
name: "description",
visible: false,
width: 200,
constraints: {
type: "string",
},
},
},
})
)
})
it("if the view defines order, the table schema order should be ignored", async () => {
const tableId = basicTable._id!
const view: ViewV2 = {
version: 2,
id: generator.guid(),
name: generator.guid(),
tableId,
schema: {
name: { visible: true, order: 1 },
id: { visible: true },
description: { visible: true, order: 2 },
},
}
const res = enrichSchema(view, basicTable.schema)
expect(res).toEqual(
expect.objectContaining({
...view,
schema: {
...basicTable.schema,
name: {
type: "string",
name: "name",
order: 1,
visible: true,
width: 80,
constraints: {
type: "string",
},
},
id: {
type: "number",
name: "id",
order: undefined,
visible: true,
constraints: {
type: "number",
},
},
description: {
type: "string",
name: "description",
order: 2,
visible: true,
width: 200,
constraints: {
type: "string",
},
},
},
})
)
})
})
describe("syncSchema", () => {
const basicView: ViewV2 = {
version: 2,
id: generator.guid(),
name: generator.guid(),
tableId: basicTable._id!,
}
describe("view without schema", () => {
it("no table schema changes will not amend the view", () => {
const view: ViewV2 = {
...basicView,
}
const result = syncSchema(
_.cloneDeep(view),
basicTable.schema,
undefined
)
expect(result).toEqual(view)
})
it("adding new columns will not change the view schema", () => {
const view: ViewV2 = {
...basicView,
}
const newTableSchema: TableSchema = {
...basicTable.schema,
newField1: {
type: FieldType.STRING,
name: "newField1",
visible: true,
},
newField2: {
type: FieldType.NUMBER,
name: "newField2",
visible: false,
},
}
const result = syncSchema(_.cloneDeep(view), newTableSchema, undefined)
expect(result).toEqual({
...view,
schema: undefined,
})
})
it("deleting columns will not change the view schema", () => {
const view: ViewV2 = {
...basicView,
}
const { name, description, ...newTableSchema } = basicTable.schema
const result = syncSchema(_.cloneDeep(view), newTableSchema, undefined)
expect(result).toEqual({
...view,
schema: undefined,
})
})
it("renaming mapped columns will update the view column mapping", () => {
const view: ViewV2 = {
...basicView,
}
const { description, ...newTableSchema } = {
...basicTable.schema,
updatedDescription: {
...basicTable.schema.description,
name: "updatedDescription",
},
} as TableSchema
const result = syncSchema(_.cloneDeep(view), newTableSchema, {
old: "description",
updated: "updatedDescription",
})
expect(result).toEqual({
...view,
schema: undefined,
})
})
})
describe("view with schema", () => {
it("no table schema changes will not amend the view", () => {
const view: ViewV2 = {
...basicView,
schema: {
name: { visible: true, width: 100 },
id: { visible: true, width: 20 },
description: { visible: false },
hiddenField: { visible: false },
},
}
const result = syncSchema(
_.cloneDeep(view),
basicTable.schema,
undefined
)
expect(result).toEqual(view)
})
it("adding new columns will add them as not visible to the view", () => {
const view: ViewV2 = {
...basicView,
schema: {
name: { visible: true, width: 100 },
id: { visible: true, width: 20 },
description: { visible: false },
hiddenField: { visible: false },
},
}
const newTableSchema: TableSchema = {
...basicTable.schema,
newField1: {
type: FieldType.STRING,
name: "newField1",
visible: true,
},
newField2: {
type: FieldType.NUMBER,
name: "newField2",
visible: false,
},
}
const result = syncSchema(_.cloneDeep(view), newTableSchema, undefined)
expect(result).toEqual({
...view,
schema: {
...view.schema,
newField1: { visible: false },
newField2: { visible: false },
},
})
})
it("deleting columns will remove them from the UI", () => {
const view: ViewV2 = {
...basicView,
schema: {
name: { visible: true, width: 100 },
id: { visible: true, width: 20 },
description: { visible: false },
hiddenField: { visible: false },
},
}
const { name, description, ...newTableSchema } = basicTable.schema
const result = syncSchema(_.cloneDeep(view), newTableSchema, undefined)
expect(result).toEqual({
...view,
schema: {
...view.schema,
name: undefined,
description: undefined,
},
})
})
it("can handle additions and deletions at the same them UI", () => {
const view: ViewV2 = {
...basicView,
schema: {
name: { visible: true, width: 100 },
id: { visible: true, width: 20 },
description: { visible: false },
hiddenField: { visible: false },
},
}
const { name, description, ...newTableSchema } = {
...basicTable.schema,
newField1: {
type: FieldType.STRING,
name: "newField1",
visible: true,
},
} as TableSchema
const result = syncSchema(_.cloneDeep(view), newTableSchema, undefined)
expect(result).toEqual({
...view,
schema: {
...view.schema,
name: undefined,
description: undefined,
newField1: { visible: false },
},
})
})
it("renaming mapped columns will update the view column mapping and it's schema", () => {
const view: ViewV2 = {
...basicView,
schema: {
name: { visible: true },
id: { visible: true },
description: { visible: true, width: 150, icon: "ic-any" },
hiddenField: { visible: false },
},
}
const { description, ...newTableSchema } = {
...basicTable.schema,
updatedDescription: {
...basicTable.schema.description,
name: "updatedDescription",
},
} as TableSchema
const result = syncSchema(_.cloneDeep(view), newTableSchema, {
old: "description",
updated: "updatedDescription",
})
expect(result).toEqual({
...view,
schema: {
...view.schema,
description: undefined,
updatedDescription: { visible: true, width: 150, icon: "ic-any" },
},
})
})
it("changing no UI schema will not affect the view", () => {
const view: ViewV2 = {
...basicView,
schema: {
name: { visible: true, width: 100 },
id: { visible: true, width: 20 },
description: { visible: false },
hiddenField: { visible: false },
},
}
const result = syncSchema(
_.cloneDeep(view),
{
...basicTable.schema,
id: {
...basicTable.schema.id,
type: FieldType.NUMBER,
} as FieldSchema,
},
undefined
)
expect(result).toEqual(view)
})
it("changing table column UI fields will not affect the view schema", () => {
const view: ViewV2 = {
...basicView,
schema: {
name: { visible: true, width: 100 },
id: { visible: true, width: 20 },
description: { visible: false },
hiddenField: { visible: false },
},
}
const result = syncSchema(
_.cloneDeep(view),
{
...basicTable.schema,
id: {
...basicTable.schema.id,
visible: !basicTable.schema.id.visible,
},
},
undefined
)
expect(result).toEqual(view)
})
})
})
})