Skip to content
File

Blob: tests/client/sign-in-oauth.test.ts

typescript104 lines
1import { describe, expect, it } from "vitest";
2 
3import {
4 shouldRedirectSignedInFromSignIn,
5 signedOAuthQueryFromParams,
6 socialErrorCallbackURL,
7} from "@/client/lib/sign-in-oauth";
8 
9describe("signedOAuthQueryFromParams", () => {
10 it("returns null when no signed query is present", () => {
11 expect(signedOAuthQueryFromParams(new URLSearchParams(""))).toBe(null);
12 expect(signedOAuthQueryFromParams(new URLSearchParams("foo=bar"))).toBe(null);
13 });
14 
15 it("returns null when only client_id is present (no sig)", () => {
16 expect(signedOAuthQueryFromParams(new URLSearchParams("client_id=A"))).toBe(null);
17 });
18 
19 it("returns null when only sig is present (no client_id)", () => {
20 expect(signedOAuthQueryFromParams(new URLSearchParams("sig=Z"))).toBe(null);
21 });
22 
23 it("preserves the signed sequence through sig", () => {
24 const params = new URLSearchParams("client_id=A&response_type=code&state=S&sig=Z");
25 expect(signedOAuthQueryFromParams(params)).toBe("client_id=A&response_type=code&state=S&sig=Z");
26 });
27 
28 it("skips a leading local error param while preserving signed order", () => {
29 const params = new URLSearchParams("error=social_unavailable&client_id=A&state=S&sig=Z");
30 expect(signedOAuthQueryFromParams(params)).toBe("client_id=A&state=S&sig=Z");
31 });
32 
33 it("skips a leading local redirect param while preserving signed order", () => {
34 const params = new URLSearchParams("redirect=%2Faccount&client_id=A&sig=Z");
35 expect(signedOAuthQueryFromParams(params)).toBe("client_id=A&sig=Z");
36 });
37 
38 it("ignores params after sig (stops at the first sig)", () => {
39 const params = new URLSearchParams("client_id=A&sig=Z&error=social_unavailable");
40 expect(signedOAuthQueryFromParams(params)).toBe("client_id=A&sig=Z");
41 });
42 
43 it("preserves repeated keys in their original order", () => {
44 const params = new URLSearchParams("scope=openid&scope=email&client_id=A&sig=Z");
45 expect(signedOAuthQueryFromParams(params)).toBe("scope=openid&scope=email&client_id=A&sig=Z");
46 });
47});
48 
49describe("socialErrorCallbackURL", () => {
50 it("returns the bare error URL when no signed query is present", () => {
51 expect(socialErrorCallbackURL(null)).toBe("/sign-in?error=social_unavailable");
52 });
53 
54 it("places signed params first and the local error after sig", () => {
55 expect(socialErrorCallbackURL("client_id=A&sig=Z")).toBe("/sign-in?client_id=A&sig=Z&error=social_unavailable");
56 });
57 
58 it("survives a round trip through signedOAuthQueryFromParams", () => {
59 const signed = "client_id=A&response_type=code&state=S&sig=Z";
60 const url = new URL(socialErrorCallbackURL(signed), "https://placeholder.invalid");
61 expect(signedOAuthQueryFromParams(url.searchParams)).toBe(signed);
62 });
63});
64 
65describe("shouldRedirectSignedInFromSignIn", () => {
66 it("returns false while the session is pending", () => {
67 expect(
68 shouldRedirectSignedInFromSignIn({ sessionPending: true, signedInUserId: "u1", signedOAuthQuery: null }),
69 ).toBe(false);
70 expect(
71 shouldRedirectSignedInFromSignIn({ sessionPending: true, signedInUserId: null, signedOAuthQuery: null }),
72 ).toBe(false);
73 expect(
74 shouldRedirectSignedInFromSignIn({
75 sessionPending: true,
76 signedInUserId: "u1",
77 signedOAuthQuery: "client_id=A&sig=Z",
78 }),
79 ).toBe(false);
80 });
81 
82 it("returns false when the user is signed out", () => {
83 expect(
84 shouldRedirectSignedInFromSignIn({ sessionPending: false, signedInUserId: null, signedOAuthQuery: null }),
85 ).toBe(false);
86 });
87 
88 it("returns true when a signed-in user has no signed query", () => {
89 expect(
90 shouldRedirectSignedInFromSignIn({ sessionPending: false, signedInUserId: "u1", signedOAuthQuery: null }),
91 ).toBe(true);
92 });
93 
94 it("returns false when a signed-in user has a signed query (prompt=login path)", () => {
95 expect(
96 shouldRedirectSignedInFromSignIn({
97 sessionPending: false,
98 signedInUserId: "u1",
99 signedOAuthQuery: "client_id=A&sig=Z",
100 }),
101 ).toBe(false);
102 });
103});