Skip to content

Commit 1feb06f

Browse files
authored
Merge pull request #157 from pesickaa/feat/switch-org-method
feat: setup switch org method and tests
2 parents 175844e + 39ec698 commit 1feb06f

File tree

2 files changed

+126
-0
lines changed

2 files changed

+126
-0
lines changed

lib/utils/switchOrg.test.ts

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import { describe, it, expect, vi, afterEach } from "vitest";
2+
import { IssuerRouteTypes, PromptTypes } from "../types";
3+
4+
vi.mock("./generateAuthUrl", () => {
5+
return {
6+
generateAuthUrl: vi.fn().mockResolvedValue({
7+
url: new URL(
8+
"https://auth.example.com/oauth2/auth?client_id=mock&response_type=code&redirect_uri=https%3A%2F%2Fredirect.example.com&audience=&scope=openid+profile&prompt=none&state=mockstate&nonce=mocknonce&code_challenge=mockchallenge&code_challenge_method=S256&org_code=org_123",
9+
),
10+
state: "mockstate",
11+
nonce: "mocknonce",
12+
codeChallenge: "mockchallenge",
13+
codeVerifier: "mockverifier",
14+
}),
15+
};
16+
});
17+
18+
import { generateAuthUrl } from "./generateAuthUrl";
19+
import { switchOrg } from "./switchOrg";
20+
21+
describe("switchOrg", () => {
22+
afterEach(() => {
23+
vi.clearAllMocks();
24+
});
25+
26+
it("throws when domain is missing", () => {
27+
expect(() => {
28+
// @ts-expect-error testing runtime validation
29+
switchOrg({
30+
orgCode: "org_123",
31+
redirectURL: "https://redirect.example.com",
32+
});
33+
}).toThrow("domain is required for switchOrg");
34+
});
35+
36+
it("throws when orgCode is missing", () => {
37+
expect(() => {
38+
// @ts-expect-error testing runtime validation
39+
switchOrg({
40+
domain: "https://auth.example.com",
41+
redirectURL: "https://redirect.example.com",
42+
});
43+
}).toThrow("orgCode is required for switchOrg");
44+
});
45+
46+
it("throws when redirectURL is missing", () => {
47+
expect(() => {
48+
// @ts-expect-error testing runtime validation
49+
switchOrg({ domain: "https://auth.example.com", orgCode: "org_123" });
50+
}).toThrow("redirectURL is required for switchOrg");
51+
});
52+
53+
it("calls generateAuthUrl with correct args and returns its result", async () => {
54+
const domain = "https://auth.example.com";
55+
const orgCode = "org_123";
56+
const redirectURL = "https://redirect.example.com";
57+
58+
const result = await switchOrg({ domain, orgCode, redirectURL });
59+
60+
expect(generateAuthUrl).toHaveBeenCalledTimes(1);
61+
expect(generateAuthUrl).toHaveBeenCalledWith(
62+
domain,
63+
IssuerRouteTypes.login,
64+
expect.objectContaining({
65+
prompt: PromptTypes.none,
66+
orgCode,
67+
redirectURL,
68+
}),
69+
);
70+
71+
expect(result.state).toBe("mockstate");
72+
expect(result.nonce).toBe("mocknonce");
73+
expect(result.codeChallenge).toBe("mockchallenge");
74+
expect(result.codeVerifier).toBe("mockverifier");
75+
76+
const prompt = result.url.searchParams.get("prompt");
77+
const orgParam = result.url.searchParams.get("org_code");
78+
const redirectParam = result.url.searchParams.get("redirect_uri");
79+
expect(prompt).toBe("none");
80+
expect(orgParam).toBe("org_123");
81+
expect(redirectParam).toBe("https://redirect.example.com");
82+
});
83+
});

lib/utils/switchOrg.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import {
2+
IssuerRouteTypes,
3+
OrgCode,
4+
PromptTypes,
5+
type LoginOptions,
6+
} from "../types";
7+
import { generateAuthUrl } from "./generateAuthUrl";
8+
9+
export interface SwitchOrgParams {
10+
domain: string;
11+
orgCode: OrgCode;
12+
redirectURL: string;
13+
}
14+
15+
/**
16+
* Switch the active organization without prompting.
17+
* @param params - { domain, orgCode, redirectURL }
18+
* @returns OAuth URL bundle to redirect to (auto-switches active org).
19+
* @throws Error when domain, orgCode, or redirectURL are missing.
20+
*/
21+
export const switchOrg = ({
22+
domain,
23+
orgCode,
24+
redirectURL,
25+
}: SwitchOrgParams): ReturnType<typeof generateAuthUrl> => {
26+
if (!domain) {
27+
throw new Error("domain is required for switchOrg");
28+
}
29+
if (!orgCode) {
30+
throw new Error("orgCode is required for switchOrg");
31+
}
32+
33+
if (!redirectURL) {
34+
throw new Error("redirectURL is required for switchOrg");
35+
}
36+
const loginOptions: LoginOptions = {
37+
prompt: PromptTypes.none,
38+
orgCode,
39+
redirectURL,
40+
};
41+
42+
return generateAuthUrl(domain, IssuerRouteTypes.login, loginOptions);
43+
};

0 commit comments

Comments
 (0)