1import { describe, expect, it } from "vite-plus/test";
2
3import {
4 ClerkPublishableKeyDecodeError,
5 ClerkPublishableKeyFrontendApiError,
6 clerkFrontendApiHostnameFromPublishableKey,
7 clerkFrontendApiUrlFromPublishableKey,
8} from "./relayAuth.ts";
9
10const clerkPublishableKey = (hostname: string): string => `pk_test_${btoa(`${hostname}$`)}`;
11
12const captureError = (run: () => unknown): unknown => {
13 try {
14 run();
15 } catch (cause) {
16 return cause;
17 }
18 throw new Error("Expected operation to throw");
19};
20
21describe("Clerk relay auth", () => {
22 it("derives a custom Frontend API hostname from a Clerk publishable key", () => {
23 expect(clerkFrontendApiHostnameFromPublishableKey(clerkPublishableKey("clerk.t3.codes"))).toBe(
24 "clerk.t3.codes",
25 );
26 expect(clerkFrontendApiUrlFromPublishableKey(clerkPublishableKey("clerk.t3.codes"))).toBe(
27 "https://clerk.t3.codes",
28 );
29 });
30
31 it("preserves Clerk publishable key decoding failures", () => {
32 const error = captureError(() => clerkFrontendApiUrlFromPublishableKey("pk_test_%"));
33
34 expect(error).toBeInstanceOf(ClerkPublishableKeyDecodeError);
35 expect(error).toMatchObject({ keyPrefix: "pk_test" });
36 expect((error as ClerkPublishableKeyDecodeError).cause).toBeInstanceOf(Error);
37 expect((error as Error).message).toBe("Failed to decode Clerk publishable key (pk_test).");
38 });
39
40 it("reports semantic frontend API failures without inventing a cause", () => {
41 const emptyError = captureError(() => clerkFrontendApiUrlFromPublishableKey("pk_test_"));
42 const pathFrontendApi = "clerk.t3.codes/path";
43 const pathError = captureError(() =>
44 clerkFrontendApiUrlFromPublishableKey(clerkPublishableKey(pathFrontendApi)),
45 );
46
47 expect(emptyError).toBeInstanceOf(ClerkPublishableKeyFrontendApiError);
48 expect(emptyError).toMatchObject({
49 keyPrefix: "pk_test",
50 frontendApi: "",
51 reason: "empty",
52 });
53 expect((emptyError as Error & { cause?: unknown }).cause).toBeUndefined();
54 expect(pathError).toBeInstanceOf(ClerkPublishableKeyFrontendApiError);
55 expect(pathError).toMatchObject({
56 keyPrefix: "pk_test",
57 frontendApi: pathFrontendApi,
58 reason: "contains-path",
59 });
60 expect((pathError as Error & { cause?: unknown }).cause).toBeUndefined();
61 });
62
63 it("preserves URL parser failures for decoded frontend APIs", () => {
64 const frontendApi = "[invalid-host";
65 const error = captureError(() =>
66 clerkFrontendApiHostnameFromPublishableKey(clerkPublishableKey(frontendApi)),
67 );
68
69 expect(error).toBeInstanceOf(ClerkPublishableKeyFrontendApiError);
70 expect(error).toMatchObject({
71 keyPrefix: "pk_test",
72 frontendApi,
73 reason: "invalid-url",
74 });
75 expect((error as ClerkPublishableKeyFrontendApiError).cause).toBeInstanceOf(Error);
76 });
77});