@plone/volto 19.0.0-alpha.0 → 19.0.0-alpha.1
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/.eslintignore +1 -0
- package/.eslintrc +2 -0
- package/CHANGELOG.md +46 -2
- package/package.json +14 -7
- package/src/actions/actions/actions.test.js +3 -3
- package/src/actions/addons/addons.test.js +15 -12
- package/src/actions/aliases/aliases.test.js +1 -1
- package/src/actions/querystring/querystring.test.js +2 -2
- package/src/actions/types/types.test.js +1 -1
- package/src/components/manage/Actions/Actions.test.jsx +5 -1
- package/src/components/manage/Add/Add.jsx +22 -20
- package/src/components/manage/Add/Add.test.jsx +6 -3
- package/src/components/manage/Aliases/Aliases.test.jsx +7 -7
- package/src/components/manage/Blocks/Block/BlocksForm.jsx +1 -0
- package/src/components/manage/Blocks/Block/BlocksForm.test.jsx +48 -16
- package/src/components/manage/Blocks/Block/Edit.jsx +2 -1
- package/src/components/manage/Blocks/Block/Settings.test.jsx +5 -1
- package/src/components/manage/Blocks/Block/StyleWrapper.jsx +11 -3
- package/src/components/manage/Blocks/Description/View.test.jsx +1 -1
- package/src/components/manage/Blocks/HTML/Edit.test.jsx +12 -5
- package/src/components/manage/Blocks/HTML/View.test.jsx +1 -1
- package/src/components/manage/Blocks/Image/ImageSidebar.test.jsx +6 -2
- package/src/components/manage/Blocks/LeadImage/LeadImageSidebar.test.jsx +8 -1
- package/src/components/manage/Blocks/Listing/View.test.jsx +3 -1
- package/src/components/manage/Blocks/Maps/MapsSidebar.test.jsx +5 -1
- package/src/components/manage/Blocks/Search/components/DateRangeFacet.test.jsx +13 -7
- package/src/components/manage/Blocks/Search/components/SelectFacet.test.jsx +12 -6
- package/src/components/manage/Blocks/ToC/variations/DefaultTocRenderer.test.jsx +11 -1
- package/src/components/manage/Blocks/Video/VideoSidebar.test.jsx +5 -1
- package/src/components/manage/ConditionalLink/ConditionalLink.test.tsx +109 -0
- package/src/components/manage/ConditionalLink/ConditionalLink.tsx +36 -0
- package/src/components/manage/Contents/Contents.test.jsx +29 -13
- package/src/components/manage/Contents/ContentsPropertiesModal.test.jsx +5 -1
- package/src/components/manage/Contents/ContentsRenameModal.test.jsx +5 -1
- package/src/components/manage/Contents/ContentsTagsModal.test.jsx +5 -1
- package/src/components/manage/Contents/ContentsWorkflowModal.test.jsx +5 -1
- package/src/components/manage/Contents/__mocks__/index.tsx +16 -0
- package/src/components/manage/Contents/__mocks__/index.vitest.tsx +5 -0
- package/src/components/manage/Controlpanels/AddonsControlpanel.test.jsx +28 -3
- package/src/components/manage/Controlpanels/Aliases.test.jsx +35 -3
- package/src/components/manage/Controlpanels/ContentType.test.jsx +29 -3
- package/src/components/manage/Controlpanels/ContentTypeLayout.test.jsx +4 -2
- package/src/components/manage/Controlpanels/ContentTypes.test.jsx +25 -2
- package/src/components/manage/Controlpanels/Controlpanel.test.jsx +37 -6
- package/src/components/manage/Controlpanels/Controlpanels.test.jsx +47 -3
- package/src/components/manage/Controlpanels/Groups/GroupsControlpanel.test.jsx +15 -9
- package/src/components/manage/Controlpanels/ModerateComments.test.jsx +31 -5
- package/src/components/manage/Controlpanels/Rules/AddRule.test.jsx +13 -4
- package/src/components/manage/Controlpanels/Rules/ConfigureRule.test.jsx +9 -5
- package/src/components/manage/Controlpanels/Rules/EditRule.test.jsx +12 -4
- package/src/components/manage/Controlpanels/Rules/Rules.test.jsx +7 -3
- package/src/components/manage/Controlpanels/UndoControlpanel.test.jsx +33 -4
- package/src/components/manage/Controlpanels/Users/UserGroupMembershipControlPanel.test.jsx +3 -1
- package/src/components/manage/Controlpanels/Users/UsersControlpanel.test.jsx +15 -9
- package/src/components/manage/Delete/Delete.test.jsx +45 -4
- package/src/components/manage/Diff/Diff.test.jsx +15 -6
- package/src/components/manage/Diff/DiffField.test.jsx +12 -6
- package/src/components/manage/Display/Display.test.jsx +17 -6
- package/src/components/manage/Edit/Edit.test.jsx +11 -3
- package/src/components/manage/Form/BlockDataForm.test.jsx +5 -1
- package/src/components/manage/Form/Form.test.jsx +5 -1
- package/src/components/manage/Form/InlineForm.test.jsx +5 -1
- package/src/components/manage/Form/ModalForm.test.jsx +5 -1
- package/src/components/manage/Form/__mocks__/index.tsx +17 -0
- package/src/components/manage/Form/__mocks__/index.vitest.tsx +73 -0
- package/src/components/manage/History/History.test.jsx +3 -1
- package/src/components/manage/LinksToItem/LinksToItem.test.jsx +6 -4
- package/src/components/manage/MaybeWrap/MaybeWrap.tsx +15 -0
- package/src/components/manage/Multilingual/ManageTranslations.test.jsx +3 -2
- package/src/components/manage/Preferences/ChangePassword.test.jsx +9 -2
- package/src/components/manage/Preferences/PersonalInformation.test.jsx +3 -1
- package/src/components/manage/Preferences/PersonalPreferences.test.jsx +20 -7
- package/src/components/manage/Rules/Rules.test.jsx +6 -3
- package/src/components/manage/Sharing/Sharing.test.jsx +3 -1
- package/src/components/manage/Sidebar/ObjectBrowserNav.test.jsx +3 -3
- package/src/components/manage/Toolbar/More.test.jsx +6 -7
- package/src/components/manage/UniversalLink/UniversalLink.test.jsx +196 -14
- package/src/components/manage/UniversalLink/UniversalLink.tsx +214 -0
- package/src/components/manage/Widgets/ArrayWidget.test.jsx +22 -5
- package/src/components/manage/Widgets/CheckboxGroupWidget.test.jsx +12 -5
- package/src/components/manage/Widgets/DatetimeWidget.test.jsx +21 -6
- package/src/components/manage/Widgets/ImageWidget.jsx +5 -2
- package/src/components/manage/Widgets/NumberWidget.test.jsx +8 -7
- package/src/components/manage/Widgets/ObjectListWidget.jsx +11 -1
- package/src/components/manage/Widgets/ObjectListWidget.test.jsx +18 -8
- package/src/components/manage/Widgets/ObjectWidget.test.jsx +5 -1
- package/src/components/manage/Widgets/RadioGroupWidget.test.jsx +12 -5
- package/src/components/manage/Widgets/RecurrenceWidget/RecurrenceWidget.test.jsx +12 -6
- package/src/components/manage/Widgets/RegistryImageWidget.test.jsx +43 -41
- package/src/components/manage/Widgets/SchemaWidget.test.jsx +12 -5
- package/src/components/manage/Widgets/SchemaWidgetFieldset.test.jsx +12 -5
- package/src/components/manage/Widgets/SelectAutoComplete.test.jsx +12 -6
- package/src/components/manage/Widgets/SelectWidget.test.jsx +12 -6
- package/src/components/manage/Widgets/TimeWidget.test.jsx +13 -5
- package/src/components/manage/Widgets/TokenWidget.test.jsx +12 -6
- package/src/components/manage/Widgets/VocabularyTermsWidget.test.jsx +18 -9
- package/src/components/manage/Widgets/__mocks__/index.tsx +16 -0
- package/src/components/manage/Widgets/__mocks__/index.vitest.tsx +41 -0
- package/src/components/manage/Workflow/Workflow.test.jsx +17 -7
- package/src/components/theme/App/App.test.jsx +21 -17
- package/src/components/theme/AppExtras/AppExtras.test.jsx +6 -6
- package/src/components/theme/Comments/CommentEditModal.test.jsx +5 -1
- package/src/components/theme/Comments/Comments.test.jsx +29 -12
- package/src/components/theme/ContactForm/ContactForm.test.jsx +8 -4
- package/src/components/theme/Header/Header.test.jsx +19 -13
- package/src/components/theme/Logout/Logout.test.jsx +1 -1
- package/src/components/theme/PasswordReset/PasswordReset.test.jsx +10 -1
- package/src/components/theme/PasswordReset/RequestPasswordReset.test.jsx +5 -1
- package/src/components/theme/Register/Register.test.jsx +5 -1
- package/src/components/theme/Search/Search.test.jsx +6 -4
- package/src/components/theme/TsTest/TsTest.test.tsx +0 -1
- package/src/components/theme/View/EventDatesInfo.test.jsx +12 -5
- package/src/components/theme/View/EventView.test.jsx +12 -5
- package/src/components/theme/View/ListingView.test.jsx +2 -0
- package/src/components/theme/View/SummaryView.test.jsx +10 -0
- package/src/components/theme/View/TabularView.test.jsx +1 -0
- package/src/components/theme/View/View.test.jsx +42 -23
- package/src/helpers/Api/Api.plone.rest.test.js +11 -9
- package/src/helpers/Api/Api.test.js +11 -14
- package/src/helpers/AsyncConnect/AsyncConnect.test.jsx +145 -189
- package/src/helpers/AuthToken/AuthToken.test.js +60 -22
- package/src/helpers/Blocks/Blocks.test.js +1 -1
- package/src/helpers/Html/Html.test.jsx +32 -28
- package/src/helpers/Loadable/__mocks__/Loadable.jsx +16 -1
- package/src/helpers/Loadable/__mocks__/Loadable.vitest.jsx +39 -0
- package/src/middleware/Api.test.js +47 -0
- package/src/middleware/api.js +1 -1
- package/src/middleware/storeProtectLoadUtils.test.js +90 -78
- package/test-setup-globals-vitest.js +46 -0
- package/tsconfig.declarations.json +12 -1
- package/tsconfig.json +2 -1
- package/types/components/manage/ConditionalLink/ConditionalLink.d.ts +11 -15
- package/types/components/manage/Contents/__mocks__/index.vitest.d.ts +2 -0
- package/types/components/manage/Form/__mocks__/index.vitest.d.ts +8 -0
- package/types/components/manage/MaybeWrap/MaybeWrap.d.ts +7 -5
- package/types/components/manage/UniversalLink/UniversalLink.d.ts +54 -20
- package/types/components/manage/Widgets/__mocks__/index.vitest.d.ts +33 -0
- package/types/helpers/Loadable/__mocks__/Loadable.vitest.d.ts +3 -0
- package/types/react-router-hash-link.d.ts +12 -0
- package/types/routes.d.ts +4 -0
- package/types/server.d.ts +1 -1
- package/vite-plugins/svg.mjs +81 -0
- package/vitest.config.mjs +77 -0
- package/src/components/manage/ConditionalLink/ConditionalLink.jsx +0 -27
- package/src/components/manage/ConditionalLink/ConditionalLink.test.jsx +0 -30
- package/src/components/manage/MaybeWrap/MaybeWrap.jsx +0 -9
- package/src/components/manage/UniversalLink/UniversalLink.jsx +0 -154
- package/src/components/manage/Widgets/FileWidget.test.jsx +0 -91
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import { Provider, connect } from 'react-redux';
|
|
3
2
|
import { withRouter, StaticRouter, MemoryRouter } from 'react-router';
|
|
4
3
|
import { renderRoutes } from 'react-router-config';
|
|
5
4
|
import { createStore, combineReducers } from 'redux';
|
|
6
|
-
import { render } from '@testing-library/react';
|
|
5
|
+
import { render, act } from '@testing-library/react';
|
|
7
6
|
|
|
8
7
|
import {
|
|
9
8
|
endGlobalLoad,
|
|
@@ -11,7 +10,7 @@ import {
|
|
|
11
10
|
} from '@plone/volto/actions/asyncConnect/asyncConnect';
|
|
12
11
|
import reduxAsyncConnect from '@plone/volto/reducers/asyncConnect/asyncConnect';
|
|
13
12
|
|
|
14
|
-
import { AsyncConnectWithContext, AsyncConnect } from './AsyncConnect';
|
|
13
|
+
import { AsyncConnectWithContext, AsyncConnect } from './AsyncConnect';
|
|
15
14
|
import { asyncConnect, loadOnServer } from './';
|
|
16
15
|
import { matchAllRoutes } from './utils';
|
|
17
16
|
|
|
@@ -23,6 +22,7 @@ describe('<ReduxAsyncConnect />', () => {
|
|
|
23
22
|
},
|
|
24
23
|
},
|
|
25
24
|
};
|
|
25
|
+
|
|
26
26
|
const initialState = {
|
|
27
27
|
router: {
|
|
28
28
|
location: {
|
|
@@ -44,8 +44,8 @@ describe('<ReduxAsyncConnect />', () => {
|
|
|
44
44
|
};
|
|
45
45
|
};
|
|
46
46
|
|
|
47
|
-
const endGlobalLoadSpy =
|
|
48
|
-
const beginGlobalLoadSpy =
|
|
47
|
+
const endGlobalLoadSpy = vi.fn(() => endGlobalLoad());
|
|
48
|
+
const beginGlobalLoadSpy = vi.fn(() => beginGlobalLoad());
|
|
49
49
|
|
|
50
50
|
const ReduxAsyncConnect = withRouter(
|
|
51
51
|
connect(null, {
|
|
@@ -54,11 +54,7 @@ describe('<ReduxAsyncConnect />', () => {
|
|
|
54
54
|
})(AsyncConnectWithContext),
|
|
55
55
|
);
|
|
56
56
|
|
|
57
|
-
/* eslint-disable no-unused-vars */
|
|
58
|
-
/* eslint-enable no-unused-vars */
|
|
59
57
|
const App = ({
|
|
60
|
-
// NOTE: use this as a reference of props passed to your component from router
|
|
61
|
-
// these are the params that are passed from router
|
|
62
58
|
history,
|
|
63
59
|
location,
|
|
64
60
|
params,
|
|
@@ -69,9 +65,7 @@ describe('<ReduxAsyncConnect />', () => {
|
|
|
69
65
|
externalState,
|
|
70
66
|
remappedProp,
|
|
71
67
|
staticContext,
|
|
72
|
-
// our param
|
|
73
68
|
lunch,
|
|
74
|
-
// react-redux dispatch prop
|
|
75
69
|
dispatch,
|
|
76
70
|
...rest
|
|
77
71
|
}) => (
|
|
@@ -85,13 +79,7 @@ describe('<ReduxAsyncConnect />', () => {
|
|
|
85
79
|
</div>
|
|
86
80
|
);
|
|
87
81
|
|
|
88
|
-
const MultiAppA = ({
|
|
89
|
-
route,
|
|
90
|
-
// our param
|
|
91
|
-
breakfast,
|
|
92
|
-
// react-redux dispatch prop
|
|
93
|
-
...rest
|
|
94
|
-
}) => (
|
|
82
|
+
const MultiAppA = ({ route, breakfast, ...rest }) => (
|
|
95
83
|
<div data-testid="MultiAppA">
|
|
96
84
|
<div>{breakfast}</div>
|
|
97
85
|
{renderRoutes(route.routes)}
|
|
@@ -102,6 +90,13 @@ describe('<ReduxAsyncConnect />', () => {
|
|
|
102
90
|
<div data-testid="MultiAppB">{dinner}</div>
|
|
103
91
|
);
|
|
104
92
|
|
|
93
|
+
const UnwrappedApp = ({ route }) => (
|
|
94
|
+
<div data-testid="UnwrappedApp">
|
|
95
|
+
{'Hi, I do not use @asyncConnect'}
|
|
96
|
+
{renderRoutes(route.routes)}
|
|
97
|
+
</div>
|
|
98
|
+
);
|
|
99
|
+
|
|
105
100
|
const WrappedApp = asyncConnect(
|
|
106
101
|
[
|
|
107
102
|
{
|
|
@@ -164,30 +159,6 @@ describe('<ReduxAsyncConnect />', () => {
|
|
|
164
159
|
}),
|
|
165
160
|
)(MultiAppB);
|
|
166
161
|
|
|
167
|
-
const UnwrappedApp = ({ route }) => (
|
|
168
|
-
<div data-testid="UnwrappedApp">
|
|
169
|
-
{'Hi, I do not use @asyncConnect'}
|
|
170
|
-
{renderRoutes(route.routes)}
|
|
171
|
-
</div>
|
|
172
|
-
);
|
|
173
|
-
|
|
174
|
-
const reducers = combineReducers({
|
|
175
|
-
reduxAsyncConnect,
|
|
176
|
-
router: routerReducer,
|
|
177
|
-
});
|
|
178
|
-
|
|
179
|
-
/*
|
|
180
|
-
const routes = (
|
|
181
|
-
<Route path="/">
|
|
182
|
-
<IndexRoute component={WrappedApp} remap="on" />
|
|
183
|
-
<Route path="/notconnected" component={UnwrappedApp} />
|
|
184
|
-
<Route path="/multi" component={WrappedAppA}>
|
|
185
|
-
<IndexRoute components={{ compA: UnwrappedApp, compB: WrappedAppB }} />
|
|
186
|
-
</Route>
|
|
187
|
-
</Route>
|
|
188
|
-
);
|
|
189
|
-
*/
|
|
190
|
-
|
|
191
162
|
const routes = [
|
|
192
163
|
{
|
|
193
164
|
path: '/',
|
|
@@ -213,15 +184,24 @@ describe('<ReduxAsyncConnect />', () => {
|
|
|
213
184
|
},
|
|
214
185
|
];
|
|
215
186
|
|
|
216
|
-
|
|
187
|
+
const reducers = combineReducers({
|
|
188
|
+
reduxAsyncConnect,
|
|
189
|
+
router: routerReducer,
|
|
190
|
+
});
|
|
191
|
+
|
|
217
192
|
let testState;
|
|
218
193
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
194
|
+
beforeEach(() => {
|
|
195
|
+
vi.clearAllMocks();
|
|
196
|
+
});
|
|
222
197
|
|
|
198
|
+
afterEach(() => {
|
|
199
|
+
vi.restoreAllMocks();
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('properly fetches data on the server', async () => {
|
|
223
203
|
const store = createStore(reducers, initialEmptyState);
|
|
224
|
-
const eat =
|
|
204
|
+
const eat = vi.fn(() => 'yammi');
|
|
225
205
|
const helpers = { eat };
|
|
226
206
|
const location = { pathname: '/' };
|
|
227
207
|
|
|
@@ -233,13 +213,15 @@ describe('<ReduxAsyncConnect />', () => {
|
|
|
233
213
|
});
|
|
234
214
|
const context = {};
|
|
235
215
|
|
|
236
|
-
const { getByTestId } =
|
|
237
|
-
|
|
238
|
-
<
|
|
239
|
-
<
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
216
|
+
const { getByTestId } = await act(async () => {
|
|
217
|
+
return render(
|
|
218
|
+
<Provider store={store} key="provider">
|
|
219
|
+
<MemoryRouter>
|
|
220
|
+
<ReduxAsyncConnect routes={routes} helpers={{ eat }} />
|
|
221
|
+
</MemoryRouter>
|
|
222
|
+
</Provider>,
|
|
223
|
+
);
|
|
224
|
+
});
|
|
243
225
|
|
|
244
226
|
if (context.url) {
|
|
245
227
|
throw new Error('redirected');
|
|
@@ -258,224 +240,197 @@ describe('<ReduxAsyncConnect />', () => {
|
|
|
258
240
|
expect(testState.reduxAsyncConnect.loadState.lunch.error).toBe(null);
|
|
259
241
|
|
|
260
242
|
expect(eat).toHaveBeenCalledTimes(1);
|
|
261
|
-
|
|
262
|
-
// global loader spy
|
|
263
243
|
expect(endGlobalLoadSpy).not.toHaveBeenCalled();
|
|
264
244
|
expect(beginGlobalLoadSpy).not.toHaveBeenCalled();
|
|
265
245
|
});
|
|
266
246
|
|
|
267
|
-
it('properly picks data up from the server',
|
|
268
|
-
endGlobalLoadSpy.mockClear();
|
|
269
|
-
beginGlobalLoadSpy.mockClear();
|
|
270
|
-
|
|
247
|
+
it('properly picks data up from the server', async () => {
|
|
271
248
|
const store = createStore(reducers, testState);
|
|
272
249
|
const proto = AsyncConnect.prototype;
|
|
273
|
-
const eat =
|
|
250
|
+
const eat = vi.fn(() => 'yammi');
|
|
274
251
|
|
|
275
|
-
const spyLoadAsyncData =
|
|
276
|
-
const spyComponentDidMount =
|
|
252
|
+
const spyLoadAsyncData = vi.spyOn(proto, 'loadAsyncData');
|
|
253
|
+
const spyComponentDidMount = vi.spyOn(proto, 'componentDidMount');
|
|
277
254
|
|
|
278
|
-
const { getByTestId } =
|
|
279
|
-
|
|
280
|
-
<
|
|
281
|
-
<
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
255
|
+
const { getByTestId } = await act(async () => {
|
|
256
|
+
return render(
|
|
257
|
+
<Provider store={store} key="provider">
|
|
258
|
+
<MemoryRouter>
|
|
259
|
+
<ReduxAsyncConnect routes={routes} helpers={{ eat }} />
|
|
260
|
+
</MemoryRouter>
|
|
261
|
+
</Provider>,
|
|
262
|
+
);
|
|
263
|
+
});
|
|
285
264
|
|
|
286
265
|
expect(spyLoadAsyncData).not.toHaveBeenCalled();
|
|
287
266
|
expect(spyComponentDidMount).toHaveBeenCalledTimes(1);
|
|
288
|
-
|
|
289
267
|
expect(eat).not.toHaveBeenCalled();
|
|
290
268
|
|
|
291
269
|
const app = getByTestId('App');
|
|
292
270
|
expect(app).toHaveTextContent('sandwich');
|
|
293
271
|
|
|
294
|
-
// global loader spy
|
|
295
272
|
expect(endGlobalLoadSpy).not.toHaveBeenCalled();
|
|
296
273
|
expect(beginGlobalLoadSpy).not.toHaveBeenCalled();
|
|
297
|
-
|
|
298
|
-
spyLoadAsyncData.mockClear();
|
|
299
|
-
spyComponentDidMount.mockClear();
|
|
300
274
|
});
|
|
301
275
|
|
|
302
|
-
it("loads data on client side when it wasn't provided by server",
|
|
303
|
-
endGlobalLoadSpy.mockClear();
|
|
304
|
-
beginGlobalLoadSpy.mockClear();
|
|
276
|
+
it("loads data on client side when it wasn't provided by server", async () => {
|
|
305
277
|
const store = createStore(reducers);
|
|
306
|
-
const eat =
|
|
278
|
+
const eat = vi.fn(() => 'yammi');
|
|
307
279
|
const proto = AsyncConnect.prototype;
|
|
308
280
|
|
|
309
|
-
const spyLoadAsyncData =
|
|
310
|
-
const spyComponentDidMount =
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
281
|
+
const spyLoadAsyncData = vi.spyOn(proto, 'loadAsyncData');
|
|
282
|
+
const spyComponentDidMount = vi.spyOn(proto, 'componentDidMount');
|
|
283
|
+
await act(async () => {
|
|
284
|
+
render(
|
|
285
|
+
<Provider store={store} key="provider">
|
|
286
|
+
<MemoryRouter>
|
|
287
|
+
<ReduxAsyncConnect routes={routes} helpers={{ eat }} />
|
|
288
|
+
</MemoryRouter>
|
|
289
|
+
</Provider>,
|
|
290
|
+
);
|
|
291
|
+
});
|
|
319
292
|
|
|
320
293
|
expect(spyLoadAsyncData).toHaveBeenCalledTimes(1);
|
|
321
294
|
expect(spyComponentDidMount).toHaveBeenCalledTimes(1);
|
|
322
|
-
|
|
323
|
-
// global loader spy
|
|
324
295
|
expect(beginGlobalLoadSpy).toHaveBeenCalled();
|
|
325
|
-
beginGlobalLoadSpy.mockClear();
|
|
326
|
-
|
|
327
|
-
return spyLoadAsyncData.mock.results[0].value.then(() => {
|
|
328
|
-
expect(endGlobalLoadSpy).toHaveBeenCalled();
|
|
329
|
-
endGlobalLoadSpy.mockClear();
|
|
330
296
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
});
|
|
297
|
+
await spyLoadAsyncData.mock.results[0].value;
|
|
298
|
+
expect(endGlobalLoadSpy).toHaveBeenCalled();
|
|
334
299
|
});
|
|
335
300
|
|
|
336
|
-
it('supports extended connect signature',
|
|
301
|
+
it('supports extended connect signature', async () => {
|
|
337
302
|
const store = createStore(reducers, initialState);
|
|
338
|
-
const eat =
|
|
303
|
+
const eat = vi.fn(() => 'yammi');
|
|
339
304
|
const proto = AsyncConnect.prototype;
|
|
340
305
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
const { getByTestId } = render(
|
|
345
|
-
<Provider store={store} key="provider">
|
|
346
|
-
<MemoryRouter>
|
|
347
|
-
<ReduxAsyncConnect routes={routes} helpers={{ eat }} />
|
|
348
|
-
</MemoryRouter>
|
|
349
|
-
</Provider>,
|
|
350
|
-
);
|
|
306
|
+
// Add spies for both methods
|
|
307
|
+
const spyLoadAsyncData = vi.spyOn(proto, 'loadAsyncData');
|
|
308
|
+
const spyComponentDidMount = vi.spyOn(proto, 'componentDidMount');
|
|
351
309
|
|
|
352
|
-
|
|
353
|
-
|
|
310
|
+
const { getByTestId } = await act(async () => {
|
|
311
|
+
return render(
|
|
312
|
+
<Provider store={store} key="provider">
|
|
313
|
+
<MemoryRouter>
|
|
314
|
+
<ReduxAsyncConnect routes={routes} helpers={{ eat }} />
|
|
315
|
+
</MemoryRouter>
|
|
316
|
+
</Provider>,
|
|
317
|
+
);
|
|
318
|
+
});
|
|
354
319
|
|
|
355
|
-
|
|
320
|
+
expect(spyLoadAsyncData).toHaveBeenCalledTimes(1);
|
|
321
|
+
expect(spyComponentDidMount).toHaveBeenCalledTimes(1);
|
|
356
322
|
expect(beginGlobalLoadSpy).toHaveBeenCalled();
|
|
357
|
-
beginGlobalLoadSpy.mockClear();
|
|
358
|
-
|
|
359
|
-
return spyLoadAsyncData.mock.results[0].value.then(() => {
|
|
360
|
-
expect(endGlobalLoadSpy).toHaveBeenCalled();
|
|
361
323
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
expect(app).toHaveAttribute('external-state', 'supported');
|
|
365
|
-
expect(app).toHaveAttribute('remapped-prop', 'on');
|
|
366
|
-
expect(app).toHaveTextContent('sandwich');
|
|
324
|
+
await spyLoadAsyncData.mock.results[0].value;
|
|
325
|
+
expect(endGlobalLoadSpy).toHaveBeenCalled();
|
|
367
326
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
327
|
+
const app = getByTestId('App');
|
|
328
|
+
expect(app).toHaveTextContent('sandwich');
|
|
329
|
+
expect(app).toHaveAttribute('external-state', 'supported');
|
|
330
|
+
expect(app).toHaveAttribute('remapped-prop', 'on');
|
|
331
|
+
expect(app).toHaveTextContent('sandwich');
|
|
371
332
|
});
|
|
372
333
|
|
|
373
|
-
it('renders even when no component is connected',
|
|
334
|
+
it('renders even when no component is connected', async () => {
|
|
374
335
|
const store = createStore(reducers);
|
|
375
|
-
const eat =
|
|
336
|
+
const eat = vi.fn(() => 'yammi');
|
|
376
337
|
const location = { pathname: '/notconnected' };
|
|
377
338
|
const helpers = { eat };
|
|
378
339
|
|
|
379
|
-
|
|
340
|
+
await loadOnServer({
|
|
380
341
|
store,
|
|
381
342
|
location,
|
|
382
343
|
routes,
|
|
383
344
|
helpers,
|
|
384
|
-
})
|
|
385
|
-
const context = {};
|
|
345
|
+
});
|
|
386
346
|
|
|
387
|
-
|
|
347
|
+
const context = {};
|
|
348
|
+
|
|
349
|
+
const { getByTestId } = await act(async () => {
|
|
350
|
+
return render(
|
|
388
351
|
<Provider store={store} key="provider">
|
|
389
352
|
<StaticRouter location={location} context={context}>
|
|
390
353
|
<ReduxAsyncConnect routes={routes} helpers={helpers} />
|
|
391
354
|
</StaticRouter>
|
|
392
355
|
</Provider>,
|
|
393
356
|
);
|
|
357
|
+
});
|
|
394
358
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
const app = getByTestId('UnwrappedApp');
|
|
400
|
-
expect(app).toHaveTextContent('Hi, I do not use @asyncConnect');
|
|
359
|
+
if (context.url) {
|
|
360
|
+
throw new Error('redirected');
|
|
361
|
+
}
|
|
401
362
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
expect(testState.reduxAsyncConnect.lunch).toBe(undefined);
|
|
405
|
-
expect(eat).not.toHaveBeenCalled();
|
|
363
|
+
const app = getByTestId('UnwrappedApp');
|
|
364
|
+
expect(app).toHaveTextContent('Hi, I do not use @asyncConnect');
|
|
406
365
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
366
|
+
testState = store.getState();
|
|
367
|
+
expect(testState.reduxAsyncConnect.loaded).toBe(true);
|
|
368
|
+
expect(testState.reduxAsyncConnect.lunch).toBe(undefined);
|
|
369
|
+
expect(eat).not.toHaveBeenCalled();
|
|
410
370
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
});
|
|
371
|
+
expect(endGlobalLoadSpy).not.toHaveBeenCalled();
|
|
372
|
+
expect(beginGlobalLoadSpy).not.toHaveBeenCalled();
|
|
414
373
|
});
|
|
415
374
|
|
|
416
|
-
it('properly fetches data in the correct order given a nested routing structure',
|
|
375
|
+
it('properly fetches data in the correct order given a nested routing structure', async () => {
|
|
417
376
|
const store = createStore(reducers);
|
|
418
377
|
const promiseOrder = [];
|
|
419
|
-
const eat =
|
|
378
|
+
const eat = vi.fn((meal) => {
|
|
420
379
|
promiseOrder.push(meal);
|
|
421
380
|
return `yammi ${meal}`;
|
|
422
381
|
});
|
|
423
382
|
const location = { pathname: '/multi' };
|
|
424
383
|
const helpers = { eat };
|
|
425
384
|
|
|
426
|
-
|
|
385
|
+
await loadOnServer({
|
|
427
386
|
store,
|
|
428
387
|
routes,
|
|
429
388
|
location,
|
|
430
389
|
helpers,
|
|
431
|
-
})
|
|
432
|
-
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
const context = {};
|
|
433
393
|
|
|
434
|
-
|
|
394
|
+
const { container } = await act(async () => {
|
|
395
|
+
return render(
|
|
435
396
|
<Provider store={store} key="provider">
|
|
436
397
|
<StaticRouter location={location} context={context}>
|
|
437
398
|
<ReduxAsyncConnect routes={routes} helpers={helpers} />
|
|
438
399
|
</StaticRouter>
|
|
439
400
|
</Provider>,
|
|
440
401
|
);
|
|
402
|
+
});
|
|
441
403
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
expect(container).toHaveTextContent('omelette');
|
|
447
|
-
expect(container).toHaveTextContent('chicken');
|
|
448
|
-
|
|
449
|
-
testState = store.getState();
|
|
450
|
-
expect(testState.reduxAsyncConnect.loaded).toBe(true);
|
|
451
|
-
expect(testState.reduxAsyncConnect.breakfast).toBe('omelette');
|
|
452
|
-
expect(testState.reduxAsyncConnect.dinner).toBe('chicken');
|
|
453
|
-
expect(testState.reduxAsyncConnect.action).toBe('yammi dinner');
|
|
454
|
-
expect(testState.reduxAsyncConnect.loadState.dinner.loading).toBe(false);
|
|
455
|
-
expect(testState.reduxAsyncConnect.loadState.dinner.loaded).toBe(true);
|
|
456
|
-
expect(testState.reduxAsyncConnect.loadState.dinner.error).toBe(null);
|
|
457
|
-
expect(testState.reduxAsyncConnect.loadState.breakfast.loading).toBe(
|
|
458
|
-
false,
|
|
459
|
-
);
|
|
460
|
-
expect(testState.reduxAsyncConnect.loadState.breakfast.loaded).toBe(true);
|
|
461
|
-
expect(testState.reduxAsyncConnect.loadState.breakfast.error).toBe(null);
|
|
462
|
-
expect(eat).toHaveBeenCalledTimes(2);
|
|
404
|
+
if (context.url) {
|
|
405
|
+
throw new Error('redirected');
|
|
406
|
+
}
|
|
463
407
|
|
|
464
|
-
|
|
408
|
+
expect(container).toHaveTextContent('omelette');
|
|
409
|
+
expect(container).toHaveTextContent('chicken');
|
|
465
410
|
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
411
|
+
testState = store.getState();
|
|
412
|
+
expect(testState.reduxAsyncConnect.loaded).toBe(true);
|
|
413
|
+
expect(testState.reduxAsyncConnect.breakfast).toBe('omelette');
|
|
414
|
+
expect(testState.reduxAsyncConnect.dinner).toBe('chicken');
|
|
415
|
+
expect(testState.reduxAsyncConnect.action).toBe('yammi dinner');
|
|
416
|
+
expect(testState.reduxAsyncConnect.loadState.dinner.loading).toBe(false);
|
|
417
|
+
expect(testState.reduxAsyncConnect.loadState.dinner.loaded).toBe(true);
|
|
418
|
+
expect(testState.reduxAsyncConnect.loadState.dinner.error).toBe(null);
|
|
419
|
+
expect(testState.reduxAsyncConnect.loadState.breakfast.loading).toBe(false);
|
|
420
|
+
expect(testState.reduxAsyncConnect.loadState.breakfast.loaded).toBe(true);
|
|
421
|
+
expect(testState.reduxAsyncConnect.loadState.breakfast.error).toBe(null);
|
|
422
|
+
expect(eat).toHaveBeenCalledTimes(2);
|
|
423
|
+
|
|
424
|
+
expect(promiseOrder).toEqual(['breakfast', 'dinner']);
|
|
469
425
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
});
|
|
426
|
+
expect(endGlobalLoadSpy).not.toHaveBeenCalled();
|
|
427
|
+
expect(beginGlobalLoadSpy).not.toHaveBeenCalled();
|
|
473
428
|
});
|
|
474
429
|
|
|
475
|
-
it('Doesnt call same extender twice',
|
|
430
|
+
it('Doesnt call same extender twice', async () => {
|
|
476
431
|
const store = createStore(reducers);
|
|
477
432
|
const promiseOrder = [];
|
|
478
|
-
const eat =
|
|
433
|
+
const eat = vi.fn((meal) => {
|
|
479
434
|
promiseOrder.push(meal);
|
|
480
435
|
return `yammi ${meal}`;
|
|
481
436
|
});
|
|
@@ -483,14 +438,15 @@ describe('<ReduxAsyncConnect />', () => {
|
|
|
483
438
|
const helpers = { eat };
|
|
484
439
|
serial = 0;
|
|
485
440
|
|
|
486
|
-
|
|
441
|
+
await loadOnServer({
|
|
487
442
|
store,
|
|
488
443
|
routes,
|
|
489
444
|
location,
|
|
490
445
|
helpers,
|
|
491
|
-
})
|
|
492
|
-
const context = {};
|
|
446
|
+
});
|
|
493
447
|
|
|
448
|
+
const context = {};
|
|
449
|
+
await act(async () => {
|
|
494
450
|
render(
|
|
495
451
|
<Provider store={store} key="provider">
|
|
496
452
|
<StaticRouter location={location} context={context}>
|
|
@@ -498,10 +454,10 @@ describe('<ReduxAsyncConnect />', () => {
|
|
|
498
454
|
</StaticRouter>
|
|
499
455
|
</Provider>,
|
|
500
456
|
);
|
|
501
|
-
expect(serial).toBe(1);
|
|
502
457
|
});
|
|
503
|
-
});
|
|
504
458
|
|
|
459
|
+
expect(serial).toBe(1);
|
|
460
|
+
});
|
|
505
461
|
it('Matches multiple asyncPropExtenders', function () {
|
|
506
462
|
const routes = [
|
|
507
463
|
{
|
|
@@ -1,60 +1,94 @@
|
|
|
1
1
|
import Cookies from 'universal-cookie';
|
|
2
2
|
import jwt from 'jsonwebtoken';
|
|
3
3
|
import jwtDecode from 'jwt-decode';
|
|
4
|
-
|
|
5
4
|
import { getAuthToken, persistAuthToken } from './AuthToken';
|
|
6
5
|
|
|
7
|
-
|
|
6
|
+
vi.mock('universal-cookie', () => {
|
|
8
7
|
const mCookie = {
|
|
9
|
-
get:
|
|
10
|
-
.fn(() =>
|
|
11
|
-
.mockImplementationOnce(() => null),
|
|
12
|
-
remove:
|
|
13
|
-
set:
|
|
8
|
+
get: vi
|
|
9
|
+
.fn(() => jwt.sign({ exp: 1 }, 'secret'))
|
|
10
|
+
.mockImplementationOnce(() => null),
|
|
11
|
+
remove: vi.fn(),
|
|
12
|
+
set: vi.fn(),
|
|
13
|
+
};
|
|
14
|
+
return {
|
|
15
|
+
default: vi.fn(() => mCookie),
|
|
14
16
|
};
|
|
15
|
-
return jest.fn(() => mCookie);
|
|
16
17
|
});
|
|
17
18
|
|
|
18
19
|
describe('AuthToken', () => {
|
|
20
|
+
let cookies;
|
|
21
|
+
let mockStore;
|
|
22
|
+
|
|
23
|
+
beforeEach(() => {
|
|
24
|
+
cookies = new Cookies();
|
|
25
|
+
vi.clearAllMocks();
|
|
26
|
+
|
|
27
|
+
mockStore = {
|
|
28
|
+
subscribe: vi.fn(),
|
|
29
|
+
dispatch: vi.fn(),
|
|
30
|
+
getState: vi.fn(() => ({
|
|
31
|
+
userSession: {
|
|
32
|
+
token: null,
|
|
33
|
+
},
|
|
34
|
+
router: {
|
|
35
|
+
location: {
|
|
36
|
+
pathname: '/current-path',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
})),
|
|
40
|
+
};
|
|
41
|
+
});
|
|
42
|
+
|
|
19
43
|
describe('anonymousAuthToken', () => {
|
|
20
44
|
it('avoid unnecessary removing auth token', () => {
|
|
21
|
-
const cookies = new Cookies();
|
|
22
45
|
const store = {
|
|
23
|
-
|
|
24
|
-
getState:
|
|
46
|
+
...mockStore,
|
|
47
|
+
getState: vi.fn(() => ({
|
|
25
48
|
userSession: {
|
|
26
49
|
token: null,
|
|
27
50
|
},
|
|
51
|
+
router: {
|
|
52
|
+
location: {
|
|
53
|
+
pathname: '/current-path',
|
|
54
|
+
},
|
|
55
|
+
},
|
|
28
56
|
})),
|
|
29
57
|
};
|
|
58
|
+
|
|
30
59
|
persistAuthToken(store);
|
|
31
|
-
expect(cookies.remove).not.
|
|
60
|
+
expect(cookies.remove).not.toHaveBeenCalledWith('auth_token', {
|
|
61
|
+
path: '/',
|
|
62
|
+
});
|
|
32
63
|
});
|
|
33
64
|
});
|
|
34
65
|
|
|
35
66
|
describe('getAuthToken', () => {
|
|
36
67
|
it('can get the auth token', () => {
|
|
37
|
-
const cookies = new Cookies();
|
|
38
68
|
getAuthToken();
|
|
39
|
-
expect(cookies.get).
|
|
69
|
+
expect(cookies.get).toHaveBeenCalledWith('auth_token');
|
|
40
70
|
});
|
|
41
71
|
});
|
|
42
72
|
|
|
43
73
|
describe('persistAuthToken', () => {
|
|
44
74
|
it('can set a new auth token', () => {
|
|
45
|
-
const cookies = new Cookies();
|
|
46
75
|
const store = {
|
|
47
|
-
|
|
48
|
-
getState:
|
|
76
|
+
...mockStore,
|
|
77
|
+
getState: vi.fn(() => ({
|
|
49
78
|
userSession: {
|
|
50
79
|
token: jwt.sign({ exp: 2 }, 'secret'),
|
|
51
80
|
},
|
|
81
|
+
router: {
|
|
82
|
+
location: {
|
|
83
|
+
pathname: '/current-path',
|
|
84
|
+
},
|
|
85
|
+
},
|
|
52
86
|
})),
|
|
53
87
|
};
|
|
54
88
|
const { token } = store.getState().userSession;
|
|
55
89
|
|
|
56
90
|
persistAuthToken(store);
|
|
57
|
-
expect(cookies.set).
|
|
91
|
+
expect(cookies.set).toHaveBeenCalledWith('auth_token', token, {
|
|
58
92
|
path: '/',
|
|
59
93
|
expires: new Date(jwtDecode(token).exp * 1000),
|
|
60
94
|
secure: false,
|
|
@@ -62,18 +96,22 @@ describe('AuthToken', () => {
|
|
|
62
96
|
});
|
|
63
97
|
|
|
64
98
|
it('can remove an auth token', () => {
|
|
65
|
-
const cookies = new Cookies();
|
|
66
99
|
const store = {
|
|
67
|
-
|
|
68
|
-
getState:
|
|
100
|
+
...mockStore,
|
|
101
|
+
getState: vi.fn(() => ({
|
|
69
102
|
userSession: {
|
|
70
103
|
token: null,
|
|
71
104
|
},
|
|
105
|
+
router: {
|
|
106
|
+
location: {
|
|
107
|
+
pathname: '/current-path',
|
|
108
|
+
},
|
|
109
|
+
},
|
|
72
110
|
})),
|
|
73
111
|
};
|
|
74
112
|
|
|
75
113
|
persistAuthToken(store);
|
|
76
|
-
expect(cookies.remove).
|
|
114
|
+
expect(cookies.remove).toHaveBeenCalledWith('auth_token', { path: '/' });
|
|
77
115
|
});
|
|
78
116
|
});
|
|
79
117
|
});
|