@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.
@@ -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
+