96 lines · 3.1 KB · TypeScript
RawDownload
import { describe, expect, it } from "@effect/vitest";import { Effect, Layer } from "effect";import { TenantScope } from "@executor-js/api/server"; import { UserStoreService } from "../../auth/context";import { WorkOSClient, type WorkOSClientService } from "../../auth/workos";import { resolveBillingOrganization } from "./route"; const createdAt = new Date("2026-01-01T00:00:00.000Z"); const MEMBER = "user_session";const SESSION_ORG = "org_session";const URL_ORG = "org_url";const URL_SLUG = "acme"; const stubWorkOS = Layer.succeed(  WorkOSClient,  new Proxy({} as WorkOSClientService, {    get: (_target, prop) => {      if (prop === "listUserMemberships") {        return (userId: string) =>          Effect.succeed({            data:              userId === MEMBER                ? [                    { userId, organizationId: SESSION_ORG, status: "active" },                    { userId, organizationId: URL_ORG, status: "active" },                  ]                : [],          });      }      return () => Effect.die(`unexpected WorkOSClient.${String(prop)} call`);    },  }),); const stubUsers = Layer.succeed(UserStoreService)({  use: (fn) =>    Effect.promise(() =>      fn({        ensureAccount: async (id: string) => ({ id, createdAt }),        getAccount: async (id: string) => ({ id, createdAt }),        upsertOrganization: async (org: { id: string; name: string }) => ({          ...org,          slug: org.id,          createdAt,        }),        getOrganization: async (id: string) => ({ id, name: `Org ${id}`, slug: id, createdAt }),        getOrganizationBySlug: async (slug: string) => ({          id: slug === URL_SLUG ? URL_ORG : "org_outsider",          name: `Org ${slug}`,          slug,          createdAt,        }),      }),    ),}); const run = (tenantSelector?: string, organizationId: string | null = SESSION_ORG) => {  const effect = resolveBillingOrganization({ userId: MEMBER, organizationId });  return (    tenantSelector      ? effect.pipe(Effect.provideService(TenantScope, { selector: tenantSelector }))      : effect  ).pipe(Effect.provide(Layer.mergeAll(stubWorkOS, stubUsers)));}; describe("billing route tenant selector", () => {  it.effect("falls back to the session org when no tenant selector is present", () =>    Effect.gen(function* () {      const org = yield* run();      expect(org.id).toBe(SESSION_ORG);    }),  );   it.effect("scopes billing to the URL tenant selector over the session org", () =>    Effect.gen(function* () {      const org = yield* run(URL_SLUG);      expect(org.id).toBe(URL_ORG);    }),  );   it.effect("rejects a selector for an org the caller is not a member of", () =>    Effect.gen(function* () {      const error = yield* Effect.flip(run("outsider-slug"));      expect(error).toMatchObject({ _tag: "HttpResponseError", status: 403 });    }),  );   it.effect("requires either a tenant selector or a session org", () =>    Effect.gen(function* () {      const error = yield* Effect.flip(run(undefined, null));      expect(error).toMatchObject({ _tag: "HttpResponseError", status: 401 });    }),  );});