Skip to content

Commit 1137035

Browse files
georgRusanovgeorgiy.rusanov
andauthored
chore: added untit tests to increase coverage (#1535)
Co-authored-by: georgiy.rusanov <georgiy.rusanov@ringcentral.com>
1 parent cb49bf9 commit 1137035

File tree

5 files changed

+542
-20
lines changed

5 files changed

+542
-20
lines changed

test/unit/SupabaseClient.test.ts

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,18 @@ describe('SupabaseClient', () => {
104104
// @ts-ignore
105105
expect(client.storageKey).toBe(customStorageKey)
106106
})
107+
108+
test('should handle undefined storageKey and headers', () => {
109+
const client = createClient(URL, KEY, {
110+
auth: { storageKey: undefined },
111+
global: { headers: undefined },
112+
})
113+
expect(client).toBeDefined()
114+
// @ts-ignore
115+
expect(client.storageKey).toBe('')
116+
// @ts-ignore
117+
expect(client.headers).toHaveProperty('X-Client-Info')
118+
})
107119
})
108120

109121
describe('Client Methods', () => {
@@ -166,6 +178,14 @@ describe('SupabaseClient', () => {
166178
})
167179
})
168180

181+
describe('Table/View Queries', () => {
182+
test('should query table with string relation', () => {
183+
const client = createClient<Database>(URL, KEY)
184+
const queryBuilder = client.from('users')
185+
expect(queryBuilder).toBeDefined()
186+
})
187+
})
188+
169189
describe('RPC Calls', () => {
170190
test('should make RPC call with arguments', () => {
171191
const client = createClient<Database>(URL, KEY)
@@ -179,4 +199,125 @@ describe('SupabaseClient', () => {
179199
expect(rpcCall).toBeDefined()
180200
})
181201
})
202+
203+
describe('Access Token Handling', () => {
204+
test('should use custom accessToken when provided', async () => {
205+
const customToken = 'custom-jwt-token'
206+
const client = createClient(URL, KEY, {
207+
accessToken: async () => customToken,
208+
})
209+
210+
// Access the private method through the client instance
211+
const accessToken = await (client as any)._getAccessToken()
212+
expect(accessToken).toBe(customToken)
213+
})
214+
215+
test('should fallback to session access token when no custom accessToken', async () => {
216+
const client = createClient(URL, KEY)
217+
218+
// Mock the auth.getSession method
219+
const mockSession = {
220+
data: {
221+
session: {
222+
access_token: 'session-jwt-token',
223+
},
224+
},
225+
}
226+
client.auth.getSession = jest.fn().mockResolvedValue(mockSession)
227+
228+
const accessToken = await (client as any)._getAccessToken()
229+
expect(accessToken).toBe('session-jwt-token')
230+
})
231+
232+
test('should fallback to supabaseKey when no session', async () => {
233+
const client = createClient(URL, KEY)
234+
235+
// Mock the auth.getSession method to return no session
236+
const mockSession = {
237+
data: {
238+
session: null,
239+
},
240+
}
241+
client.auth.getSession = jest.fn().mockResolvedValue(mockSession)
242+
243+
const accessToken = await (client as any)._getAccessToken()
244+
expect(accessToken).toBe(KEY)
245+
})
246+
})
247+
248+
describe('Auth Event Handling', () => {
249+
test('should handle TOKEN_REFRESHED event', () => {
250+
const client = createClient(URL, KEY)
251+
const newToken = 'new-refreshed-token'
252+
253+
// Mock realtime.setAuth
254+
client.realtime.setAuth = jest.fn()
255+
;(client as any)._handleTokenChanged('TOKEN_REFRESHED', 'CLIENT', newToken)
256+
257+
expect((client as any).changedAccessToken).toBe(newToken)
258+
})
259+
260+
test('should listen for auth events', () => {
261+
const client = createClient(URL, KEY)
262+
263+
// Mock auth.onAuthStateChange
264+
const mockCallback = jest.fn()
265+
client.auth.onAuthStateChange = jest.fn().mockReturnValue(mockCallback)
266+
267+
// Call the private method
268+
const result = (client as any)._listenForAuthEvents()
269+
270+
expect(client.auth.onAuthStateChange).toHaveBeenCalled()
271+
expect(result).toBe(mockCallback)
272+
})
273+
274+
test('should handle SIGNED_IN event', () => {
275+
const client = createClient(URL, KEY)
276+
const newToken = 'new-signed-in-token'
277+
278+
// Mock realtime.setAuth
279+
client.realtime.setAuth = jest.fn()
280+
;(client as any)._handleTokenChanged('SIGNED_IN', 'CLIENT', newToken)
281+
282+
expect((client as any).changedAccessToken).toBe(newToken)
283+
})
284+
285+
test('should not update token if it is the same', () => {
286+
const client = createClient(URL, KEY)
287+
const existingToken = 'existing-token'
288+
;(client as any).changedAccessToken = existingToken
289+
290+
// Mock realtime.setAuth
291+
client.realtime.setAuth = jest.fn()
292+
;(client as any)._handleTokenChanged('TOKEN_REFRESHED', 'CLIENT', existingToken)
293+
294+
expect((client as any).changedAccessToken).toBe(existingToken)
295+
})
296+
297+
test('should handle SIGNED_OUT event from CLIENT source', () => {
298+
const client = createClient(URL, KEY)
299+
;(client as any).changedAccessToken = 'old-token'
300+
301+
// Mock realtime.setAuth
302+
client.realtime.setAuth = jest.fn()
303+
;(client as any)._handleTokenChanged('SIGNED_OUT', 'CLIENT')
304+
305+
expect(client.realtime.setAuth).toHaveBeenCalled()
306+
expect((client as any).changedAccessToken).toBeUndefined()
307+
})
308+
309+
test('should handle SIGNED_OUT event from STORAGE source', () => {
310+
const client = createClient(URL, KEY)
311+
;(client as any).changedAccessToken = 'old-token'
312+
313+
// Mock realtime.setAuth and auth.signOut
314+
client.realtime.setAuth = jest.fn()
315+
client.auth.signOut = jest.fn()
316+
;(client as any)._handleTokenChanged('SIGNED_OUT', 'STORAGE')
317+
318+
expect(client.realtime.setAuth).toHaveBeenCalled()
319+
expect(client.auth.signOut).toHaveBeenCalled()
320+
expect((client as any).changedAccessToken).toBeUndefined()
321+
})
322+
})
182323
})

