Skip to content

Commit 1de724c

Browse files
committed
Improve dev browser cookie cleanup tests
1 parent 89e7ca6 commit 1de724c

1 file changed

Lines changed: 120 additions & 91 deletions

File tree

Lines changed: 120 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,118 +1,147 @@
1-
import { createCookieHandler } from '@clerk/shared/cookie';
2-
import { addYears } from '@clerk/shared/date';
3-
import { inCrossOriginIframe } from '@clerk/shared/internal/clerk-js/runtime';
4-
import { beforeEach, describe, expect, it, vi } from 'vitest';
1+
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
52

6-
import { getSecureAttribute } from '../../getSecureAttribute';
73
import { createDevBrowserCookie } from '../devBrowser';
8-
import { requiresSameSiteNone } from '../requireSameSiteNone';
94

10-
vi.mock('@clerk/shared/cookie');
11-
vi.mock('@clerk/shared/date');
12-
vi.mock('@clerk/shared/internal/clerk-js/runtime');
13-
vi.mock('../../getSecureAttribute');
14-
vi.mock('../requireSameSiteNone');
5+
const { cookieStore, removeCalls, setCalls } = vi.hoisted(() => ({
6+
cookieStore: new Map<string, string>(),
7+
removeCalls: [] as Array<{ name: string; attributes?: object }>,
8+
setCalls: [] as Array<{ name: string; value: string; attributes?: object }>,
9+
}));
10+
11+
vi.mock('@clerk/shared/cookie', () => ({
12+
createCookieHandler: (name: string) => ({
13+
get: () => cookieStore.get(name),
14+
remove: (attributes?: object) => {
15+
removeCalls.push({ name, attributes });
16+
cookieStore.delete(name);
17+
},
18+
set: (value: string, attributes?: object) => {
19+
setCalls.push({ name, value, attributes });
20+
cookieStore.set(name, value);
21+
},
22+
}),
23+
}));
1524

