From e7044080c59a15e42e3f4b9fdd2dd7279d4b2274 Mon Sep 17 00:00:00 2001 From: Konstantin Wohlwend Date: Mon, 23 Dec 2024 14:02:59 -0800 Subject: [PATCH] Create fewer projects in unit tests --- .vscode/settings.json | 1 + apps/e2e/tests/backend/backend-helpers.ts | 53 ++++++------ .../contact-channels/contact-channels.test.ts | 38 +++------ .../backend/endpoints/api/v1/projects.test.ts | 22 ++--- .../endpoints/api/v1/team-invitations.test.ts | 12 +-- .../api/v1/team-member-profiles.test.ts | 6 +- .../endpoints/api/v1/team-memberships.test.ts | 21 ++--- .../backend/endpoints/api/v1/teams.test.ts | 18 ++-- .../backend/endpoints/api/v1/users.test.ts | 82 +++++++++++++++---- apps/e2e/tests/helpers.ts | 30 ++++++- 10 files changed, 164 insertions(+), 119 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 81fb89d64..d60084c8d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -73,6 +73,7 @@ "typecheck", "typehack", "Uncapitalize", + "unindexed", "unsubscribers", "upsert", "webapi", diff --git a/apps/e2e/tests/backend/backend-helpers.ts b/apps/e2e/tests/backend/backend-helpers.ts index 0a08046ee..20c5c6c78 100644 --- a/apps/e2e/tests/backend/backend-helpers.ts +++ b/apps/e2e/tests/backend/backend-helpers.ts @@ -2,15 +2,16 @@ import { InternalProjectsCrud } from "@stackframe/stack-shared/dist/interface/cr import { encodeBase64 } from "@stackframe/stack-shared/dist/utils/bytes"; import { generateSecureRandomString } from "@stackframe/stack-shared/dist/utils/crypto"; import { StackAssertionError, throwErr } from "@stackframe/stack-shared/dist/utils/errors"; -import { filterUndefined, omit } from "@stackframe/stack-shared/dist/utils/objects"; +import { filterUndefined } from "@stackframe/stack-shared/dist/utils/objects"; import { nicify } from "@stackframe/stack-shared/dist/utils/strings"; import * as jose from "jose"; import { randomUUID } from "node:crypto"; import { expect } from "vitest"; -import { Context, INBUCKET_API_URL, Mailbox, MailboxMessage, NiceRequestInit, NiceResponse, STACK_BACKEND_BASE_URL, STACK_INTERNAL_PROJECT_ADMIN_KEY, STACK_INTERNAL_PROJECT_CLIENT_KEY, STACK_INTERNAL_PROJECT_ID, STACK_INTERNAL_PROJECT_SERVER_KEY, generatedEmailSuffix, localRedirectUrl, niceFetch, updateCookiesFromResponse } from "../helpers"; +import { Context, Mailbox, NiceRequestInit, NiceResponse, STACK_BACKEND_BASE_URL, STACK_INTERNAL_PROJECT_ADMIN_KEY, STACK_INTERNAL_PROJECT_CLIENT_KEY, STACK_INTERNAL_PROJECT_ID, STACK_INTERNAL_PROJECT_SERVER_KEY, generatedEmailSuffix, localRedirectUrl, niceFetch, updateCookiesFromResponse } from "../helpers"; type BackendContext = { readonly projectKeys: ProjectKeys, + readonly defaultProjectKeys: ProjectKeys, readonly mailbox: Mailbox, readonly userAuth: { readonly refreshToken?: string, @@ -30,6 +31,7 @@ type BackendContext = { export const backendContext = new Context>( () => ({ + defaultProjectKeys: InternalProjectKeys, projectKeys: InternalProjectKeys, mailbox: createMailbox(`default-mailbox--${randomUUID()}${generatedEmailSuffix}`), generatedMailboxNamesCount: 0, @@ -37,6 +39,12 @@ export const backendContext = new Context { + if ("defaultProjectKeys" in update) { + throw new StackAssertionError("Cannot set defaultProjectKeys"); + } + if ("mailbox" in update && !(update.mailbox instanceof Mailbox)) { + throw new StackAssertionError("Must create a mailbox with createMailbox()!"); + } return { ...acc, ...update, @@ -50,26 +58,7 @@ export function createMailbox(email?: string): Mailbox { email = `mailbox-${backendContext.value.generatedMailboxNamesCount}--${randomUUID()}${generatedEmailSuffix}`; } if (!email.includes("@")) throw new StackAssertionError(`Invalid mailbox email: ${email}`); - const mailboxName = email.split("@")[0]; - const fullMessageCache = new Map(); - return { - emailAddress: email, - async fetchMessages({ noBody } = {}) { - const res = await niceFetch(new URL(`/api/v1/mailbox/${encodeURIComponent(mailboxName)}`, INBUCKET_API_URL)); - return await Promise.all((res.body as any[]).map(async (message) => { - let fullMessage: any; - if (fullMessageCache.has(message.id)) { - fullMessage = fullMessageCache.get(message.id); - } else { - const fullMessageRes = await niceFetch(new URL(`/api/v1/mailbox/${encodeURIComponent(mailboxName)}/${message.id}`, INBUCKET_API_URL)); - fullMessage = fullMessageRes.body; - fullMessageCache.set(message.id, fullMessage); - } - const messagePart = noBody ? omit(fullMessage, ["body", "attachments"]) : fullMessage; - return new MailboxMessage(messagePart); - })); - }, - }; + return new Mailbox("(we can ignore the disclaimer here)" as any, email); } export type ProjectKeys = "no-project" | { @@ -169,6 +158,19 @@ export async function niceBackendFetch(url: string | URL, options?: Omit { - const response = await niceBackendFetch("/api/v1/auth/passkey/initiate-passkey-registration", { method: "POST", accessType: "client", @@ -925,7 +926,9 @@ export namespace Project { backendContext.set({ projectKeys: InternalProjectKeys, }); - await Auth.Otp.signIn(); + const oldMailbox = backendContext.value.mailbox; + await bumpEmailAddress({ unindexed: true }); + const { userId } = await Auth.Otp.signIn(); const adminAccessToken = backendContext.value.userAuth?.accessToken; expect(adminAccessToken).toBeDefined(); const { projectId, createProjectResponse } = await Project.create(body); @@ -935,9 +938,11 @@ export namespace Project { projectId, }, userAuth: null, + mailbox: oldMailbox, }); return { + creatorUserId: userId, projectId, adminAccessToken: adminAccessToken!, createProjectResponse, diff --git a/apps/e2e/tests/backend/endpoints/api/v1/contact-channels/contact-channels.test.ts b/apps/e2e/tests/backend/endpoints/api/v1/contact-channels/contact-channels.test.ts index 68ffb205d..0fbe724ce 100644 --- a/apps/e2e/tests/backend/endpoints/api/v1/contact-channels/contact-channels.test.ts +++ b/apps/e2e/tests/backend/endpoints/api/v1/contact-channels/contact-channels.test.ts @@ -1,14 +1,14 @@ import { it } from "../../../../../helpers"; -import { Auth, ContactChannels, Project, backendContext, createMailbox, niceBackendFetch } from "../../../../backend-helpers"; +import { Auth, ContactChannels, backendContext, bumpEmailAddress, createMailbox, niceBackendFetch } from "../../../../backend-helpers"; it("create contact channel on the client", async ({ expect }) => { - await Project.createAndSwitch({ config: { magic_link_enabled: true } }); await Auth.Otp.signIn(); + const mailbox = createMailbox(); const response = await niceBackendFetch("/api/v1/contact-channels", { accessType: "client", method: "POST", body: { - value: "test@example.com", + value: mailbox.emailAddress, type: "email", used_for_auth: true, user_id: "me", @@ -24,7 +24,7 @@ it("create contact channel on the client", async ({ expect }) => { "type": "email", "used_for_auth": true, "user_id": "", - "value": "test@example.com", + "value": "mailbox-1--@stack-generated.example.com", }, "headers": Headers {