Skip to content

Commit c765e7d

Browse files
committed
test: add tests for isAuthenticated and refreshToken
1 parent 6ae7ec2 commit c765e7d

File tree

3 files changed

+232
-2
lines changed

3 files changed

+232
-2
lines changed
+94
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2+
import { isAuthenticated } from ".";
3+
import * as tokenUtils from ".";
4+
5+
// Mock the entire token utils module
6+
vi.mock("..");
7+
8+
describe("isAuthenticated", () => {
9+
const mockCurrentTime = 1000000000;
10+
11+
beforeEach(() => {
12+
// Mock Date.now() to return a fixed timestamp
13+
vi.spyOn(Date, "now").mockImplementation(() => mockCurrentTime * 1000);
14+
});
15+
16+
afterEach(() => {
17+
vi.restoreAllMocks();
18+
});
19+
20+
it("should return false if no token is found", async () => {
21+
vi.spyOn(tokenUtils, "getDecodedToken").mockResolvedValue(null);
22+
23+
const result = await isAuthenticated();
24+
25+
expect(result).toBe(false);
26+
});
27+
28+
it("should return true if token is valid and not expired", async () => {
29+
vi.spyOn(tokenUtils, "getDecodedToken").mockResolvedValue({
30+
exp: mockCurrentTime + 3600,
31+
});
32+
33+
const result = await isAuthenticated();
34+
35+
expect(result).toBe(true);
36+
});
37+
38+
it("should return false if token is expired and useRefreshToken is not set", async () => {
39+
vi.spyOn(tokenUtils, "getDecodedToken").mockResolvedValue({
40+
exp: mockCurrentTime - 3600,
41+
});
42+
43+
const result = await isAuthenticated();
44+
45+
expect(result).toBe(false);
46+
});
47+
48+
it("should attempt to refresh token if expired and useRefreshToken is true", async () => {
49+
vi.spyOn(tokenUtils, "getDecodedToken").mockResolvedValue({
50+
exp: mockCurrentTime - 3600,
51+
});
52+
const mockRefreshToken = vi
53+
.spyOn(tokenUtils, "refreshToken")
54+
.mockResolvedValue(true);
55+
56+
const result = await isAuthenticated({
57+
useRefreshToken: true,
58+
domain: "test.com",
59+
clientId: "123",
60+
});
61+
62+
expect(result).toBe(true);
63+
expect(mockRefreshToken).toHaveBeenCalledWith("test.com", "123");
64+
});
65+
66+
it("should return false if token refresh fails", async () => {
67+
vi.spyOn(tokenUtils, "getDecodedToken").mockResolvedValue({
68+
exp: mockCurrentTime - 3600,
69+
});
70+
vi.spyOn(tokenUtils, "refreshToken").mockResolvedValue(false);
71+
72+
const result = await isAuthenticated({
73+
useRefreshToken: true,
74+
domain: "test.com",
75+
clientId: "123",
76+
});
77+
78+
expect(result).toBe(false);
79+
});
80+
81+
it("should return false and log error if an exception occurs", async () => {
82+
const mockError = new Error("Test error");
83+
vi.spyOn(tokenUtils, "getDecodedToken").mockRejectedValue(mockError);
84+
const consoleSpy = vi.spyOn(console, "error").mockImplementation(() => {});
85+
86+
const result = await isAuthenticated();
87+
88+
expect(result).toBe(false);
89+
expect(consoleSpy).toHaveBeenCalledWith(
90+
"Error checking authentication:",
91+
mockError,
92+
);
93+
});
94+
});

lib/utils/token/refreshToken.test.ts

