From 110de112c4224aa63cab2c345b76eab4be53c8d7 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Mon, 3 Mar 2025 11:27:38 +0000 Subject: [PATCH 1/6] Fix test flake. --- .../src/api/controllers/view/exporters.ts | 2 +- packages/server/src/utilities/schema.ts | 18 ++---------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/packages/server/src/api/controllers/view/exporters.ts b/packages/server/src/api/controllers/view/exporters.ts index 76e5f865a3..94487e4dd1 100644 --- a/packages/server/src/api/controllers/view/exporters.ts +++ b/packages/server/src/api/controllers/view/exporters.ts @@ -26,7 +26,7 @@ export function csv( headers.map(header => { const val = row[header] if (typeof val === "object" && !(val instanceof Date)) { - return `"${JSON.stringify(val).replace(/"/g, "'")}"` + return `"${escapeCsvString(JSON.stringify(val))}"` } if (val !== undefined) { return `"${escapeCsvString(val.toString())}"` diff --git a/packages/server/src/utilities/schema.ts b/packages/server/src/utilities/schema.ts index b13999c842..eca74e32b7 100644 --- a/packages/server/src/utilities/schema.ts +++ b/packages/server/src/utilities/schema.ts @@ -270,20 +270,6 @@ function parseJsonExport(value: any) { if (typeof value !== "string") { return value } - try { - const parsed = JSON.parse(value) - - return parsed as T - } catch (e: any) { - if ( - e.message.startsWith("Expected property name or '}' in JSON at position ") - ) { - // This was probably converted as CSV and it has single quotes instead of double ones - const parsed = JSON.parse(value.replace(/'/g, '"')) - return parsed as T - } - - // It is no a valid JSON - throw e - } + const parsed = JSON.parse(value) + return parsed as T } From 9f2b543896be7fab99cccb55de4018e6e3ee3411 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Mon, 3 Mar 2025 12:15:54 +0000 Subject: [PATCH 2/6] Delete airtable.spec.ts. --- .../src/integrations/tests/airtable.spec.ts | 76 ------------------- 1 file changed, 76 deletions(-) delete mode 100644 packages/server/src/integrations/tests/airtable.spec.ts diff --git a/packages/server/src/integrations/tests/airtable.spec.ts b/packages/server/src/integrations/tests/airtable.spec.ts deleted file mode 100644 index 367e31e8a0..0000000000 --- a/packages/server/src/integrations/tests/airtable.spec.ts +++ /dev/null @@ -1,76 +0,0 @@ -import { default as AirtableIntegration } from "../airtable" - -jest.mock("airtable") - -class TestConfiguration { - integration: any - client: any - - constructor(config: any = {}) { - this.integration = new AirtableIntegration.integration(config) - this.client = { - create: jest.fn(), - select: jest.fn(() => ({ - firstPage: jest.fn(() => []), - })), - update: jest.fn(), - destroy: jest.fn(), - } - this.integration.client = () => this.client - } -} - -describe("Airtable Integration", () => { - let config: any - - beforeEach(() => { - config = new TestConfiguration() - }) - - it("calls the create method with the correct params", async () => { - await config.integration.create({ - table: "test", - json: {}, - }) - expect(config.client.create).toHaveBeenCalledWith([ - { - fields: {}, - }, - ]) - }) - - it("calls the read method with the correct params", async () => { - await config.integration.read({ - table: "test", - view: "Grid view", - }) - expect(config.client.select).toHaveBeenCalledWith({ - maxRecords: 10, - view: "Grid view", - }) - }) - - it("calls the update method with the correct params", async () => { - await config.integration.update({ - table: "table", - id: "123", - json: { - name: "test", - }, - }) - expect(config.client.update).toHaveBeenCalledWith([ - { - id: "123", - fields: { name: "test" }, - }, - ]) - }) - - it("calls the delete method with the correct params", async () => { - const ids = [1, 2, 3, 4] - await config.integration.delete({ - ids, - }) - expect(config.client.destroy).toHaveBeenCalledWith(ids) - }) -}) From fd8929daaece594bf10316da7a192a1cdcd3d150 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Mon, 3 Mar 2025 14:29:17 +0000 Subject: [PATCH 3/6] Fix tests, reinstate old workaround. --- .../server/src/api/routes/tests/table.spec.ts | 5 +--- packages/server/src/utilities/schema.ts | 24 +++++++++++++++++-- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/packages/server/src/api/routes/tests/table.spec.ts b/packages/server/src/api/routes/tests/table.spec.ts index 29b576d16a..6f790df9ad 100644 --- a/packages/server/src/api/routes/tests/table.spec.ts +++ b/packages/server/src/api/routes/tests/table.spec.ts @@ -1246,10 +1246,7 @@ if (descriptions.length) { }) describe.each([ - [ - RowExportFormat.CSV, - (val: any) => JSON.stringify(val).replace(/"/g, "'"), - ], + [RowExportFormat.CSV, (val: any) => JSON.stringify(val)], [RowExportFormat.JSON, (val: any) => val], ])("import validation (%s)", (_, userParser) => { const basicSchema: TableSchema = { diff --git a/packages/server/src/utilities/schema.ts b/packages/server/src/utilities/schema.ts index eca74e32b7..8309014a61 100644 --- a/packages/server/src/utilities/schema.ts +++ b/packages/server/src/utilities/schema.ts @@ -270,6 +270,26 @@ function parseJsonExport(value: any) { if (typeof value !== "string") { return value } - const parsed = JSON.parse(value) - return parsed as T + + try { + const parsed = JSON.parse(value) + + return parsed as T + } catch (e: any) { + if ( + e.message.startsWith("Expected property name or '}' in JSON at position ") + ) { + // In order to store JSON within CSVs what we used to do is replace double + // quotes with single quotes. This results in invalid JSON, so the line + // below is a workaround to parse it. However, this method of storing JSON + // was never valid, and we don't do it anymore. However, people may have + // exported data and stored it, hoping to be able to restore it later, so + // we leave this in place to support that. + const parsed = JSON.parse(value.replace(/'/g, '"')) + return parsed as T + } + + // It is not valid JSON + throw e + } } From 28d3c18aba1a11ade75b78bad193cc5ab0723dc0 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Mon, 3 Mar 2025 14:44:07 +0000 Subject: [PATCH 4/6] Fix row.spec.ts --- packages/server/src/api/routes/tests/row.spec.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/server/src/api/routes/tests/row.spec.ts b/packages/server/src/api/routes/tests/row.spec.ts index b349a1df8a..5af839c654 100644 --- a/packages/server/src/api/routes/tests/row.spec.ts +++ b/packages/server/src/api/routes/tests/row.spec.ts @@ -2515,15 +2515,14 @@ if (descriptions.length) { csvString: exportedValue, }) - const stringified = (value: string) => - JSON.stringify(value).replace(/"/g, "'") + const stringified = (value: string) => JSON.stringify(value) const matchingObject = ( key: string, value: any, isArray: boolean ) => { - const objectMatcher = `{'${key}':'${value[key]}'.*?}` + const objectMatcher = `{\"${key}\":\"${value[key]}\".*?}` if (isArray) { return expect.stringMatching( new RegExp(`^\\[${objectMatcher}\\]$`) From 1d0d1f895a893a030f2027e822554ead98b0a694 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Mon, 3 Mar 2025 14:59:44 +0000 Subject: [PATCH 5/6] Fix lint. --- packages/server/src/api/routes/tests/row.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/server/src/api/routes/tests/row.spec.ts b/packages/server/src/api/routes/tests/row.spec.ts index 5af839c654..3a732cc662 100644 --- a/packages/server/src/api/routes/tests/row.spec.ts +++ b/packages/server/src/api/routes/tests/row.spec.ts @@ -2522,7 +2522,7 @@ if (descriptions.length) { value: any, isArray: boolean ) => { - const objectMatcher = `{\"${key}\":\"${value[key]}\".*?}` + const objectMatcher = `{"${key}":"${value[key]}".*?}` if (isArray) { return expect.stringMatching( new RegExp(`^\\[${objectMatcher}\\]$`) From 210e7e0c37e791a3555a125db45c13b2e1bb1ab5 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Mon, 3 Mar 2025 16:13:52 +0000 Subject: [PATCH 6/6] Remove redis mock from application.spec.ts. --- .../server/src/api/routes/tests/application.spec.ts | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/packages/server/src/api/routes/tests/application.spec.ts b/packages/server/src/api/routes/tests/application.spec.ts index cff205bbfa..e0b295f78e 100644 --- a/packages/server/src/api/routes/tests/application.spec.ts +++ b/packages/server/src/api/routes/tests/application.spec.ts @@ -1,19 +1,6 @@ import { DEFAULT_TABLES } from "../../../db/defaultData/datasource_bb_default" import { setEnv } from "../../../environment" -jest.mock("../../../utilities/redis", () => ({ - init: jest.fn(), - getLocksById: () => { - return {} - }, - doesUserHaveLock: () => { - return true - }, - updateLock: jest.fn(), - setDebounce: jest.fn(), - checkDebounce: jest.fn(), - shutdown: jest.fn(), -})) import { checkBuilderEndpoint } from "./utilities/TestFunctions" import * as setup from "./utilities" import { AppStatus } from "../../../db/utils"