import { describe, expect, test } from "bun:test"; // --------------------------------------------------------------------------- // Slice 1: buildSocialProviders — conditional provider registration // // Public interface under test: buildSocialProviders(env) → object // Behaviour: only registers providers whose env vars are all present. // --------------------------------------------------------------------------- import { buildSocialProviders } from "@/lib/build-social-providers"; describe("buildSocialProviders", () => { test("returns empty object when no OAuth env vars are set", () => { const result = buildSocialProviders({}); expect(result).toEqual({}); }); test("registers google when both Google vars are present", () => { const result = buildSocialProviders({ AUTH_GOOGLE_CLIENT_ID: "gid", AUTH_GOOGLE_CLIENT_SECRET: "gsecret", }); expect(result).toHaveProperty("google"); expect(result.google).toMatchObject({ clientId: "gid", clientSecret: "gsecret", }); }); test("does NOT register google when only clientId is present", () => { const result = buildSocialProviders({ AUTH_GOOGLE_CLIENT_ID: "gid", }); expect(result).not.toHaveProperty("google"); }); test("does NOT register google when only clientSecret is present", () => { const result = buildSocialProviders({ AUTH_GOOGLE_CLIENT_SECRET: "gsecret", }); expect(result).not.toHaveProperty("google"); }); test("registers apple when all four Apple vars are present", () => { const result = buildSocialProviders({ AUTH_APPLE_CLIENT_ID: "aid", AUTH_APPLE_CLIENT_SECRET: "asecret", AUTH_APPLE_TEAM_ID: "TEAM1", AUTH_APPLE_KEY_ID: "KEY1", AUTH_APPLE_PRIVATE_KEY: "-----BEGIN PRIVATE KEY-----\nfake\n-----END PRIVATE KEY-----", }); expect(result).toHaveProperty("apple"); expect(result.apple).toMatchObject({ clientId: "aid", clientSecret: "asecret", }); }); test("does NOT register apple when any Apple var is missing", () => { const result = buildSocialProviders({ AUTH_APPLE_CLIENT_ID: "aid", AUTH_APPLE_CLIENT_SECRET: "asecret", AUTH_APPLE_TEAM_ID: "TEAM1", // AUTH_APPLE_KEY_ID missing AUTH_APPLE_PRIVATE_KEY: "-----BEGIN PRIVATE KEY-----\nfake\n-----END PRIVATE KEY-----", }); expect(result).not.toHaveProperty("apple"); }); test("registers both google and apple when all vars are present", () => { const result = buildSocialProviders({ AUTH_GOOGLE_CLIENT_ID: "gid", AUTH_GOOGLE_CLIENT_SECRET: "gsecret", AUTH_APPLE_CLIENT_ID: "aid", AUTH_APPLE_CLIENT_SECRET: "asecret", AUTH_APPLE_TEAM_ID: "TEAM1", AUTH_APPLE_KEY_ID: "KEY1", AUTH_APPLE_PRIVATE_KEY: "-----BEGIN PRIVATE KEY-----\nfake\n-----END PRIVATE KEY-----", }); expect(result).toHaveProperty("google"); expect(result).toHaveProperty("apple"); }); }); // --------------------------------------------------------------------------- // Slice 2: auth-client — signIn.social is available // // Public interface under test: authClient.signIn.social // Behaviour: the function exists and is callable (no plugin wiring needed // for socialProviders on the client — it's built into createAuthClient). // --------------------------------------------------------------------------- import { authClient } from "@/lib/auth-client"; describe("authClient", () => { test("exposes signIn.social as a function", () => { expect(typeof authClient.signIn.social).toBe("function"); }); test("exposes useSession hook", () => { expect(typeof authClient.useSession).toBe("function"); }); }); // --------------------------------------------------------------------------- // Slice 3: getSignInProviders — sign-in page provider list // // Public interface under test: getSignInProviders() // Behaviour: returns the ordered list of available sign-in providers with // their labels and ids, based on which env vars are configured. // The component consumes this list to render buttons — testing the list // verifies the button-to-provider mapping without needing a DOM. // --------------------------------------------------------------------------- import { getSignInProviders } from "@/lib/get-sign-in-providers"; describe("getSignInProviders", () => { test("returns authentik when Authentik vars are set", () => { const providers = getSignInProviders({ AUTH_AUTHENTIK_CLIENT_ID: "id", AUTH_AUTHENTIK_CLIENT_SECRET: "secret", AUTH_AUTHENTIK_ISSUER: "https://auth.example.com", }); const ids = providers.map((p) => p.id); expect(ids).toContain("authentik"); }); test("returns google when Google vars are set", () => { const providers = getSignInProviders({ AUTH_GOOGLE_CLIENT_ID: "gid", AUTH_GOOGLE_CLIENT_SECRET: "gsecret", }); const ids = providers.map((p) => p.id); expect(ids).toContain("google"); }); test("returns apple when Apple vars are set", () => { const providers = getSignInProviders({ AUTH_APPLE_CLIENT_ID: "aid", AUTH_APPLE_CLIENT_SECRET: "asecret", AUTH_APPLE_TEAM_ID: "TEAM1", AUTH_APPLE_KEY_ID: "KEY1", AUTH_APPLE_PRIVATE_KEY: "-----BEGIN PRIVATE KEY-----\nfake\n-----END PRIVATE KEY-----", }); const ids = providers.map((p) => p.id); expect(ids).toContain("apple"); }); test("returns empty list when no vars are set", () => { const providers = getSignInProviders({}); expect(providers).toHaveLength(0); }); test("each provider has id, label, and signInMethod", () => { const providers = getSignInProviders({ AUTH_GOOGLE_CLIENT_ID: "gid", AUTH_GOOGLE_CLIENT_SECRET: "gsecret", }); expect(providers[0]).toMatchObject({ id: expect.any(String), label: expect.any(String), signInMethod: expect.any(String), }); }); test("google provider uses 'social' signInMethod", () => { const providers = getSignInProviders({ AUTH_GOOGLE_CLIENT_ID: "gid", AUTH_GOOGLE_CLIENT_SECRET: "gsecret", }); const google = providers.find((p) => p.id === "google"); expect(google?.signInMethod).toBe("social"); }); test("apple provider uses 'social' signInMethod", () => { const providers = getSignInProviders({ AUTH_APPLE_CLIENT_ID: "aid", AUTH_APPLE_CLIENT_SECRET: "asecret", AUTH_APPLE_TEAM_ID: "TEAM1", AUTH_APPLE_KEY_ID: "KEY1", AUTH_APPLE_PRIVATE_KEY: "-----BEGIN PRIVATE KEY-----\nfake\n-----END PRIVATE KEY-----", }); const apple = providers.find((p) => p.id === "apple"); expect(apple?.signInMethod).toBe("social"); }); test("authentik provider uses 'oauth2' signInMethod", () => { const providers = getSignInProviders({ AUTH_AUTHENTIK_CLIENT_ID: "id", AUTH_AUTHENTIK_CLIENT_SECRET: "secret", AUTH_AUTHENTIK_ISSUER: "https://auth.example.com", }); const authentik = providers.find((p) => p.id === "authentik"); expect(authentik?.signInMethod).toBe("oauth2"); }); });