test/unit/constants.test.ts

Lines changed: 102 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,105 @@
1-
import { DEFAULT_HEADERS } from '../../src/lib/constants'
1+
import {
2+
DEFAULT_HEADERS,
3+
DEFAULT_GLOBAL_OPTIONS,
4+
DEFAULT_DB_OPTIONS,
5+
DEFAULT_AUTH_OPTIONS,
6+
DEFAULT_REALTIME_OPTIONS,
7+
} from '../../src/lib/constants'
28
import { version } from '../../src/lib/version'
39

4-
test('it has the correct type of returning with the correct value', () => {
5-
let JS_ENV = ''
6-
// @ts-ignore
7-
if (typeof Deno !== 'undefined') {
8-
JS_ENV = 'deno'
9-
} else if (typeof document !== 'undefined') {
10-
JS_ENV = 'web'
11-
} else if (typeof navigator !== 'undefined' && navigator.product === 'ReactNative') {
12-
JS_ENV = 'react-native'
13-
} else {
14-
JS_ENV = 'node'
15-
}
16-
const expected = {
17-
'X-Client-Info': `supabase-js-${JS_ENV}/${version}`,
18-
}
19-
expect(DEFAULT_HEADERS).toEqual(expected)
20-
expect(typeof DEFAULT_HEADERS).toBe('object')
21-
expect(typeof DEFAULT_HEADERS['X-Client-Info']).toBe('string')
22-
expect(Object.keys(DEFAULT_HEADERS).length).toBe(1)
10+
describe('constants', () => {
11+
const originalEnv = process.env
12+
const originalWindow = global.window
13+
const originalDocument = global.document
14+
const originalNavigator = global.navigator
15+
const originalDeno = (global as any).Deno
16+
17+
beforeEach(() => {
18+
jest.resetModules()
19+
// Reset globals
20+
delete (global as any).window
21+
delete (global as any).document
22+
delete (global as any).navigator
23+
delete (global as any).Deno
24+
})
25+
26+
afterEach(() => {
27+
// Restore globals
28+
if (originalWindow) global.window = originalWindow
29+
if (originalDocument) global.document = originalDocument
30+
if (originalNavigator) global.navigator = originalNavigator
31+
if (originalDeno) (global as any).Deno = originalDeno
32+
})
33+
34+
test('DEFAULT_HEADERS should contain X-Client-Info', () => {
35+
expect(DEFAULT_HEADERS).toHaveProperty('X-Client-Info')
36+
expect(DEFAULT_HEADERS['X-Client-Info']).toMatch(/^supabase-js-.*\/.*$/)
37+
})
38+
39+
test('DEFAULT_GLOBAL_OPTIONS should contain headers', () => {
40+
expect(DEFAULT_GLOBAL_OPTIONS).toHaveProperty('headers')
41+
expect(DEFAULT_GLOBAL_OPTIONS.headers).toBe(DEFAULT_HEADERS)
42+
})
43+
44+
test('DEFAULT_DB_OPTIONS should have schema set to public', () => {
45+
expect(DEFAULT_DB_OPTIONS).toHaveProperty('schema')
46+
expect(DEFAULT_DB_OPTIONS.schema).toBe('public')
47+
})
48+
49+
test('DEFAULT_AUTH_OPTIONS should have correct default values', () => {
50+
expect(DEFAULT_AUTH_OPTIONS).toHaveProperty('autoRefreshToken')
51+
expect(DEFAULT_AUTH_OPTIONS.autoRefreshToken).toBe(true)
52+
expect(DEFAULT_AUTH_OPTIONS).toHaveProperty('persistSession')
53+
expect(DEFAULT_AUTH_OPTIONS.persistSession).toBe(true)
54+
expect(DEFAULT_AUTH_OPTIONS).toHaveProperty('detectSessionInUrl')
55+
expect(DEFAULT_AUTH_OPTIONS.detectSessionInUrl).toBe(true)
56+
expect(DEFAULT_AUTH_OPTIONS).toHaveProperty('flowType')
57+
expect(DEFAULT_AUTH_OPTIONS.flowType).toBe('implicit')
58+
})
59+
60+
test('DEFAULT_REALTIME_OPTIONS should be an empty object', () => {
61+
expect(DEFAULT_REALTIME_OPTIONS).toEqual({})
62+
})
63+
64+
describe('JS_ENV detection', () => {
65+
test('should detect Deno environment', () => {
66+
;(global as any).Deno = {}
67+
68+
// Re-import to trigger the detection logic
69+
jest.resetModules()
70+
const { DEFAULT_HEADERS: newHeaders } = require('../../src/lib/constants')
71+
72+
expect(newHeaders['X-Client-Info']).toContain('supabase-js-deno')
73+
})
74+
75+
test('should detect web environment', () => {
76+
global.document = {} as any
77+
78+
// Re-import to trigger the detection logic
79+
jest.resetModules()
80+
const { DEFAULT_HEADERS: newHeaders } = require('../../src/lib/constants')
81+
82+
expect(newHeaders['X-Client-Info']).toContain('supabase-js-web')
83+
})
84+
85+
test('should detect React Native environment', () => {
86+
global.navigator = { product: 'ReactNative' } as any
87+
88+
// Re-import to trigger the detection logic
89+
jest.resetModules()
90+
const { DEFAULT_HEADERS: newHeaders } = require('../../src/lib/constants')
91+
92+
expect(newHeaders['X-Client-Info']).toContain('supabase-js-react-native')
93+
})
94+
95+
test('should default to node environment when no specific environment is detected', () => {
96+
// No globals set
97+
98+
// Re-import to trigger the detection logic
99+
jest.resetModules()
100+
const { DEFAULT_HEADERS: newHeaders } = require('../../src/lib/constants')
101+
102+
expect(newHeaders['X-Client-Info']).toContain('supabase-js-node')
103+
})
104+
})
23105
})

0 commit comments

Comments
 (0)