1625
describe('createDevBrowserCookie', () => {
17-
const mockCookieSuffix = 'test-suffix';
18-
const mockDevBrowser = 'test-dev-browser';
19-
const mockExpires = new Date('2024-12-31');
26+
const cookieSuffix = 'test-suffix';
27+
const suffixedCookieName = '__clerk_db_jwt_test-suffix';
28+
const unsuffixedCookieName = '__clerk_db_jwt';
29+
const devBrowser = 'test-dev-browser';
30+
const now = new Date('2024-01-01T00:00:00.000Z');
31+
const expires = new Date('2025-01-01T00:00:00.000Z');
2032
const defaultOptions = { usePartitionedCookies: () => false };
21-
const mockSet = vi.fn();
22-
const mockRemove = vi.fn();
23-
const mockGet = vi.fn();
2433

2534
beforeEach(() => {
26-
vi.clearAllMocks();
27-
mockGet.mockReset();
28-
(addYears as ReturnType<typeof vi.fn>).mockReturnValue(mockExpires);
29-
(inCrossOriginIframe as ReturnType<typeof vi.fn>).mockReturnValue(false);
30-
(requiresSameSiteNone as ReturnType<typeof vi.fn>).mockReturnValue(false);
31-
(getSecureAttribute as ReturnType<typeof vi.fn>).mockReturnValue(true);
32-
(createCookieHandler as ReturnType<typeof vi.fn>).mockImplementation(() => ({
33-
set: mockSet,
34-
remove: mockRemove,
35-
get: mockGet,
36-
}));
35+
vi.useFakeTimers();
36+
vi.setSystemTime(now);
37+
cookieStore.clear();
38+
removeCalls.length = 0;
39+
setCalls.length = 0;
3740
});
3841

39-
it('should create both suffixed and non-suffixed cookie handlers', () => {
40-
createDevBrowserCookie(mockCookieSuffix, defaultOptions);
41-
42-
expect(createCookieHandler).toHaveBeenCalledTimes(2);
43-
expect(createCookieHandler).toHaveBeenCalledWith('__clerk_db_jwt');
44-
expect(createCookieHandler).toHaveBeenCalledWith('__clerk_db_jwt_test-suffix');
42+
afterEach(() => {
43+
vi.useRealTimers();
44+
vi.unstubAllGlobals();
4545
});
4646

47-
it('should remove non-partitioned and partitioned cookies even when partitioned cookies are disabled', () => {
48-
const cookieHandler = createDevBrowserCookie(mockCookieSuffix, defaultOptions);
47+
it('removes current, non-partitioned, and partitioned cookie variants for both dev browser cookie names', () => {
48+
const cookieHandler = createDevBrowserCookie(cookieSuffix, defaultOptions);
49+
4950
cookieHandler.remove();
5051

51-
const currentAttributes = {
52-
sameSite: 'Lax',
53-
secure: true,
54-
partitioned: false,
55-
};
56-
const partitionedAttributes = {
57-
sameSite: 'None',
58-
secure: true,
59-
partitioned: true,
60-
};
61-
62-
expect(mockRemove).toHaveBeenCalledTimes(6);
63-
expect(mockRemove).toHaveBeenNthCalledWith(1, currentAttributes);
64-
expect(mockRemove).toHaveBeenNthCalledWith(2);
65-
expect(mockRemove).toHaveBeenNthCalledWith(3, partitionedAttributes);
66-
expect(mockRemove).toHaveBeenNthCalledWith(4, currentAttributes);
67-
expect(mockRemove).toHaveBeenNthCalledWith(5);
68-
expect(mockRemove).toHaveBeenNthCalledWith(6, partitionedAttributes);
52+
expect(removeCalls).toEqual([
53+
{
54+
name: suffixedCookieName,
55+
attributes: {
56+
sameSite: 'Lax',
57+
secure: false,
58+
partitioned: false,
59+
},
60+
},
61+
{ name: suffixedCookieName, attributes: undefined },
62+
{
63+
name: suffixedCookieName,
64+
attributes: {
65+
sameSite: 'None',
66+
secure: true,
67+
partitioned: true,
68+
},
69+
},
70+
{
71+
name: unsuffixedCookieName,
72+
attributes: {
73+
sameSite: 'Lax',
74+
secure: false,
75+
partitioned: false,
76+
},
77+
},
78+
{ name: unsuffixedCookieName, attributes: undefined },
79+
{
80+
name: unsuffixedCookieName,
81+
attributes: {
82+
sameSite: 'None',
83+
secure: true,
84+
partitioned: true,
85+
},
86+
},
87+
]);
6988
});
7089

71-
it('should clear stale partitioned cookies before setting a new non-partitioned cookie', () => {
72-
const cookieHandler = createDevBrowserCookie(mockCookieSuffix, defaultOptions);
73-
cookieHandler.set(mockDevBrowser);
90+
it('clears stale partitioned cookie variants before writing a new dev browser', () => {
91+
const cookieHandler = createDevBrowserCookie(cookieSuffix, defaultOptions);
7492

75-
expect(mockRemove).toHaveBeenCalledWith({
76-
sameSite: 'None',
77-
secure: true,
78-
partitioned: true,
79-
});
80-
expect(mockSet).toHaveBeenCalledTimes(2);
81-
expect(mockSet).toHaveBeenCalledWith(mockDevBrowser, {
82-
expires: mockExpires,
83-
sameSite: 'Lax',
84-
secure: true,
85-
partitioned: false,
86-
});
87-
});
93+
cookieHandler.set(devBrowser);
8894

89-
it('should set partitioned cookies when usePartitionedCookies returns true', () => {
90-
const cookieHandler = createDevBrowserCookie(mockCookieSuffix, { usePartitionedCookies: () => true });
91-
cookieHandler.set(mockDevBrowser);
92-
93-
expect(mockSet).toHaveBeenCalledWith(mockDevBrowser, {
94-
expires: mockExpires,
95-
sameSite: 'None',
96-
secure: true,
97-
partitioned: true,
95+
expect(removeCalls).toContainEqual({
96+
name: suffixedCookieName,
97+
attributes: {
98+
sameSite: 'None',
99+
secure: true,
100+
partitioned: true,
101+
},
102+
});
103+
expect(removeCalls).toContainEqual({
104+
name: unsuffixedCookieName,
105+
attributes: {
106+
sameSite: 'None',
107+
secure: true,
108+
partitioned: true,
109+
},
98110
});
111+
expect(setCalls).toEqual([
112+
{
113+
name: suffixedCookieName,
114+
value: devBrowser,
115+
attributes: {
116+
expires,
117+
sameSite: 'Lax',
118+
secure: false,
119+
partitioned: false,
120+
},
121+
},
122+
{
123+
name: unsuffixedCookieName,
124+
value: devBrowser,
125+
attributes: {
126+
expires,
127+
sameSite: 'Lax',
128+
secure: false,
129+
partitioned: false,
130+
},
131+
},
132+
]);
99133
});
100134

101-
it('should get cookie value from suffixed cookie first, then fallback to non-suffixed', () => {
102-
mockGet.mockImplementationOnce(() => 'suffixed-value').mockImplementationOnce(() => 'non-suffixed-value');
135+
it('reads the suffixed cookie before falling back to the unsuffixed cookie', () => {
136+
const cookieHandler = createDevBrowserCookie(cookieSuffix, defaultOptions);
103137

104-
const cookieHandler = createDevBrowserCookie(mockCookieSuffix, defaultOptions);
105-
const result = cookieHandler.get();
106-
107-
expect(result).toBe('suffixed-value');
108-
});
138+
cookieStore.set(unsuffixedCookieName, 'unsuffixed-value');
139+
cookieStore.set(suffixedCookieName, 'suffixed-value');
109140

110-
it('should fallback to non-suffixed cookie when suffixed cookie is not present', () => {
111-
mockGet.mockImplementationOnce(() => undefined).mockImplementationOnce(() => 'non-suffixed-value');
141+
expect(cookieHandler.get()).toBe('suffixed-value');
112142

113-
const cookieHandler = createDevBrowserCookie(mockCookieSuffix, defaultOptions);
114-
const result = cookieHandler.get();
143+
cookieStore.delete(suffixedCookieName);
115144

116-
expect(result).toBe('non-suffixed-value');
145+
expect(cookieHandler.get()).toBe('unsuffixed-value');
117146
});
118147
});

0 commit comments

Comments
 (0)