+135
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2+
import { refreshToken } from ".";
3+
import { SessionManager, StorageKeys } from "../../sessionManager";
4+
import * as tokenUtils from ".";
5+
6+
describe("refreshToken", () => {
7+
const mockDomain = "https://example.com";
8+
const mockClientId = "test-client-id";
9+
const mockRefreshTokenValue = "mock-refresh-token";
10+
const mockStorage: SessionManager = {
11+
getSessionItem: vi.fn(),
12+
setSessionItem: vi.fn(),
13+
removeSessionItem: vi.fn(),
14+
destroySession: vi.fn(),
15+
};
16+
17+
beforeEach(() => {
18+
vi.resetAllMocks();
19+
vi.spyOn(tokenUtils, "getDecodedToken").mockResolvedValue(null);
20+
vi.spyOn(tokenUtils, "getActiveStorage").mockResolvedValue(mockStorage);
21+
// vi.spyOn(Utils, 'sanatizeURL').mockImplementation((url) => url);
22+
global.fetch = vi.fn();
23+
vi.spyOn(console, "error").mockImplementation(() => {});
24+
});
25+
26+
afterEach(() => {
27+
vi.restoreAllMocks();
28+
});
29+
30+
it("should return false if domain is not provided", async () => {
31+
const result = await refreshToken(undefined, mockClientId);
32+
expect(result).toBe(false);
33+
expect(console.error).toHaveBeenCalledWith(
34+
"Domain is required for token refresh",
35+
);
36+
});
37+
38+
it("should return false if clientId is not provided", async () => {
39+
const result = await refreshToken(mockDomain, undefined);
40+
expect(result).toBe(false);
41+
expect(console.error).toHaveBeenCalledWith(
42+
"Client ID is required for token refresh",
43+
);
44+
});
45+
46+
it("should return false if no refresh token is found", async () => {
47+
// mockStorage.getSessionItem.mockResolvedValue(null);
48+
const result = await refreshToken(mockDomain, mockClientId);
49+
expect(result).toBe(false);
50+
expect(console.error).toHaveBeenCalledWith("No refresh token found");
51+
});
52+
53+
it("should return false if the fetch request fails", async () => {
54+
mockStorage.getSessionItem = vi
55+
.fn()
56+
.mockResolvedValue(mockRefreshTokenValue);
57+
vi.mocked(global.fetch).mockRejectedValue(new Error("Network error"));
58+
const result = await refreshToken(mockDomain, mockClientId);
59+
expect(result).toBe(false);
60+
expect(console.error).toHaveBeenCalledWith(
61+
"Error refreshing token:",
62+
expect.any(Error),
63+
);
64+
});
65+
66+
it("should return false if the response is not ok", async () => {
67+
mockStorage.getSessionItem = vi
68+
.fn()
69+
.mockResolvedValue(mockRefreshTokenValue);
70+
vi.mocked(global.fetch).mockResolvedValue({ ok: false } as Response);
71+
const result = await refreshToken(mockDomain, mockClientId);
72+
expect(result).toBe(false);
73+
expect(console.error).toHaveBeenCalledWith("Failed to refresh token");
74+
});
75+
76+
it("should return false if the response does not contain an access token", async () => {
77+
mockStorage.getSessionItem = vi
78+
.fn()
79+
.mockResolvedValue(mockRefreshTokenValue);
80+
vi.mocked(global.fetch).mockResolvedValue({
81+
ok: true,
82+
json: () => Promise.resolve({}),
83+
} as Response);
84+
const result = await refreshToken(mockDomain, mockClientId);
85+
expect(result).toBe(false);
86+
});
87+
88+
it("should return true and update tokens if the refresh is successful", async () => {
89+
const mockResponse = {
90+
access_token: "new-access-token",
91+
id_token: "new-id-token",
92+
refresh_token: "new-refresh-token",
93+
};
94+
mockStorage.getSessionItem = vi
95+
.fn()
96+
.mockResolvedValue(mockRefreshTokenValue);
97+
vi.mocked(global.fetch).mockResolvedValue({
98+
ok: true,
99+
json: () => Promise.resolve(mockResponse),
100+
} as Response);
101+
102+
const result = await refreshToken(mockDomain, mockClientId);
103+
104+
expect(result).toBe(true);
105+
expect(mockStorage.setSessionItem).toHaveBeenCalledWith(
106+
StorageKeys.accessToken,
107+
"new-access-token",
108+
);
109+
expect(mockStorage.setSessionItem).toHaveBeenCalledWith(
110+
StorageKeys.idToken,
111+
"new-id-token",
112+
);
113+
expect(mockStorage.setSessionItem).toHaveBeenCalledWith(
114+
StorageKeys.refreshToken,
115+
"new-refresh-token",
116+
);
117+
});
118+
119+
it("should use sanatizeURL for the domain", async () => {
120+
mockStorage.getSessionItem = vi
121+
.fn()
122+
.mockResolvedValue(mockRefreshTokenValue);
123+
vi.mocked(global.fetch).mockResolvedValue({
124+
ok: true,
125+
json: () => Promise.resolve({ access_token: "new-token" }),
126+
} as Response);
127+
128+
await refreshToken("https://example.com/", mockClientId);
129+
130+
expect(global.fetch).toHaveBeenCalledWith(
131+
expect.stringContaining(`https://example.com/oauth2/token`),
132+
expect.any(Object),
133+
);
134+
});
135+
});

lib/utils/token/refreshToken.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { getActiveStorage } from ".";
22
import { StorageKeys } from "../../sessionManager";
3-
import { sanatizeURL } from "../sanatizeUrl";
3+
import { sanatizeURL } from "..";
44

55
/**
66
* refreshes the token
@@ -21,7 +21,8 @@ export const refreshToken = async (
2121
return false;
2222
}
2323

24-
const storage = getActiveStorage();
24+
const storage = await getActiveStorage();
25+
2526
const refreshTokenValue = await storage.getSessionItem(
2627
StorageKeys.refreshToken,
2728
);

0 commit comments

Comments
 (0)