stack/apps/e2e/tests/js/oauth-providers.test.ts
BilalG1 609579abab
Some checks failed
all-good: Did all the other checks pass? / all-good (push) Has been cancelled
Ensure Prisma migrations are in sync with the schema / check_prisma_migrations (22.x) (push) Has been cancelled
DB migration compat / Check if migrations changed (push) Has been cancelled
Docker Server Build and Push / Docker Build and Push Server (push) Has been cancelled
Docker Server Build and Run / docker (push) Has been cancelled
Runs E2E API Tests (Local Emulator) / E2E Tests (Local Emulator, Node ${{ matrix.node-version }}) (22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (mock, 22.x) (push) Has been cancelled
Runs E2E API Tests / E2E Tests (Node ${{ matrix.node-version }}, Freestyle ${{ matrix.freestyle-mode }}) (prod, 22.x) (push) Has been cancelled
Runs E2E API Tests with custom port prefix / build (22.x) (push) Has been cancelled
Runs E2E Fallback Tests / E2E Fallback Tests (Node ${{ matrix.node-version }}) (22.x) (push) Has been cancelled
Lint & build / lint_and_build (24) (push) Has been cancelled
TOC Generator / TOC Generator (push) Has been cancelled
DB migration compat / Back-compat — Current branch migrations with ${{ needs.check-migrations-changed.outputs.base_branch }} branch code (push) Has been cancelled
DB migration compat / Forward-compat — Current branch code with ${{ needs.check-migrations-changed.outputs.base_branch }} branch migrations (push) Has been cancelled
DB migration compat / No migration changes (skipped) (push) Has been cancelled
feat(hexclave): PR 3 — native @hexclave/* source rename + delete dual-publish wiring (#1482)
2026-05-29 15:21:59 -07:00

291 lines
9.7 KiB
TypeScript

import { stringCompare } from "@hexclave/shared/dist/utils/strings";
import { describe } from "vitest";
import { it } from "../helpers";
import { createApp } from "./js-helpers";
describe("OAuth Providers Client Functions", () => {
async function createAppsWithOAuth() {
return await createApp({
config: {
magicLinkEnabled: true,
oauthProviders: [
{
id: "spotify",
type: "standard",
clientId: "test_client_id",
clientSecret: "test_client_secret",
},
{
id: "github",
type: "standard",
clientId: "test_github_client_id",
clientSecret: "test_github_client_secret",
}
]
}
});
}
it("should list OAuth providers for current user", async ({ expect }) => {
const apps = await createAppsWithOAuth();
const user = await apps.serverApp.createUser({
primaryEmail: "test@example.com",
password: "password123",
primaryEmailAuthEnabled: true,
});
await apps.serverApp.createOAuthProvider({
userId: user.id,
providerConfigId: "spotify",
accountId: "spotify_user_123",
email: "test@example.com",
allowSignIn: true,
allowConnectedAccounts: true,
});
await apps.serverApp.createOAuthProvider({
userId: user.id,
providerConfigId: "github",
accountId: "github_user_456",
email: "test@example.com",
allowSignIn: false,
allowConnectedAccounts: true,
});
await apps.clientApp.signInWithCredential({ email: "test@example.com", password: "password123" });
const currentUser = await apps.clientApp.getUser({ or: "throw" });
const providers = await currentUser.listOAuthProviders();
expect(providers).toHaveLength(2);
const spotifyProvider = providers.find((p) => p.type === "spotify");
const githubProvider = providers.find((p) => p.type === "github");
expect(spotifyProvider).toBeDefined();
expect(spotifyProvider?.allowSignIn).toBe(true);
expect(spotifyProvider?.allowConnectedAccounts).toBe(true);
expect(spotifyProvider?.email).toBe("test@example.com");
expect(githubProvider).toBeDefined();
expect(githubProvider?.allowSignIn).toBe(false);
expect(githubProvider?.allowConnectedAccounts).toBe(true);
expect(githubProvider?.email).toBe("test@example.com");
});
it("should get specific OAuth provider by id", async ({ expect }) => {
const apps = await createAppsWithOAuth();
const user = await apps.serverApp.createUser({
primaryEmail: "test@example.com",
password: "password123",
primaryEmailAuthEnabled: true,
});
const createdProviderResult = await apps.serverApp.createOAuthProvider({
userId: user.id,
providerConfigId: "spotify",
accountId: "spotify_user_123",
email: "test@example.com",
allowSignIn: true,
allowConnectedAccounts: true,
});
if (createdProviderResult.status === "error") {
throw new Error("Failed to create OAuth provider");
}
const createdProvider = createdProviderResult.data!;
await apps.clientApp.signInWithCredential({ email: "test@example.com", password: "password123" });
const currentUser = await apps.clientApp.getUser({ or: "throw" });
const provider = await currentUser.getOAuthProvider(createdProvider.id);
expect(provider).toBeDefined();
expect(provider?.id).toBe(createdProvider.id);
expect(provider?.type).toBe("spotify");
expect(provider?.allowSignIn).toBe(true);
expect(provider?.allowConnectedAccounts).toBe(true);
expect(provider?.email).toBe("test@example.com");
});
it("should return null when getting non-existent OAuth provider", async ({ expect }) => {
const apps = await createAppsWithOAuth();
await apps.serverApp.createUser({
primaryEmail: "test@example.com",
password: "password123",
primaryEmailAuthEnabled: true,
});
await apps.clientApp.signInWithCredential({ email: "test@example.com", password: "password123" });
const currentUser = await apps.clientApp.getUser({ or: "throw" });
const provider = await currentUser.getOAuthProvider("non-existent-id");
expect(provider).toBeNull();
});
it("should return empty list when user has no OAuth providers", async ({ expect }) => {
const apps = await createAppsWithOAuth();
await apps.serverApp.createUser({
primaryEmail: "test@example.com",
password: "password123",
primaryEmailAuthEnabled: true,
});
await apps.clientApp.signInWithCredential({ email: "test@example.com", password: "password123" });
const currentUser = await apps.clientApp.getUser({ or: "throw" });
const providers = await currentUser.listOAuthProviders();
expect(providers).toHaveLength(0);
});
it("should update OAuth provider settings", async ({ expect }) => {
const apps = await createAppsWithOAuth();
const user = await apps.serverApp.createUser({
primaryEmail: "test@example.com",
password: "password123",
primaryEmailAuthEnabled: true,
});
const createdProviderResult = await apps.serverApp.createOAuthProvider({
userId: user.id,
providerConfigId: "spotify",
accountId: "spotify_user_123",
email: "test@example.com",
allowSignIn: true,
allowConnectedAccounts: true,
});
if (createdProviderResult.status === "error") {
throw new Error("Failed to create OAuth provider");
}
const createdProvider = createdProviderResult.data!;
await apps.clientApp.signInWithCredential({ email: "test@example.com", password: "password123" });
const currentUser = await apps.clientApp.getUser({ or: "throw" });
const provider = await currentUser.getOAuthProvider(createdProvider.id);
expect(provider).toBeDefined();
await provider!.update({ allowSignIn: false, allowConnectedAccounts: false });
const updatedProvider = await currentUser.getOAuthProvider(createdProvider.id);
expect(updatedProvider?.allowSignIn).toBe(false);
expect(updatedProvider?.allowConnectedAccounts).toBe(false);
});
it("should delete OAuth provider", async ({ expect }) => {
const apps = await createAppsWithOAuth();
const user = await apps.serverApp.createUser({
primaryEmail: "test@example.com",
password: "password123",
primaryEmailAuthEnabled: true,
});
const createdProviderResult = await apps.serverApp.createOAuthProvider({
userId: user.id,
providerConfigId: "spotify",
accountId: "spotify_user_123",
email: "test@example.com",
allowSignIn: true,
allowConnectedAccounts: true,
});
if (createdProviderResult.status === "error") {
throw new Error("Failed to create OAuth provider");
}
const createdProvider = createdProviderResult.data!;
await apps.clientApp.signInWithCredential({ email: "test@example.com", password: "password123" });
const currentUser = await apps.clientApp.getUser({ or: "throw" });
let provider = await currentUser.getOAuthProvider(createdProvider.id);
expect(provider).toBeDefined();
await provider!.delete();
provider = await currentUser.getOAuthProvider(createdProvider.id);
expect(provider).toBeNull();
const providers = await currentUser.listOAuthProviders();
expect(providers).toHaveLength(0);
});
it("should handle multiple OAuth providers of different types", async ({ expect }) => {
const apps = await createAppsWithOAuth();
const user = await apps.serverApp.createUser({
primaryEmail: "test@example.com",
password: "password123",
primaryEmailAuthEnabled: true,
});
await apps.serverApp.createOAuthProvider({
userId: user.id,
providerConfigId: "spotify",
accountId: "spotify_user_123",
email: "test@example.com",
allowSignIn: true,
allowConnectedAccounts: true,
});
await apps.serverApp.createOAuthProvider({
userId: user.id,
providerConfigId: "github",
accountId: "github_user_456",
email: "test@example.com",
allowSignIn: false,
allowConnectedAccounts: true,
});
await apps.clientApp.signInWithCredential({ email: "test@example.com", password: "password123" });
const currentUser = await apps.clientApp.getUser({ or: "throw" });
const providers = await currentUser.listOAuthProviders();
expect(providers).toHaveLength(2);
const providerTypes = providers.map((p: any) => p.type).sort((a, b) => stringCompare(a, b));
expect(providerTypes).toEqual(["github", "spotify"]);
const enabledForSignIn = providers.filter((p: any) => p.allowSignIn);
expect(enabledForSignIn).toHaveLength(1);
expect(enabledForSignIn[0].type).toBe("spotify");
});
it("should update OAuth provider email on server side", async ({ expect }) => {
const apps = await createAppsWithOAuth();
const user = await apps.serverApp.createUser({
primaryEmail: "test@example.com",
password: "password123",
primaryEmailAuthEnabled: true,
});
const createdProviderResult = await apps.serverApp.createOAuthProvider({
userId: user.id,
providerConfigId: "spotify",
accountId: "spotify_user_123",
email: "test@example.com",
allowSignIn: true,
allowConnectedAccounts: true,
});
if (createdProviderResult.status === "error") {
throw new Error("Failed to create OAuth provider");
}
const createdProvider = createdProviderResult.data!;
await createdProvider.update({ email: "updated@example.com" });
await apps.clientApp.signInWithCredential({ email: "test@example.com", password: "password123" });
const currentUser = await apps.clientApp.getUser({ or: "throw" });
const provider = await currentUser.getOAuthProvider(createdProvider.id);
expect(provider?.email).toBe("updated@example.com");
});
});