budibase/packages/server/src/utilities/rowProcessor/tests/attachments.spec.ts

180 lines
5.2 KiB
TypeScript

import { AttachmentCleanup } from "../attachments"
import { FieldType, Table, Row, TableSourceType } from "@budibase/types"
import { DEFAULT_BB_DATASOURCE_ID } from "../../../constants"
import { objectStore } from "@budibase/backend-core"
const BUCKET = "prod-budi-app-assets"
const FILE_NAME = "file/thing.jpg"
jest.mock("@budibase/backend-core", () => {
const actual = jest.requireActual("@budibase/backend-core")
return {
...actual,
objectStore: {
deleteFiles: jest.fn(),
ObjectStoreBuckets: actual.objectStore.ObjectStoreBuckets,
},
db: {
isProdAppID: () => jest.fn(() => false),
dbExists: () => jest.fn(() => false),
},
}
})
const mockedDeleteFiles = objectStore.deleteFiles as jest.MockedFunction<
typeof objectStore.deleteFiles
>
const rowGenerators: [
string,
FieldType.ATTACHMENT_SINGLE | FieldType.ATTACHMENTS,
(fileKey?: string) => Row
][] = [
[
"row with a attachment list column",
FieldType.ATTACHMENTS,
function rowWithAttachments(fileKey: string = FILE_NAME): Row {
return {
attach: [
{
size: 1,
extension: "jpg",
key: fileKey,
},
],
}
},
],
[
"row with a single attachment column",
FieldType.ATTACHMENT_SINGLE,
function rowWithAttachments(fileKey: string = FILE_NAME): Row {
return {
attach: {
size: 1,
extension: "jpg",
key: fileKey,
},
}
},
],
]
describe.each(rowGenerators)(
"attachment cleanup",
(_, attachmentFieldType, rowGenerator) => {
function tableGenerator(): Table {
return {
name: "table",
sourceId: DEFAULT_BB_DATASOURCE_ID,
sourceType: TableSourceType.INTERNAL,
type: "table",
schema: {
attach: {
name: "attach",
type: attachmentFieldType,
constraints: {},
},
},
}
}
beforeEach(() => {
mockedDeleteFiles.mockClear()
})
it("should be able to cleanup a table update", async () => {
const originalTable = tableGenerator()
delete originalTable.schema["attach"]
await AttachmentCleanup.tableUpdate(originalTable, [rowGenerator()], {
oldTable: tableGenerator(),
})
expect(mockedDeleteFiles).toHaveBeenCalledWith(BUCKET, [FILE_NAME])
})
it("should be able to cleanup a table deletion", async () => {
await AttachmentCleanup.tableDelete(tableGenerator(), [rowGenerator()])
expect(mockedDeleteFiles).toHaveBeenCalledWith(BUCKET, [FILE_NAME])
})
it("should handle table column renaming", async () => {
const updatedTable = tableGenerator()
updatedTable.schema.attach2 = updatedTable.schema.attach
delete updatedTable.schema.attach
await AttachmentCleanup.tableUpdate(updatedTable, [rowGenerator()], {
oldTable: tableGenerator(),
rename: { old: "attach", updated: "attach2" },
})
expect(mockedDeleteFiles).not.toHaveBeenCalled()
})
it("shouldn't cleanup if no table changes", async () => {
await AttachmentCleanup.tableUpdate(tableGenerator(), [rowGenerator()], {
oldTable: tableGenerator(),
})
expect(mockedDeleteFiles).not.toHaveBeenCalled()
})
it("should handle row updates", async () => {
const updatedRow = rowGenerator()
delete updatedRow.attach
await AttachmentCleanup.rowUpdate(tableGenerator(), {
row: updatedRow,
oldRow: rowGenerator(),
})
expect(mockedDeleteFiles).toHaveBeenCalledWith(BUCKET, [FILE_NAME])
})
it("should handle row deletion", async () => {
await AttachmentCleanup.rowDelete(tableGenerator(), [rowGenerator()])
expect(mockedDeleteFiles).toHaveBeenCalledWith(BUCKET, [FILE_NAME])
})
it("should handle row deletion and not throw when attachments are undefined", async () => {
await AttachmentCleanup.rowDelete(tableGenerator(), [
{
multipleAttachments: undefined,
},
])
})
it("shouldn't cleanup attachments if row not updated", async () => {
await AttachmentCleanup.rowUpdate(tableGenerator(), {
row: rowGenerator(),
oldRow: rowGenerator(),
})
expect(mockedDeleteFiles).not.toHaveBeenCalled()
})
it("should be able to cleanup a column and not throw when attachments are undefined", async () => {
const originalTable = tableGenerator()
delete originalTable.schema["attach"]
await AttachmentCleanup.tableUpdate(
originalTable,
[rowGenerator("file 1"), { attach: undefined }, rowGenerator("file 2")],
{
oldTable: tableGenerator(),
}
)
expect(mockedDeleteFiles).toHaveBeenCalledTimes(1)
expect(mockedDeleteFiles).toHaveBeenCalledWith(BUCKET, [
"file 1",
"file 2",
])
})
it("should be able to cleanup a column and not throw when ALL attachments are undefined", async () => {
const originalTable = tableGenerator()
delete originalTable.schema["attach"]
await AttachmentCleanup.tableUpdate(
originalTable,
[{}, { attach: undefined }],
{
oldTable: tableGenerator(),
}
)
expect(mockedDeleteFiles).not.toHaveBeenCalled()
})
}
)