From d7e07bb44aaca857383e913e156a3254948c5978 Mon Sep 17 00:00:00 2001 From: Sam Rose Date: Wed, 7 Aug 2024 17:33:47 +0100 Subject: [PATCH] Fix worker tests. --- .../src/features/tests/features.spec.ts | 14 ++++++- .../middleware/passport/sso/tests/sso.spec.ts | 2 +- .../src/api/routes/global/tests/auth.spec.ts | 29 +++++++------ .../api/routes/global/tests/realEmail.spec.ts | 42 +++++++++++++------ packages/worker/src/tests/api/configs.ts | 2 +- packages/worker/src/tests/jestSetup.ts | 16 +++++-- 6 files changed, 70 insertions(+), 35 deletions(-) diff --git a/packages/backend-core/src/features/tests/features.spec.ts b/packages/backend-core/src/features/tests/features.spec.ts index de40e24b3c..25e9765287 100644 --- a/packages/backend-core/src/features/tests/features.spec.ts +++ b/packages/backend-core/src/features/tests/features.spec.ts @@ -71,7 +71,7 @@ describe("feature flags", () => { ({ tenant, flags, expected }) => context.doInTenant(tenant, () => withEnv({ TENANT_FEATURE_FLAGS: flags }, () => - expect(fetch()).rejects.toThrow(expected) + expect(fetch).rejects.toThrow(expected) ) ) ) @@ -159,5 +159,17 @@ describe("feature flags", () => { expect(flags._TEST_NUMBER).toBe(123) }) }) + + it("should not fail when a flag is not known", async () => { + mockFlags({ + featureFlags: { + _SOME_RANDOM_FLAG: true, + }, + }) + + await context.doInIdentityContext(identity, async () => { + await expect(fetch()).resolves.not.toThrow() + }) + }) }) }) diff --git a/packages/backend-core/src/middleware/passport/sso/tests/sso.spec.ts b/packages/backend-core/src/middleware/passport/sso/tests/sso.spec.ts index 9fa82b6594..62b71055d9 100644 --- a/packages/backend-core/src/middleware/passport/sso/tests/sso.spec.ts +++ b/packages/backend-core/src/middleware/passport/sso/tests/sso.spec.ts @@ -1,4 +1,4 @@ -import { structures, mocks } from "../../../../../tests" +import { structures } from "../../../../../tests" import { testEnv } from "../../../../../tests/extra" import { SSOAuthDetails, User } from "@budibase/types" diff --git a/packages/worker/src/api/routes/global/tests/auth.spec.ts b/packages/worker/src/api/routes/global/tests/auth.spec.ts index 3f2b3045de..9a004497c7 100644 --- a/packages/worker/src/api/routes/global/tests/auth.spec.ts +++ b/packages/worker/src/api/routes/global/tests/auth.spec.ts @@ -292,9 +292,9 @@ describe("/api/global/auth", () => { it("redirects to auth provider", async () => { nock("http://someconfigurl").get("/").times(1).reply(200, { issuer: "test", - authorization_endpoint: "http://localhost/auth", - token_endpoint: "http://localhost/token", - userinfo_endpoint: "http://localhost/userinfo", + authorization_endpoint: "http://example.com/auth", + token_endpoint: "http://example.com/token", + userinfo_endpoint: "http://example.com/userinfo", }) const configId = await generateOidcConfig() @@ -305,7 +305,7 @@ describe("/api/global/auth", () => { const location: string = res.get("location") expect( location.startsWith( - `http://localhost/auth?response_type=code&client_id=clientId&redirect_uri=http%3A%2F%2Flocalhost%3A10000%2Fapi%2Fglobal%2Fauth%2F${config.tenantId}%2Foidc%2Fcallback&scope=openid%20profile%20email%20offline_access` + `http://example.com/auth?response_type=code&client_id=clientId&redirect_uri=http%3A%2F%2Flocalhost%3A10000%2Fapi%2Fglobal%2Fauth%2F${config.tenantId}%2Foidc%2Fcallback&scope=openid%20profile%20email%20offline_access` ) ).toBe(true) }) @@ -313,11 +313,13 @@ describe("/api/global/auth", () => { describe("GET /api/global/auth/:tenantId/oidc/callback", () => { it("logs in", async () => { + const email = `${generator.guid()}@example.com` + nock("http://someconfigurl").get("/").times(2).reply(200, { issuer: "test", - authorization_endpoint: "http://localhost/auth", - token_endpoint: "http://localhost/token", - userinfo_endpoint: "http://localhost/userinfo", + authorization_endpoint: "http://example.com/auth", + token_endpoint: "http://example.com/token", + userinfo_endpoint: "http://example.com/userinfo", }) const token = jwt.sign( @@ -326,20 +328,20 @@ describe("/api/global/auth", () => { sub: "sub", aud: "clientId", exp: Math.floor(Date.now() / 1000) + 60 * 60, - email: "oauth@example.com", + email, }, "secret" ) - nock("http://localhost").post("/token").reply(200, { + nock("http://example.com").post("/token").reply(200, { access_token: "access", refresh_token: "refresh", id_token: token, }) - nock("http://localhost").get("/userinfo?schema=openid").reply(200, { + nock("http://example.com").get("/userinfo?schema=openid").reply(200, { sub: "sub", - email: "oauth@example.com", + email, }) const configId = await generateOidcConfig() @@ -351,10 +353,7 @@ describe("/api/global/auth", () => { ) } - expect(events.auth.login).toHaveBeenCalledWith( - "oidc", - "oauth@example.com" - ) + expect(events.auth.login).toHaveBeenCalledWith("oidc", email) expect(events.auth.login).toHaveBeenCalledTimes(1) expect(res.status).toBe(302) const location: string = res.get("location") diff --git a/packages/worker/src/api/routes/global/tests/realEmail.spec.ts b/packages/worker/src/api/routes/global/tests/realEmail.spec.ts index bea627d5b6..a18d8ee247 100644 --- a/packages/worker/src/api/routes/global/tests/realEmail.spec.ts +++ b/packages/worker/src/api/routes/global/tests/realEmail.spec.ts @@ -12,6 +12,33 @@ const nodemailer = require("nodemailer") // for the real email tests give them a long time to try complete/fail jest.setTimeout(30000) +function cancelableTimeout(timeout: number): [Promise, () => void] { + let timeoutId: NodeJS.Timeout + return [ + new Promise((resolve, reject) => { + timeoutId = setTimeout(() => { + reject({ + status: 301, + errno: "ETIME", + }) + }, timeout) + }), + () => { + clearTimeout(timeoutId) + }, + ] +} + +async function withTimeout( + timeout: number, + promise: Promise +): Promise { + const [timeoutPromise, cancel] = cancelableTimeout(timeout) + const result = (await Promise.race([promise, timeoutPromise])) as T + cancel() + return result +} + describe("/api/global/email", () => { const config = new TestConfiguration() @@ -30,19 +57,8 @@ describe("/api/global/email", () => { ) { let response, text try { - const timeout = () => - new Promise((resolve, reject) => - setTimeout( - () => - reject({ - status: 301, - errno: "ETIME", - }), - 20000 - ) - ) - await Promise.race([config.saveEtherealSmtpConfig(), timeout()]) - await Promise.race([config.saveSettingsConfig(), timeout()]) + await withTimeout(20000, config.saveEtherealSmtpConfig()) + await withTimeout(20000, config.saveSettingsConfig()) let res if (attachments) { res = await config.api.emails diff --git a/packages/worker/src/tests/api/configs.ts b/packages/worker/src/tests/api/configs.ts index 74cef2bf8b..86fe0830ca 100644 --- a/packages/worker/src/tests/api/configs.ts +++ b/packages/worker/src/tests/api/configs.ts @@ -40,7 +40,7 @@ export class ConfigAPI extends TestAPI { const sessionContent = JSON.parse( Buffer.from(koaSession, "base64").toString("utf-8") ) - const handle = sessionContent["openidconnect:localhost"].state.handle + const handle = sessionContent["openidconnect:example.com"].state.handle return this.request .get(`/api/global/auth/${this.config.getTenantId()}/oidc/callback`) .query({ code: "test", state: handle }) diff --git a/packages/worker/src/tests/jestSetup.ts b/packages/worker/src/tests/jestSetup.ts index 0f933bd562..6a98031d34 100644 --- a/packages/worker/src/tests/jestSetup.ts +++ b/packages/worker/src/tests/jestSetup.ts @@ -1,13 +1,21 @@ import { mocks, testContainerUtils } from "@budibase/backend-core/tests" import env from "../environment" import { env as coreEnv, timers } from "@budibase/backend-core" - -// must explicitly enable fetch mock -mocks.fetch.enable() +import nock from "nock" // mock all dates to 2020-01-01T00:00:00.000Z // use tk.reset() to use real dates in individual tests -const tk = require("timekeeper") +import tk from "timekeeper" + +nock.disableNetConnect() +nock.enableNetConnect(host => { + return ( + host.includes("localhost") || + host.includes("127.0.0.1") || + host.includes("::1") || + host.includes("ethereal.email") // used in realEmail.spec.ts + ) +}) tk.freeze(mocks.date.MOCK_DATE)