|
1 | 1 | /** biome-ignore-all lint/suspicious/noExplicitAny: any is used to allow for flexibility in the type */ |
2 | 2 | import { expect, test } from 'bun:test' |
3 | 3 | import { createApi } from '@devup-api/fetch' |
4 | | -import { DevupQueryClient, getQueryKey } from '../query-client' |
| 4 | +import { DevupQueryClient } from '../query-client' |
| 5 | + |
| 6 | +const api = createApi({ baseUrl: 'https://api.example.com' }) |
| 7 | +const queryClient = new DevupQueryClient(api as any) |
5 | 8 |
|
6 | 9 | test('DevupQueryClient constructor', () => { |
7 | | - const api = createApi({ baseUrl: 'https://api.example.com' }) |
8 | | - const queryClient = new DevupQueryClient(api) |
9 | 10 | expect(queryClient).toBeInstanceOf(DevupQueryClient) |
10 | 11 | }) |
11 | 12 |
|
12 | 13 | test('DevupQueryClient useQuery method exists', () => { |
13 | | - const api = createApi({ baseUrl: 'https://api.example.com' }) |
14 | | - const queryClient = new DevupQueryClient(api) |
15 | 14 | expect(typeof queryClient.useQuery).toBe('function') |
16 | 15 | }) |
17 | 16 |
|
18 | 17 | test('DevupQueryClient useMutation method exists', () => { |
19 | | - const api = createApi({ baseUrl: 'https://api.example.com' }) |
20 | | - const queryClient = new DevupQueryClient(api) |
21 | 18 | expect(typeof queryClient.useMutation).toBe('function') |
22 | 19 | }) |
23 | 20 |
|
24 | 21 | test('DevupQueryClient useSuspenseQuery method exists', () => { |
25 | | - const api = createApi({ baseUrl: 'https://api.example.com' }) |
26 | | - const queryClient = new DevupQueryClient(api) |
27 | 22 | expect(typeof queryClient.useSuspenseQuery).toBe('function') |
28 | 23 | }) |
29 | 24 |
|
30 | 25 | test('DevupQueryClient useInfiniteQuery method exists', () => { |
31 | | - const api = createApi({ baseUrl: 'https://api.example.com' }) |
32 | | - const queryClient = new DevupQueryClient(api) |
33 | 26 | expect(typeof queryClient.useInfiniteQuery).toBe('function') |
34 | 27 | }) |
35 | 28 |
|
36 | 29 | test('DevupQueryClient useQueries method exists', () => { |
37 | | - const api = createApi({ baseUrl: 'https://api.example.com' }) |
38 | | - const queryClient = new DevupQueryClient(api) |
39 | 30 | expect(typeof queryClient.useQueries).toBe('function') |
40 | 31 | }) |
41 | 32 |
|
42 | 33 | test('getQueryKey returns correct key without options', () => { |
43 | | - const result = getQueryKey('get', '/test', undefined) |
| 34 | + const result = queryClient.getQueryKey('get' as any, '/test' as any) |
44 | 35 | expect(result).toEqual(['get', '/test']) |
45 | 36 | }) |
46 | 37 |
|
47 | 38 | test('getQueryKey returns correct key with options', () => { |
48 | 39 | const options = { params: { id: '123' } } |
49 | | - const result = getQueryKey('get', '/test', options) |
| 40 | + const result = queryClient.getQueryKey( |
| 41 | + 'get' as any, |
| 42 | + '/test' as any, |
| 43 | + options as any, |
| 44 | + ) |
50 | 45 | expect(result).toEqual(['get', '/test', options]) |
51 | 46 | }) |
52 | 47 |
|
53 | 48 | test('getQueryKey handles different methods', () => { |
54 | 49 | const methods = ['get', 'post', 'put', 'delete', 'patch'] as const |
55 | 50 | for (const method of methods) { |
56 | | - const result = getQueryKey(method, '/test', undefined) |
| 51 | + const result = queryClient.getQueryKey(method as any, '/test' as any) |
57 | 52 | expect(result).toEqual([method, '/test']) |
58 | 53 | } |
59 | 54 | }) |
60 | 55 |
|
61 | 56 | test('getQueryKey handles different paths', () => { |
62 | 57 | const paths = ['/test', '/users', '/users/{id}'] as const |
63 | 58 | for (const path of paths) { |
64 | | - const result = getQueryKey('get', path, undefined) |
| 59 | + const result = queryClient.getQueryKey('get' as any, path as any) |
65 | 60 | expect(result).toEqual(['get', path]) |
66 | 61 | } |
67 | 62 | }) |
68 | 63 |
|
69 | 64 | test('getQueryKey handles different option types', () => { |
70 | 65 | const options1 = { params: { id: '123' } } |
71 | | - const result1 = getQueryKey('get', '/test', options1) |
| 66 | + const result1 = queryClient.getQueryKey( |
| 67 | + 'get' as any, |
| 68 | + '/test' as any, |
| 69 | + options1 as any, |
| 70 | + ) |
72 | 71 | expect(result1).toEqual(['get', '/test', options1]) |
73 | 72 |
|
74 | 73 | const options2 = { query: { page: 1 } } |
75 | | - const result2 = getQueryKey('get', '/test', options2) |
| 74 | + const result2 = queryClient.getQueryKey( |
| 75 | + 'get' as any, |
| 76 | + '/test' as any, |
| 77 | + options2 as any, |
| 78 | + ) |
76 | 79 | expect(result2).toEqual(['get', '/test', options2]) |
77 | 80 |
|
78 | 81 | const options3 = { params: { id: '123' }, query: { page: 1 } } |
79 | | - const result3 = getQueryKey('get', '/test', options3) |
| 82 | + const result3 = queryClient.getQueryKey( |
| 83 | + 'get' as any, |
| 84 | + '/test' as any, |
| 85 | + options3 as any, |
| 86 | + ) |
80 | 87 | expect(result3).toEqual(['get', '/test', options3]) |
81 | 88 | }) |
| 89 | + |
| 90 | +test('getQueryKey normalizes method to lowercase', () => { |
| 91 | + const upper = queryClient.getQueryKey('GET' as any, '/test' as any) |
| 92 | + const lower = queryClient.getQueryKey('get' as any, '/test' as any) |
| 93 | + expect(upper).toEqual(lower) |
| 94 | + expect(upper).toEqual(['get', '/test']) |
| 95 | +}) |
| 96 | + |
| 97 | +test('getQueryKey normalizes method to lowercase with options', () => { |
| 98 | + const options = { params: { id: '123' } } |
| 99 | + const upper = queryClient.getQueryKey( |
| 100 | + 'POST' as any, |
| 101 | + '/test' as any, |
| 102 | + options as any, |
| 103 | + ) |
| 104 | + const lower = queryClient.getQueryKey( |
| 105 | + 'post' as any, |
| 106 | + '/test' as any, |
| 107 | + options as any, |
| 108 | + ) |
| 109 | + expect(upper).toEqual(lower) |
| 110 | + expect(upper).toEqual(['post', '/test', options]) |
| 111 | +}) |
| 112 | + |
| 113 | +test('getQueryKey normalizes all HTTP methods', () => { |
| 114 | + const methods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'] as const |
| 115 | + for (const method of methods) { |
| 116 | + const result = queryClient.getQueryKey(method as any, '/test' as any) |
| 117 | + expect(result[0]).toBe(method.toLowerCase()) |
| 118 | + } |
| 119 | +}) |
| 120 | + |
| 121 | +test('resolveEndpoint falls back to key itself when no URL map entry', () => { |
| 122 | + const resolved = api.resolveEndpoint('GET' as any, '/users' as any) |
| 123 | + expect(resolved.url).toBe('/users') |
| 124 | + expect(resolved.method).toBe('GET') |
| 125 | +}) |
| 126 | + |
| 127 | +test('resolveEndpoint returns key as url for unknown operationId', () => { |
| 128 | + const resolved = api.resolveEndpoint('GET' as any, 'unknownOp' as any) |
| 129 | + expect(resolved.url).toBe('unknownOp') |
| 130 | +}) |
| 131 | + |
| 132 | +test('getQueryKey produces consistent keys for same resolved URL', () => { |
| 133 | + const resolvedUrl = api.resolveEndpoint('GET' as any, '/users' as any).url |
| 134 | + const key1 = queryClient.getQueryKey('GET' as any, resolvedUrl as any) |
| 135 | + const key2 = queryClient.getQueryKey('get' as any, '/users' as any) |
| 136 | + expect(key1).toEqual(key2) |
| 137 | + expect(key1).toEqual(['get', '/users']) |
| 138 | +}) |
| 139 | + |
| 140 | +test('getQueryKey produces identical keys when resolved URL matches path', () => { |
| 141 | + const key1 = queryClient.getQueryKey( |
| 142 | + 'GET' as any, |
| 143 | + '/users' as any, |
| 144 | + { query: { page: 1 } } as any, |
| 145 | + ) |
| 146 | + const key2 = queryClient.getQueryKey( |
| 147 | + 'get' as any, |
| 148 | + '/users' as any, |
| 149 | + { query: { page: 1 } } as any, |
| 150 | + ) |
| 151 | + expect(key1).toEqual(key2) |
| 152 | + expect(key1).toEqual(['get', '/users', { query: { page: 1 } }]) |
| 153 | +}) |
0 commit comments