diff --git a/jestTestcontainersConfigGenerator.js b/jestTestcontainersConfigGenerator.js index 1e39ed771f..82d50145e6 100644 --- a/jestTestcontainersConfigGenerator.js +++ b/jestTestcontainersConfigGenerator.js @@ -10,7 +10,7 @@ module.exports = () => { wait: { type: "ports", timeout: 20000, - } - } + }, + }, } } diff --git a/packages/backend-core/src/db/Replication.ts b/packages/backend-core/src/db/Replication.ts index 9c960d76dd..735c2fa86e 100644 --- a/packages/backend-core/src/db/Replication.ts +++ b/packages/backend-core/src/db/Replication.ts @@ -27,7 +27,7 @@ class Replication { return resolve(info) }) .on("error", function (err) { - throw new Error(`Replication Error: ${err}`) + throw err }) }) } diff --git a/packages/server/jest-testcontainers-config.js b/packages/server/jest-testcontainers-config.js deleted file mode 100644 index 8ac0f0cd9d..0000000000 --- a/packages/server/jest-testcontainers-config.js +++ /dev/null @@ -1,8 +0,0 @@ -const { join } = require("path") -require("dotenv").config({ - path: join(__dirname, "..", "..", "hosting", ".env"), -}) - -const jestTestcontainersConfigGenerator = require("../../jestTestcontainersConfigGenerator") - -module.exports = jestTestcontainersConfigGenerator() diff --git a/packages/server/jest.config.ts b/packages/server/jest.config.ts index 6c6d6a20d3..20979d7999 100644 --- a/packages/server/jest.config.ts +++ b/packages/server/jest.config.ts @@ -18,6 +18,8 @@ const baseConfig: Config.InitialProjectOptions = { "svelte", ], setupFilesAfterEnv: ["./src/tests/jestSetup.ts"], + globalSetup: "./src/tests/globalSetup.ts", + globalTeardown: "./src/tests/globalTeardown.ts", transform: { "^.+\\.ts?$": "@swc/jest", "^.+\\.js?$": "@swc/jest", diff --git a/packages/server/scripts/test.sh b/packages/server/scripts/test.sh index 3ecf8bb794..58e68c9749 100644 --- a/packages/server/scripts/test.sh +++ b/packages/server/scripts/test.sh @@ -1,6 +1,8 @@ #!/bin/bash set -e +export DEBUG="testcontainers*" + if [[ -n $CI ]] then export NODE_OPTIONS="--max-old-space-size=4096 --no-node-snapshot $NODE_OPTIONS" diff --git a/packages/server/src/tests/globalSetup.ts b/packages/server/src/tests/globalSetup.ts new file mode 100644 index 0000000000..1bb61a79d9 --- /dev/null +++ b/packages/server/src/tests/globalSetup.ts @@ -0,0 +1,27 @@ +import { GenericContainer, Wait } from "testcontainers" + +export default async function setup() { + const container = await new GenericContainer("budibase/couchdb") + .withName("couchdb-service") + .withExposedPorts(5984) + .withEnvironment({ + COUCHDB_PASSWORD: "budibase", + COUCHDB_USER: "budibase", + }) + .withCopyFilesToContainer([ + { + source: "./src/tests/test-couchdb.ini", + target: "/opt/couchdb/etc/local.d/test-couchdb.ini", + }, + ]) + .withWaitStrategy( + Wait.forSuccessfulCommand( + "curl http://budibase:budibase@localhost:5984/_up" + ).withStartupTimeout(20000) + ) + .start() + + // @ts-expect-error + // eslint-disable-next-line no-undef + globalThis.__COUCHDB_CONTAINER_ID__ = container.getId() +} diff --git a/packages/server/src/tests/globalTeardown.ts b/packages/server/src/tests/globalTeardown.ts new file mode 100644 index 0000000000..4be959c1f9 --- /dev/null +++ b/packages/server/src/tests/globalTeardown.ts @@ -0,0 +1,12 @@ +import { getContainerRuntimeClient } from "testcontainers" + +export default async function teardown() { + const client = await getContainerRuntimeClient() + + // @ts-expect-error + // eslint-disable-next-line no-undef + const containerId = globalThis.__COUCHDB_CONTAINER_ID__ + const container = client.container.getById(containerId) + await client.container.stop(container) + await client.container.remove(container) +} diff --git a/packages/server/src/tests/jestEnv.ts b/packages/server/src/tests/jestEnv.ts index 7c58470e9b..3b0c2a88d9 100644 --- a/packages/server/src/tests/jestEnv.ts +++ b/packages/server/src/tests/jestEnv.ts @@ -11,3 +11,6 @@ process.env.PLATFORM_URL = "http://localhost:10000" process.env.REDIS_PASSWORD = "budibase" process.env.BUDIBASE_VERSION = "0.0.0+jest" process.env.WORKER_URL = "http://localhost:10000" +process.env.COUCH_DB_PASSWORD = "budibase" +process.env.COUCH_DB_USER = "budibase" +process.env.JWT_SECRET = "jwtsecret" diff --git a/packages/server/src/tests/test-couchdb.ini b/packages/server/src/tests/test-couchdb.ini new file mode 100644 index 0000000000..8924e6ec3f --- /dev/null +++ b/packages/server/src/tests/test-couchdb.ini @@ -0,0 +1,2 @@ +[log] +level = warn \ No newline at end of file diff --git a/packages/server/src/tests/utilities/api/base.ts b/packages/server/src/tests/utilities/api/base.ts index 4df58ff425..486514cfbe 100644 --- a/packages/server/src/tests/utilities/api/base.ts +++ b/packages/server/src/tests/utilities/api/base.ts @@ -187,6 +187,22 @@ export abstract class TestAPI { expect(response.body).toMatchObject(expectations.body) } + if (response.text && response.text.length > 0) { + // @ts-expect-error - we know this exists, it's just not in the types + const request = response.request as Test + const contentLength = response.headers["content-length"] + if (!contentLength) { + throw new Error( + `Failed request "${request.method} ${request.url}": Content-Length header not present, but response has a body (body length ${response.text.length})` + ) + } + if (parseInt(contentLength) !== response.text.length) { + throw new Error( + `Failed request "${request.method} ${request.url}": Content-Length header does not match response body length (header: ${contentLength}, body: ${response.text.length})` + ) + } + } + return response }