Fixes for existing attachment tests and some coverage for signatures

This commit is contained in:
Dean 2024-04-08 16:51:43 +01:00
parent 9b276aa3c1
commit 8e62aa8945
1 changed files with 196 additions and 20 deletions

View File

@ -1,22 +1,30 @@
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"
import { objectStore, db, context } from "@budibase/backend-core"
import * as uuid from "uuid"
const BUCKET = "prod-budi-app-assets"
const FILE_NAME = "file/thing.jpg"
const DEV_APPID = "abc_dev_123"
const PROD_APPID = "abc_123"
jest.mock("@budibase/backend-core", () => {
const actual = jest.requireActual("@budibase/backend-core")
return {
...actual,
context: {
...actual.context,
getAppId: jest.fn(),
},
objectStore: {
deleteFiles: jest.fn(),
ObjectStoreBuckets: actual.objectStore.ObjectStoreBuckets,
},
db: {
isProdAppID: () => jest.fn(() => false),
dbExists: () => jest.fn(() => false),
isProdAppID: jest.fn(),
getProdAppID: jest.fn(),
dbExists: jest.fn(),
},
}
})
@ -37,11 +45,28 @@ function table(): Table {
type: FieldType.ATTACHMENT,
constraints: {},
},
signature: {
name: "signature",
type: FieldType.SIGNATURE,
constraints: {},
},
},
}
}
function row(fileKey: string = FILE_NAME): Row {
function rowSignature(fieldName: string = "signature") {
return {
[fieldName]: [
{
size: 1,
extension: "png",
key: `${uuid.v4()}.png`,
},
],
}
}
function rowAttachment(fileKey: string = FILE_NAME): Row {
return {
attach: [
{
@ -53,56 +78,154 @@ function row(fileKey: string = FILE_NAME): Row {
}
}
describe("attachment cleanup", () => {
describe("attachment/signature cleanup", () => {
beforeEach(() => {
mockedDeleteFiles.mockClear()
jest.resetAllMocks()
jest.spyOn(context, "getAppId").mockReturnValue(DEV_APPID)
jest.spyOn(db, "isProdAppID").mockReturnValue(false)
jest.spyOn(db, "getProdAppID").mockReturnValue(PROD_APPID)
jest.spyOn(db, "dbExists").mockReturnValue(Promise.resolve(false))
})
// Ignore calls to prune attachments when app is in production.
it("should not attempt to delete attachments/signatures if a published app exists", async () => {
jest.spyOn(db, "dbExists").mockReturnValue(Promise.resolve(true))
const targetRow = {
...rowAttachment(),
...rowSignature(),
}
const originalTable = table()
delete originalTable.schema["attach"]
await AttachmentCleanup.tableUpdate(originalTable, [targetRow], {
oldTable: table(),
})
expect(mockedDeleteFiles).not.toHaveBeenCalled()
})
it("should be able to cleanup a table update", async () => {
const originalTable = table()
delete originalTable.schema["attach"]
await AttachmentCleanup.tableUpdate(originalTable, [row()], {
await AttachmentCleanup.tableUpdate(originalTable, [rowAttachment()], {
oldTable: table(),
})
expect(mockedDeleteFiles).toHaveBeenCalledWith(BUCKET, [FILE_NAME])
})
it("should be able to cleanup a table deletion", async () => {
await AttachmentCleanup.tableDelete(table(), [row()])
expect(mockedDeleteFiles).toHaveBeenCalledWith(BUCKET, [FILE_NAME])
const targetRow = {
...rowAttachment(),
...rowSignature(),
}
await AttachmentCleanup.tableDelete(table(), [targetRow])
expect(mockedDeleteFiles).toHaveBeenCalledWith(BUCKET, [
FILE_NAME,
targetRow.signature[0].key,
])
})
it("should handle table column renaming", async () => {
it("should handle table attachment column renaming", async () => {
const targetRow = {
...rowAttachment(),
...rowSignature(),
}
const updatedTable = table()
updatedTable.schema.attach2 = updatedTable.schema.attach
delete updatedTable.schema.attach
await AttachmentCleanup.tableUpdate(updatedTable, [row()], {
await AttachmentCleanup.tableUpdate(updatedTable, [targetRow], {
oldTable: table(),
rename: { old: "attach", updated: "attach2" },
})
expect(mockedDeleteFiles).not.toHaveBeenCalled()
})
it("shouldn't cleanup if no table changes", async () => {
await AttachmentCleanup.tableUpdate(table(), [row()], { oldTable: table() })
it("should handle table signature column renaming", async () => {
const targetRow = {
...rowAttachment(),
...rowSignature(),
}
const updatedTable = table()
updatedTable.schema.signaturex = updatedTable.schema.signature
delete updatedTable.schema.signature
await AttachmentCleanup.tableUpdate(updatedTable, [targetRow], {
oldTable: table(),
rename: { old: "signature", updated: "signaturex" },
})
expect(mockedDeleteFiles).not.toHaveBeenCalled()
})
it("should handle row updates", async () => {
const updatedRow = row()
it("shouldn't cleanup if no table changes", async () => {
const targetRow = {
...rowAttachment(),
...rowSignature(),
}
await AttachmentCleanup.tableUpdate(table(), [targetRow], {
oldTable: table(),
})
expect(mockedDeleteFiles).not.toHaveBeenCalled()
})
it("should handle row updates, remove attachment", async () => {
const targetRow = {
...rowAttachment(),
...rowSignature(),
}
const updatedRow = targetRow
delete updatedRow.attach
await AttachmentCleanup.rowUpdate(table(), {
row: updatedRow,
oldRow: row(),
oldRow: rowAttachment(),
})
expect(mockedDeleteFiles).toHaveBeenCalledWith(BUCKET, [FILE_NAME])
})
it("should handle row deletion", async () => {
await AttachmentCleanup.rowDelete(table(), [row()])
it("should handle row updates, remove signature", async () => {
const targetRow = {
...rowAttachment(),
...rowSignature(),
}
const updatedRow = { ...targetRow }
delete updatedRow.signature
await AttachmentCleanup.rowUpdate(table(), {
row: updatedRow,
oldRow: targetRow,
})
expect(mockedDeleteFiles).toHaveBeenCalledWith(BUCKET, [
targetRow.signature[0].key,
])
})
it("should handle row deletion, prune attachment", async () => {
const targetRow = {
...rowAttachment(),
}
await AttachmentCleanup.rowDelete(table(), [targetRow])
expect(mockedDeleteFiles).toHaveBeenCalledWith(BUCKET, [FILE_NAME])
})
it("should handle row deletion, prune signature", async () => {
const targetRow = {
...rowSignature(),
}
await AttachmentCleanup.rowDelete(table(), [targetRow])
expect(mockedDeleteFiles).toHaveBeenCalledWith(BUCKET, [
targetRow.signature[0].key,
])
})
it("should handle row deletion, prune attachment AND signature", async () => {
const targetRow = {
...rowAttachment(),
...rowSignature(),
}
await AttachmentCleanup.rowDelete(table(), [targetRow])
expect(mockedDeleteFiles).toHaveBeenCalledWith(BUCKET, [
FILE_NAME,
targetRow.signature[0].key,
])
})
it("should handle row deletion and not throw when attachments are undefined", async () => {
await AttachmentCleanup.rowDelete(table(), [
{
@ -111,8 +234,28 @@ describe("attachment cleanup", () => {
])
})
it("shouldn't cleanup attachments if row not updated", async () => {
await AttachmentCleanup.rowUpdate(table(), { row: row(), oldRow: row() })
it("should handle row deletion and not throw when signatures are undefined", async () => {
await AttachmentCleanup.rowDelete(table(), [
{
signature: undefined,
},
])
})
it("shouldn't cleanup attachments if row isn't updated", async () => {
await AttachmentCleanup.rowUpdate(table(), {
row: rowAttachment(),
oldRow: rowAttachment(),
})
expect(mockedDeleteFiles).not.toHaveBeenCalled()
})
it("shouldn't cleanup signature if row isn't updated", async () => {
const targetRow = rowSignature()
await AttachmentCleanup.rowUpdate(table(), {
row: targetRow,
oldRow: targetRow,
})
expect(mockedDeleteFiles).not.toHaveBeenCalled()
})
@ -121,7 +264,7 @@ describe("attachment cleanup", () => {
delete originalTable.schema["attach"]
await AttachmentCleanup.tableUpdate(
originalTable,
[row("file 1"), { attach: undefined }, row("file 2")],
[rowAttachment("file 1"), { attach: undefined }, rowAttachment("file 2")],
{
oldTable: table(),
}
@ -130,6 +273,26 @@ describe("attachment cleanup", () => {
expect(mockedDeleteFiles).toHaveBeenCalledWith(BUCKET, ["file 1", "file 2"])
})
it("should be able to cleanup a column and not throw when signatures are undefined", async () => {
const originalTable = table()
delete originalTable.schema["signature"]
const sig1 = rowSignature()
const sig2 = rowSignature()
await AttachmentCleanup.tableUpdate(
originalTable,
[sig1, { signature: undefined }, sig2],
{
oldTable: table(),
}
)
expect(mockedDeleteFiles).toHaveBeenCalledTimes(1)
expect(mockedDeleteFiles).toHaveBeenCalledWith(BUCKET, [
sig1.signature[0].key,
sig2.signature[0].key,
])
})
it("should be able to cleanup a column and not throw when ALL attachments are undefined", async () => {
const originalTable = table()
delete originalTable.schema["attach"]
@ -142,4 +305,17 @@ describe("attachment cleanup", () => {
)
expect(mockedDeleteFiles).not.toHaveBeenCalled()
})
it("should be able to cleanup a column and not throw when ALL signatures are undefined", async () => {
const originalTable = table()
delete originalTable.schema["signature"]
await AttachmentCleanup.tableUpdate(
originalTable,
[{}, { signature: undefined }],
{
oldTable: table(),
}
)
expect(mockedDeleteFiles).not.toHaveBeenCalled()
})
})