|
4 | 4 |
|
5 | 5 | import { autoRefreshClient, getClientWithSpecificStorage, pkceClient } from './lib/clients'
|
6 | 6 | import { mockUserCredentials } from './lib/utils'
|
| 7 | +import { |
| 8 | + supportsLocalStorage, |
| 9 | + validateExp, |
| 10 | + sleep, |
| 11 | + userNotAvailableProxy, |
| 12 | + resolveFetch, |
| 13 | +} from '../src/lib/helpers' |
7 | 14 |
|
8 | 15 | // Add structuredClone polyfill for jsdom
|
9 | 16 | if (typeof structuredClone === 'undefined') {
|
10 |
| - ;(global as any).structuredClone = (obj: any) => JSON.parse(JSON.stringify(obj)) |
| 17 | + ; (global as any).structuredClone = (obj: any) => JSON.parse(JSON.stringify(obj)) |
11 | 18 | }
|
12 | 19 |
|
13 | 20 | describe('GoTrueClient in browser environment', () => {
|
@@ -100,6 +107,49 @@ describe('GoTrueClient in browser environment', () => {
|
100 | 107 | })
|
101 | 108 | })
|
102 | 109 |
|
| 110 | +describe('Browser-specific helper functions', () => { |
| 111 | + it('should handle localStorage not available', () => { |
| 112 | + // Mock localStorage as undefined |
| 113 | + Object.defineProperty(window, 'localStorage', { |
| 114 | + value: undefined, |
| 115 | + writable: true, |
| 116 | + }) |
| 117 | + expect(supportsLocalStorage()).toBe(false) |
| 118 | + }) |
| 119 | +}) |
| 120 | + |
| 121 | +describe('JWT and cryptographic functions in browser', () => { |
| 122 | + it('should throw on missing exp claim', () => { |
| 123 | + expect(() => validateExp(0)).toThrow('Missing exp claim') |
| 124 | + }) |
| 125 | +}) |
| 126 | + |
| 127 | +describe('Retryable and sleep functions in browser', () => { |
| 128 | + it('should sleep for specified time', async () => { |
| 129 | + const start = Date.now() |
| 130 | + await sleep(100) |
| 131 | + const end = Date.now() |
| 132 | + expect(end - start).toBeGreaterThanOrEqual(90) |
| 133 | + }) |
| 134 | +}) |
| 135 | + |
| 136 | +describe('User proxy and deep clone functions in browser', () => { |
| 137 | + it('should throw on property setting to user proxy', () => { |
| 138 | + const proxy = userNotAvailableProxy() |
| 139 | + expect(() => { |
| 140 | + (proxy as any).email = '[email protected]' |
| 141 | + }).toThrow() |
| 142 | + }) |
| 143 | +}) |
| 144 | + |
| 145 | +describe('Fetch resolution in browser environment', () => { |
| 146 | + it('should resolve fetch correctly', () => { |
| 147 | + const customFetch = jest.fn() |
| 148 | + const resolvedFetch = resolveFetch(customFetch) |
| 149 | + expect(typeof resolvedFetch).toBe('function') |
| 150 | + }) |
| 151 | +}) |
| 152 | + |
103 | 153 | describe('Callback URL handling', () => {
|
104 | 154 | let mockFetch: jest.Mock
|
105 | 155 | let storedSession: string | null
|
@@ -241,4 +291,88 @@ describe('GoTrueClient BroadcastChannel', () => {
|
241 | 291 | sub1.unsubscribe()
|
242 | 292 | sub2.unsubscribe()
|
243 | 293 | })
|
| 294 | + |
| 295 | + it('should handle BroadcastChannel errors', () => { |
| 296 | + const mockBroadcastChannel = jest.fn().mockImplementation(() => { |
| 297 | + throw new Error('BroadcastChannel not supported') |
| 298 | + }) |
| 299 | + |
| 300 | + Object.defineProperty(window, 'BroadcastChannel', { |
| 301 | + value: mockBroadcastChannel, |
| 302 | + writable: true, |
| 303 | + }) |
| 304 | + |
| 305 | + const client = getClientWithSpecificStorage({ |
| 306 | + getItem: jest.fn(), |
| 307 | + setItem: jest.fn(), |
| 308 | + removeItem: jest.fn(), |
| 309 | + }) |
| 310 | + |
| 311 | + expect(client).toBeDefined() |
| 312 | + }) |
| 313 | +}) |
| 314 | + |
| 315 | +describe('Browser locks functionality', () => { |
| 316 | + it('should use navigator locks when available', () => { |
| 317 | + // Mock navigator.locks |
| 318 | + const mockLock = { name: 'test-lock' } |
| 319 | + const mockRequest = jest.fn().mockImplementation((_, __, callback) => |
| 320 | + Promise.resolve(callback(mockLock)) |
| 321 | + ) |
| 322 | + |
| 323 | + Object.defineProperty(navigator, 'locks', { |
| 324 | + value: { request: mockRequest }, |
| 325 | + writable: true, |
| 326 | + }) |
| 327 | + |
| 328 | + // Test navigator locks usage in GoTrueClient |
| 329 | + const client = getClientWithSpecificStorage({ |
| 330 | + getItem: jest.fn(), |
| 331 | + setItem: jest.fn(), |
| 332 | + removeItem: jest.fn(), |
| 333 | + }) |
| 334 | + |
| 335 | + expect(client).toBeDefined() |
| 336 | + }) |
| 337 | +}) |
| 338 | + |
| 339 | +describe('Web3 functionality in browser', () => { |
| 340 | + it('should handle Web3 provider not available', async () => { |
| 341 | + const credentials = { |
| 342 | + chain: 'ethereum' as const, |
| 343 | + wallet: {} as any, |
| 344 | + } |
| 345 | + |
| 346 | + await expect(pkceClient.signInWithWeb3(credentials)).rejects.toThrow() |
| 347 | + }) |
| 348 | + |
| 349 | + it('should handle Solana Web3 provider not available', async () => { |
| 350 | + const credentials = { |
| 351 | + chain: 'solana' as const, |
| 352 | + wallet: {} as any, |
| 353 | + } |
| 354 | + |
| 355 | + await expect(pkceClient.signInWithWeb3(credentials)).rejects.toThrow() |
| 356 | + }) |
| 357 | +}) |
| 358 | + |
| 359 | +describe('GoTrueClient constructor edge cases', () => { |
| 360 | + |
| 361 | + it('should handle userStorage with persistSession', () => { |
| 362 | + const customUserStorage = { |
| 363 | + getItem: jest.fn(), |
| 364 | + setItem: jest.fn(), |
| 365 | + removeItem: jest.fn(), |
| 366 | + } |
| 367 | + |
| 368 | + const client = new (require('../src/GoTrueClient').default)({ |
| 369 | + url: 'http://localhost:9999', |
| 370 | + userStorage: customUserStorage, |
| 371 | + persistSession: true, |
| 372 | + autoRefreshToken: false, |
| 373 | + }) |
| 374 | + |
| 375 | + expect(client).toBeDefined() |
| 376 | + expect((client as any).userStorage).toBe(customUserStorage) |
| 377 | + }) |
244 | 378 | })
|
0 commit comments