@websolutespa/bom-mixer-hooks 3.1.0 → 3.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/package.json +7 -7
- package/src/useApi/useApi.test.tsx +193 -193
- package/src/useCollectionApi/useCollectionApi.test.tsx +194 -194
- package/src/useHttp/useHttp.test.tsx +197 -197
- package/src/usePagination/usePagination.test.ts +79 -79
- package/src/usePaginationLegacy/usePaginationLegacy.test.ts +1 -1
- package/src/useSearchParams/useSearchParams.test.ts +65 -65
- package/src/useSearchParamsEncoded/useSearchParamsEncoded.test.ts +64 -64
- package/src/useSearchParamsQs/useSearchParamsQs.test.ts +82 -82
|
@@ -1,194 +1,194 @@
|
|
|
1
|
-
import { render, renderHook, screen, waitFor, waitForElementToBeRemoved } from '@testing-library/react';
|
|
2
|
-
import { ILayout } from '@websolutespa/bom-core';
|
|
3
|
-
import { getLocalApiUrl } from '@websolutespa/bom-mixer-store';
|
|
4
|
-
import { afterAll, beforeEach, describe, expect, test, vi } from 'vitest';
|
|
5
|
-
import { useApiFetch } from '../useApi/useApi';
|
|
6
|
-
import { LayoutProvider } from '../useLayout/useLayout';
|
|
7
|
-
import { LayoutDefaults } from '../useLayout/useLayout.default';
|
|
8
|
-
import { useCollectionApi, useCollectionApiDelete, useCollectionApiGet, useCollectionApiPatch, useCollectionApiPost, useCollectionApiPut } from './useCollectionApi';
|
|
9
|
-
|
|
10
|
-
const wrapper = (props: { children: React.ReactNode }) => (
|
|
11
|
-
<LayoutProvider layout={LayoutDefaults as ILayout}>{props.children}</LayoutProvider>
|
|
12
|
-
);
|
|
13
|
-
|
|
14
|
-
const defaultResponse = {
|
|
15
|
-
ok: true,
|
|
16
|
-
status: 200,
|
|
17
|
-
json: () => Promise.resolve(null),
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
function mockFetch(
|
|
21
|
-
method: string = 'GET',
|
|
22
|
-
result: any = { message: 'ok' },
|
|
23
|
-
overrideResponse: Partial<typeof defaultResponse> = {}
|
|
24
|
-
) {
|
|
25
|
-
const endpoint = '/endpoint';
|
|
26
|
-
const url = `${getLocalApiUrl(endpoint)}?locale=en&market=ww`;
|
|
27
|
-
const payload = { data: 'data' };
|
|
28
|
-
const response = {
|
|
29
|
-
...defaultResponse,
|
|
30
|
-
...overrideResponse,
|
|
31
|
-
json: () => Promise.resolve(result),
|
|
32
|
-
} as Response;
|
|
33
|
-
global.fetch = vi.fn(() =>
|
|
34
|
-
Promise.resolve(response)
|
|
35
|
-
);
|
|
36
|
-
const request: {
|
|
37
|
-
body?: string;
|
|
38
|
-
headers: { [key: string]: string },
|
|
39
|
-
method: string;
|
|
40
|
-
} = {
|
|
41
|
-
headers: {
|
|
42
|
-
'Content-Type': 'application/json',
|
|
43
|
-
},
|
|
44
|
-
method,
|
|
45
|
-
};
|
|
46
|
-
if (['POST', 'PATCH', 'PUT'].includes(method)) {
|
|
47
|
-
request.body = JSON.stringify(payload);
|
|
48
|
-
}
|
|
49
|
-
return { endpoint, url, payload, result, request, response };
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
describe('useCollectionApi', () => {
|
|
53
|
-
const ENV = process.env;
|
|
54
|
-
const FETCH = global.fetch;
|
|
55
|
-
|
|
56
|
-
beforeEach(() => {
|
|
57
|
-
vi.resetModules();
|
|
58
|
-
vi.resetAllMocks();
|
|
59
|
-
vi.spyOn(console, 'error').mockImplementation(() => { });
|
|
60
|
-
vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
61
|
-
process.env = {
|
|
62
|
-
MIXER_SECRET: 'MIXER_SECRET_32_CHARS_LONG_12345',
|
|
63
|
-
NEXT_PUBLIC_API: '/api',
|
|
64
|
-
NEXT_PUBLIC_MOCK_FALLBACK_URL: 'http://localhost:3000',
|
|
65
|
-
NEXT_PUBLIC_URL: 'http://localhost:3000',
|
|
66
|
-
NODE_ENV: 'test',
|
|
67
|
-
STORE_API_KEY: 'STORE_API_KEY',
|
|
68
|
-
STORE_API: '/bowl/api',
|
|
69
|
-
STORE_STRATEGY: 'mock',
|
|
70
|
-
STORE_URL: 'http://localhost:4000',
|
|
71
|
-
};
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
afterAll(() => {
|
|
75
|
-
process.env = ENV;
|
|
76
|
-
global.fetch = FETCH;
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
test('should throw without provider', () => {
|
|
80
|
-
expect(() => {
|
|
81
|
-
renderHook(() => useCollectionApi());
|
|
82
|
-
}).toThrow('useGenericContext must be used within a Provider');
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
test('should not throw with provider', () => {
|
|
86
|
-
expect(() => {
|
|
87
|
-
renderHook(() => useCollectionApi(), { wrapper });
|
|
88
|
-
}).not.toThrow();
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
test('api.get should return ok', async () => {
|
|
92
|
-
const { result } = renderHook(() => useCollectionApi(), { wrapper });
|
|
93
|
-
const mock = mockFetch();
|
|
94
|
-
const response = await result.current.get(mock.endpoint);
|
|
95
|
-
expect(fetch).toHaveBeenCalledTimes(1);
|
|
96
|
-
expect(fetch).toHaveBeenCalledWith(mock.url, mock.request);
|
|
97
|
-
expect(response).toBe(mock.result);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
test('api.post should return ok', async () => {
|
|
101
|
-
const { result } = renderHook(() => useCollectionApi(), { wrapper });
|
|
102
|
-
const mock = mockFetch('POST');
|
|
103
|
-
const response = await result.current.post(mock.endpoint, mock.payload);
|
|
104
|
-
expect(fetch).toHaveBeenCalledTimes(1);
|
|
105
|
-
expect(fetch).toHaveBeenCalledWith(mock.url, mock.request);
|
|
106
|
-
expect(response).toBe(mock.result);
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
test('api.patch should return ok', async () => {
|
|
110
|
-
const { result } = renderHook(() => useCollectionApi(), { wrapper });
|
|
111
|
-
const mock = mockFetch('PATCH');
|
|
112
|
-
const response = await result.current.patch(mock.endpoint, mock.payload);
|
|
113
|
-
expect(fetch).toHaveBeenCalledTimes(1);
|
|
114
|
-
expect(fetch).toHaveBeenCalledWith(mock.url, mock.request);
|
|
115
|
-
expect(response).toBe(mock.result);
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
test('api.put should return ok', async () => {
|
|
119
|
-
const { result } = renderHook(() => useCollectionApi(), { wrapper });
|
|
120
|
-
const mock = mockFetch('PUT');
|
|
121
|
-
const response = await result.current.put(mock.endpoint, mock.payload);
|
|
122
|
-
expect(fetch).toHaveBeenCalledTimes(1);
|
|
123
|
-
expect(fetch).toHaveBeenCalledWith(mock.url, mock.request);
|
|
124
|
-
expect(response).toBe(mock.result);
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
test('api.delete should return ok', async () => {
|
|
128
|
-
const { result } = renderHook(() => useCollectionApi(), { wrapper });
|
|
129
|
-
const mock = mockFetch('DELETE');
|
|
130
|
-
const response = await result.current.delete(mock.endpoint);
|
|
131
|
-
expect(fetch).toHaveBeenCalledTimes(1);
|
|
132
|
-
expect(fetch).toHaveBeenCalledWith(mock.url, mock.request);
|
|
133
|
-
expect(response).toBe(mock.result);
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
test('useCollectionApiGet expect result ok', TestMethod('GET'));
|
|
137
|
-
|
|
138
|
-
test('useCollectionApiPost expect result ok', TestMethod('POST'));
|
|
139
|
-
|
|
140
|
-
test('useCollectionApiPatch expect result ok', TestMethod('PATCH'));
|
|
141
|
-
|
|
142
|
-
test('useCollectionApiPut expect result ok', TestMethod('PUT'));
|
|
143
|
-
|
|
144
|
-
test('useCollectionApiDelete expect result ok', TestMethod('DELETE'));
|
|
145
|
-
|
|
146
|
-
function TestMethod(method?: string) {
|
|
147
|
-
const useHook = (mock: ReturnType<typeof mockFetch>) => {
|
|
148
|
-
switch (method) {
|
|
149
|
-
case 'GET':
|
|
150
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
151
|
-
return useCollectionApiGet(mock.endpoint);
|
|
152
|
-
case 'POST':
|
|
153
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
154
|
-
return useCollectionApiPost(mock.endpoint, mock.payload);
|
|
155
|
-
case 'PATCH':
|
|
156
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
157
|
-
return useCollectionApiPatch(mock.endpoint, mock.payload);
|
|
158
|
-
case 'PUT':
|
|
159
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
160
|
-
return useCollectionApiPut(mock.endpoint, mock.payload);
|
|
161
|
-
case 'DELETE':
|
|
162
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
163
|
-
return useCollectionApiDelete(mock.endpoint);
|
|
164
|
-
default:
|
|
165
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
166
|
-
return useApiFetch(mock.endpoint);
|
|
167
|
-
}
|
|
168
|
-
};
|
|
169
|
-
return async () => {
|
|
170
|
-
const mock = mockFetch(method);
|
|
171
|
-
const Wrapper = () => {
|
|
172
|
-
const [response, loading, error, setError] = useHook(mock);
|
|
173
|
-
return (
|
|
174
|
-
<>
|
|
175
|
-
{loading && <div data-testid="loading">loading</div>}
|
|
176
|
-
{response && <div data-testid="result">{JSON.stringify(response)}</div>}
|
|
177
|
-
{error && <div data-testid="error">{JSON.stringify(error)}</div>}
|
|
178
|
-
</>
|
|
179
|
-
);
|
|
180
|
-
};
|
|
181
|
-
render(
|
|
182
|
-
<LayoutProvider layout={LayoutDefaults as ILayout}><Wrapper /></LayoutProvider>
|
|
183
|
-
);
|
|
184
|
-
expect(screen.getByTestId('loading')).toHaveTextContent('loading');
|
|
185
|
-
await waitForElementToBeRemoved(() => screen.getByTestId('loading'));
|
|
186
|
-
expect(fetch).toHaveBeenCalledTimes(1);
|
|
187
|
-
expect(fetch).toHaveBeenCalledWith(mock.url, mock.request);
|
|
188
|
-
const result = await waitFor(() => screen.getByTestId('result'));
|
|
189
|
-
expect(result).toHaveTextContent(JSON.stringify(mock.result));
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
});
|
|
194
|
-
|
|
1
|
+
import { render, renderHook, screen, waitFor, waitForElementToBeRemoved } from '@testing-library/react';
|
|
2
|
+
import { ILayout } from '@websolutespa/bom-core';
|
|
3
|
+
import { getLocalApiUrl } from '@websolutespa/bom-mixer-store';
|
|
4
|
+
import { afterAll, beforeEach, describe, expect, test, vi } from 'vitest';
|
|
5
|
+
import { useApiFetch } from '../useApi/useApi';
|
|
6
|
+
import { LayoutProvider } from '../useLayout/useLayout';
|
|
7
|
+
import { LayoutDefaults } from '../useLayout/useLayout.default';
|
|
8
|
+
import { useCollectionApi, useCollectionApiDelete, useCollectionApiGet, useCollectionApiPatch, useCollectionApiPost, useCollectionApiPut } from './useCollectionApi';
|
|
9
|
+
|
|
10
|
+
const wrapper = (props: { children: React.ReactNode }) => (
|
|
11
|
+
<LayoutProvider layout={LayoutDefaults as ILayout}>{props.children}</LayoutProvider>
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
const defaultResponse = {
|
|
15
|
+
ok: true,
|
|
16
|
+
status: 200,
|
|
17
|
+
json: () => Promise.resolve(null),
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
function mockFetch(
|
|
21
|
+
method: string = 'GET',
|
|
22
|
+
result: any = { message: 'ok' },
|
|
23
|
+
overrideResponse: Partial<typeof defaultResponse> = {}
|
|
24
|
+
) {
|
|
25
|
+
const endpoint = '/endpoint';
|
|
26
|
+
const url = `${getLocalApiUrl(endpoint)}?locale=en&market=ww`;
|
|
27
|
+
const payload = { data: 'data' };
|
|
28
|
+
const response = {
|
|
29
|
+
...defaultResponse,
|
|
30
|
+
...overrideResponse,
|
|
31
|
+
json: () => Promise.resolve(result),
|
|
32
|
+
} as Response;
|
|
33
|
+
global.fetch = vi.fn(() =>
|
|
34
|
+
Promise.resolve(response)
|
|
35
|
+
);
|
|
36
|
+
const request: {
|
|
37
|
+
body?: string;
|
|
38
|
+
headers: { [key: string]: string },
|
|
39
|
+
method: string;
|
|
40
|
+
} = {
|
|
41
|
+
headers: {
|
|
42
|
+
'Content-Type': 'application/json',
|
|
43
|
+
},
|
|
44
|
+
method,
|
|
45
|
+
};
|
|
46
|
+
if (['POST', 'PATCH', 'PUT'].includes(method)) {
|
|
47
|
+
request.body = JSON.stringify(payload);
|
|
48
|
+
}
|
|
49
|
+
return { endpoint, url, payload, result, request, response };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
describe('useCollectionApi', () => {
|
|
53
|
+
const ENV = process.env;
|
|
54
|
+
const FETCH = global.fetch;
|
|
55
|
+
|
|
56
|
+
beforeEach(() => {
|
|
57
|
+
vi.resetModules();
|
|
58
|
+
vi.resetAllMocks();
|
|
59
|
+
vi.spyOn(console, 'error').mockImplementation(() => { });
|
|
60
|
+
vi.spyOn(console, 'log').mockImplementation(() => { });
|
|
61
|
+
process.env = {
|
|
62
|
+
MIXER_SECRET: 'MIXER_SECRET_32_CHARS_LONG_12345',
|
|
63
|
+
NEXT_PUBLIC_API: '/api',
|
|
64
|
+
NEXT_PUBLIC_MOCK_FALLBACK_URL: 'http://localhost:3000',
|
|
65
|
+
NEXT_PUBLIC_URL: 'http://localhost:3000',
|
|
66
|
+
NODE_ENV: 'test',
|
|
67
|
+
STORE_API_KEY: 'STORE_API_KEY',
|
|
68
|
+
STORE_API: '/bowl/api',
|
|
69
|
+
STORE_STRATEGY: 'mock',
|
|
70
|
+
STORE_URL: 'http://localhost:4000',
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
afterAll(() => {
|
|
75
|
+
process.env = ENV;
|
|
76
|
+
global.fetch = FETCH;
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test('should throw without provider', () => {
|
|
80
|
+
expect(() => {
|
|
81
|
+
renderHook(() => useCollectionApi());
|
|
82
|
+
}).toThrow('useGenericContext must be used within a Provider');
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
test('should not throw with provider', () => {
|
|
86
|
+
expect(() => {
|
|
87
|
+
renderHook(() => useCollectionApi(), { wrapper });
|
|
88
|
+
}).not.toThrow();
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test('api.get should return ok', async () => {
|
|
92
|
+
const { result } = renderHook(() => useCollectionApi(), { wrapper });
|
|
93
|
+
const mock = mockFetch();
|
|
94
|
+
const response = await result.current.get(mock.endpoint);
|
|
95
|
+
expect(fetch).toHaveBeenCalledTimes(1);
|
|
96
|
+
expect(fetch).toHaveBeenCalledWith(mock.url, mock.request);
|
|
97
|
+
expect(response).toBe(mock.result);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test('api.post should return ok', async () => {
|
|
101
|
+
const { result } = renderHook(() => useCollectionApi(), { wrapper });
|
|
102
|
+
const mock = mockFetch('POST');
|
|
103
|
+
const response = await result.current.post(mock.endpoint, mock.payload);
|
|
104
|
+
expect(fetch).toHaveBeenCalledTimes(1);
|
|
105
|
+
expect(fetch).toHaveBeenCalledWith(mock.url, mock.request);
|
|
106
|
+
expect(response).toBe(mock.result);
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('api.patch should return ok', async () => {
|
|
110
|
+
const { result } = renderHook(() => useCollectionApi(), { wrapper });
|
|
111
|
+
const mock = mockFetch('PATCH');
|
|
112
|
+
const response = await result.current.patch(mock.endpoint, mock.payload);
|
|
113
|
+
expect(fetch).toHaveBeenCalledTimes(1);
|
|
114
|
+
expect(fetch).toHaveBeenCalledWith(mock.url, mock.request);
|
|
115
|
+
expect(response).toBe(mock.result);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test('api.put should return ok', async () => {
|
|
119
|
+
const { result } = renderHook(() => useCollectionApi(), { wrapper });
|
|
120
|
+
const mock = mockFetch('PUT');
|
|
121
|
+
const response = await result.current.put(mock.endpoint, mock.payload);
|
|
122
|
+
expect(fetch).toHaveBeenCalledTimes(1);
|
|
123
|
+
expect(fetch).toHaveBeenCalledWith(mock.url, mock.request);
|
|
124
|
+
expect(response).toBe(mock.result);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
test('api.delete should return ok', async () => {
|
|
128
|
+
const { result } = renderHook(() => useCollectionApi(), { wrapper });
|
|
129
|
+
const mock = mockFetch('DELETE');
|
|
130
|
+
const response = await result.current.delete(mock.endpoint);
|
|
131
|
+
expect(fetch).toHaveBeenCalledTimes(1);
|
|
132
|
+
expect(fetch).toHaveBeenCalledWith(mock.url, mock.request);
|
|
133
|
+
expect(response).toBe(mock.result);
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
test('useCollectionApiGet expect result ok', TestMethod('GET'));
|
|
137
|
+
|
|
138
|
+
test('useCollectionApiPost expect result ok', TestMethod('POST'));
|
|
139
|
+
|
|
140
|
+
test('useCollectionApiPatch expect result ok', TestMethod('PATCH'));
|
|
141
|
+
|
|
142
|
+
test('useCollectionApiPut expect result ok', TestMethod('PUT'));
|
|
143
|
+
|
|
144
|
+
test('useCollectionApiDelete expect result ok', TestMethod('DELETE'));
|
|
145
|
+
|
|
146
|
+
function TestMethod(method?: string) {
|
|
147
|
+
const useHook = (mock: ReturnType<typeof mockFetch>) => {
|
|
148
|
+
switch (method) {
|
|
149
|
+
case 'GET':
|
|
150
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
151
|
+
return useCollectionApiGet(mock.endpoint);
|
|
152
|
+
case 'POST':
|
|
153
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
154
|
+
return useCollectionApiPost(mock.endpoint, mock.payload);
|
|
155
|
+
case 'PATCH':
|
|
156
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
157
|
+
return useCollectionApiPatch(mock.endpoint, mock.payload);
|
|
158
|
+
case 'PUT':
|
|
159
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
160
|
+
return useCollectionApiPut(mock.endpoint, mock.payload);
|
|
161
|
+
case 'DELETE':
|
|
162
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
163
|
+
return useCollectionApiDelete(mock.endpoint);
|
|
164
|
+
default:
|
|
165
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
166
|
+
return useApiFetch(mock.endpoint);
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
return async () => {
|
|
170
|
+
const mock = mockFetch(method);
|
|
171
|
+
const Wrapper = () => {
|
|
172
|
+
const [response, loading, error, setError] = useHook(mock);
|
|
173
|
+
return (
|
|
174
|
+
<>
|
|
175
|
+
{loading && <div data-testid="loading">loading</div>}
|
|
176
|
+
{response && <div data-testid="result">{JSON.stringify(response)}</div>}
|
|
177
|
+
{error && <div data-testid="error">{JSON.stringify(error)}</div>}
|
|
178
|
+
</>
|
|
179
|
+
);
|
|
180
|
+
};
|
|
181
|
+
render(
|
|
182
|
+
<LayoutProvider layout={LayoutDefaults as ILayout}><Wrapper /></LayoutProvider>
|
|
183
|
+
);
|
|
184
|
+
expect(screen.getByTestId('loading')).toHaveTextContent('loading');
|
|
185
|
+
await waitForElementToBeRemoved(() => screen.getByTestId('loading'));
|
|
186
|
+
expect(fetch).toHaveBeenCalledTimes(1);
|
|
187
|
+
expect(fetch).toHaveBeenCalledWith(mock.url, mock.request);
|
|
188
|
+
const result = await waitFor(() => screen.getByTestId('result'));
|
|
189
|
+
expect(result).toHaveTextContent(JSON.stringify(mock.result));
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
});
|
|
194
|
+
|