navigation-stack 0.5.3 → 0.6.0
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 +16 -0
- package/README.md +144 -282
- package/karma.conf.cjs +1 -1
- package/lib/cjs/NavigationStack.js +138 -49
- package/lib/cjs/data-storage/DataStorage.js +7 -6
- package/lib/cjs/environment/InMemoryEnvironment.js +6 -0
- package/lib/cjs/{session/ServerSideRenderSession.js → environment/ServerSideRenderEnvironment.js} +5 -6
- package/lib/cjs/environment/WebBrowserEnvironment.js +6 -0
- package/lib/cjs/environment/log/InMemoryLog.js +23 -0
- package/lib/cjs/environment/log/WebBrowserLog.js +22 -0
- package/lib/cjs/{session → environment}/navigation/InMemoryNavigation.js +16 -5
- package/lib/cjs/{session → environment}/navigation/ServerSideNavigation.js +16 -7
- package/lib/cjs/{session → environment}/navigation/WebBrowserNavigation.js +48 -8
- package/lib/cjs/{session/navigation/error/ServerSideNavigationError.js → environment/navigation/error/ServerSideRedirectError.js} +2 -2
- package/lib/cjs/environment/scroll-position/WebBrowserScrollPosition.js +15 -0
- package/lib/cjs/getLocationBaseFromLocation.js +14 -0
- package/lib/cjs/getLocationUrl.js +3 -5
- package/lib/cjs/index.js +10 -16
- package/lib/cjs/navigationBlockers.js +34 -32
- package/lib/cjs/navigationBlockersEvaluation.js +150 -0
- package/lib/cjs/parseInputLocation.js +2 -2
- package/lib/cjs/parseQueryFromSearch.js +3 -6
- package/lib/cjs/parseQueryString.js +77 -0
- package/lib/cjs/scroll-position/ScrollPositionAutoSaver.js +7 -6
- package/lib/cjs/scroll-position/ScrollPositionRestoration.js +31 -27
- package/lib/cjs/scroll-position/ScrollPositionSaver.js +6 -4
- package/lib/cjs/session/Session.js +61 -26
- package/lib/cjs/session/subscription/Subscription.js +36 -18
- package/lib/cjs/stringifyQuery.js +66 -0
- package/lib/cjs/stringifyQueryAsSearch.js +14 -0
- package/lib/esm/NavigationStack.js +138 -49
- package/lib/esm/data-storage/DataStorage.js +7 -6
- package/lib/esm/environment/InMemoryEnvironment.js +6 -0
- package/lib/esm/environment/ServerSideRenderEnvironment.js +10 -0
- package/lib/esm/environment/WebBrowserEnvironment.js +6 -0
- package/lib/esm/environment/log/InMemoryLog.js +17 -0
- package/lib/esm/environment/log/WebBrowserLog.js +16 -0
- package/lib/esm/{session → environment}/navigation/InMemoryNavigation.js +16 -5
- package/lib/esm/{session → environment}/navigation/ServerSideNavigation.js +16 -7
- package/lib/esm/{session → environment}/navigation/WebBrowserNavigation.js +48 -8
- package/lib/esm/{session/navigation/error/ServerSideNavigationError.js → environment/navigation/error/ServerSideRedirectError.js} +1 -1
- package/lib/esm/environment/scroll-position/WebBrowserScrollPosition.js +15 -0
- package/lib/esm/getLocationBaseFromLocation.js +9 -0
- package/lib/esm/getLocationUrl.js +2 -5
- package/lib/esm/index.js +5 -8
- package/lib/esm/navigationBlockers.js +34 -32
- package/lib/esm/navigationBlockersEvaluation.js +145 -0
- package/lib/esm/parseInputLocation.js +2 -2
- package/lib/esm/parseQueryFromSearch.js +2 -6
- package/lib/esm/parseQueryString.js +72 -0
- package/lib/esm/scroll-position/ScrollPositionAutoSaver.js +7 -6
- package/lib/esm/scroll-position/ScrollPositionRestoration.js +31 -27
- package/lib/esm/scroll-position/ScrollPositionSaver.js +6 -4
- package/lib/esm/session/Session.js +61 -26
- package/lib/esm/session/subscription/Subscription.js +36 -18
- package/lib/esm/stringifyQuery.js +61 -0
- package/lib/esm/stringifyQueryAsSearch.js +8 -0
- package/lib/index.d.ts +180 -34
- package/package.json +4 -7
- package/src/NavigationStack.js +166 -56
- package/src/data-storage/DataStorage.js +9 -6
- package/src/environment/InMemoryEnvironment.js +6 -0
- package/src/environment/ServerSideRenderEnvironment.js +10 -0
- package/src/environment/WebBrowserEnvironment.js +6 -0
- package/src/environment/log/InMemoryLog.js +20 -0
- package/src/environment/log/WebBrowserLog.js +18 -0
- package/src/{session → environment}/navigation/InMemoryNavigation.js +16 -5
- package/src/{session → environment}/navigation/ServerSideNavigation.js +16 -7
- package/src/{session → environment}/navigation/WebBrowserNavigation.js +48 -8
- package/src/{session/navigation/error/ServerSideNavigationError.js → environment/navigation/error/ServerSideRedirectError.js} +1 -1
- package/src/environment/scroll-position/WebBrowserScrollPosition.js +15 -0
- package/src/getLocationBaseFromLocation.js +7 -0
- package/src/getLocationUrl.js +2 -5
- package/src/index.js +10 -13
- package/src/navigationBlockers.js +55 -34
- package/src/navigationBlockersEvaluation.js +161 -0
- package/src/parseInputLocation.js +2 -2
- package/src/parseQueryFromSearch.js +2 -6
- package/src/parseQueryString.js +81 -0
- package/src/scroll-position/ScrollPositionAutoSaver.js +10 -6
- package/src/scroll-position/ScrollPositionRestoration.js +36 -30
- package/src/scroll-position/ScrollPositionSaver.js +6 -4
- package/src/scroll-position/index.js +1 -1
- package/src/session/Session.js +68 -24
- package/src/session/subscription/Subscription.js +36 -11
- package/src/stringifyQuery.js +71 -0
- package/src/stringifyQueryAsSearch.js +9 -0
- package/test/NavigationStack.addBasePath.test.js +50 -0
- package/test/{redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.test.js → NavigationStack.blockNonProgrammaticNavigationIfRequired.test.js} +51 -63
- package/test/{redux/middleware/createProgrammaticNavigationBlockerMiddleware.test.js → NavigationStack.blockProgrammaticNavigationIfRequired.test.js} +98 -78
- package/test/NavigationStack.general.test.js +68 -0
- package/test/NavigationStack.parseInputLocation.test.js +52 -0
- package/test/NavigationStack.removeBasePath.test.js +69 -0
- package/test/NavigationStack.test.js +97 -29
- package/test/data-storage/LocationDataStorage.test.js +3 -2
- package/test/index.js +7 -31
- package/test/index.test.js +4 -5
- package/test/parseQueryFromSearch.test.js +19 -0
- package/test/parseQueryString.test.js +18 -0
- package/test/scroll-position/ScrollPositionRestoration.test.js +34 -13
- package/test/scroll-position/createApp.js +8 -8
- package/test/scroll-position/withScrollableContainerAtIndexPageWithDisabledAutomaticScrollPositionRestoration.js +4 -4
- package/test/session/{InMemorySession.test.js → Session.InMemoryEnvironment.test.js} +10 -9
- package/test/session/{ServerSession.test.js → Session.ServerSideRenderEnvironment.test.js} +5 -4
- package/test/session/{WebBrowserSession.test.js → Session.WebBrowserEnvironment.test.js} +63 -13
- package/test/shouldWarn.js +44 -0
- package/test/stringifyQuery.test.js +65 -0
- package/types/index.d.ts +180 -34
- package/types/tsconfig.json +0 -1
- package/data-storage/package.json +0 -7
- package/lib/cjs/createSearchFromQuery.js +0 -13
- package/lib/cjs/debug.js +0 -12
- package/lib/cjs/redux/ActionTypes.js +0 -14
- package/lib/cjs/redux/ActionTypesInternal.js +0 -8
- package/lib/cjs/redux/Actions.js +0 -28
- package/lib/cjs/redux/createMiddlewares.js +0 -60
- package/lib/cjs/redux/index.js +0 -13
- package/lib/cjs/redux/internalLocationReducer.js +0 -14
- package/lib/cjs/redux/locationReducer.js +0 -13
- package/lib/cjs/redux/middleware/createAddInputLocationBasePathMiddleware.js +0 -32
- package/lib/cjs/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.js +0 -113
- package/lib/cjs/redux/middleware/createProgrammaticNavigationBlockerMiddleware.js +0 -94
- package/lib/cjs/redux/middleware/createRemoveOutputLocationBasePathMiddleware.js +0 -30
- package/lib/cjs/redux/middleware/createUpdateInternalLocationMiddleware.js +0 -73
- package/lib/cjs/redux/middleware/navigationOperationMiddleware.js +0 -40
- package/lib/cjs/redux/middleware/parseInputLocationMiddleware.js +0 -29
- package/lib/cjs/redux/middleware/updateLocationMiddleware.js +0 -34
- package/lib/cjs/session/InMemorySession.js +0 -22
- package/lib/cjs/session/WebBrowserSession.js +0 -20
- package/lib/data-storage/index.d.ts +0 -35
- package/lib/esm/createSearchFromQuery.js +0 -8
- package/lib/esm/debug.js +0 -7
- package/lib/esm/redux/ActionTypes.js +0 -9
- package/lib/esm/redux/ActionTypesInternal.js +0 -3
- package/lib/esm/redux/Actions.js +0 -22
- package/lib/esm/redux/createMiddlewares.js +0 -54
- package/lib/esm/redux/index.js +0 -4
- package/lib/esm/redux/internalLocationReducer.js +0 -8
- package/lib/esm/redux/locationReducer.js +0 -7
- package/lib/esm/redux/middleware/createAddInputLocationBasePathMiddleware.js +0 -27
- package/lib/esm/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.js +0 -108
- package/lib/esm/redux/middleware/createProgrammaticNavigationBlockerMiddleware.js +0 -88
- package/lib/esm/redux/middleware/createRemoveOutputLocationBasePathMiddleware.js +0 -25
- package/lib/esm/redux/middleware/createUpdateInternalLocationMiddleware.js +0 -68
- package/lib/esm/redux/middleware/navigationOperationMiddleware.js +0 -35
- package/lib/esm/redux/middleware/parseInputLocationMiddleware.js +0 -24
- package/lib/esm/redux/middleware/updateLocationMiddleware.js +0 -28
- package/lib/esm/session/InMemorySession.js +0 -15
- package/lib/esm/session/ServerSideRenderSession.js +0 -11
- package/lib/esm/session/WebBrowserSession.js +0 -13
- package/lib/redux/index.d.ts +0 -90
- package/lib/scroll-position/index.d.ts +0 -107
- package/redux/package.json +0 -7
- package/scroll-position/package.json +0 -7
- package/src/createSearchFromQuery.js +0 -9
- package/src/debug.js +0 -8
- package/src/redux/ActionTypes.js +0 -9
- package/src/redux/ActionTypesInternal.js +0 -3
- package/src/redux/Actions.js +0 -27
- package/src/redux/createMiddlewares.js +0 -65
- package/src/redux/index.js +0 -4
- package/src/redux/internalLocationReducer.js +0 -9
- package/src/redux/locationReducer.js +0 -8
- package/src/redux/middleware/createAddInputLocationBasePathMiddleware.js +0 -27
- package/src/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.js +0 -119
- package/src/redux/middleware/createProgrammaticNavigationBlockerMiddleware.js +0 -94
- package/src/redux/middleware/createRemoveOutputLocationBasePathMiddleware.js +0 -26
- package/src/redux/middleware/createUpdateInternalLocationMiddleware.js +0 -72
- package/src/redux/middleware/navigationOperationMiddleware.js +0 -34
- package/src/redux/middleware/parseInputLocationMiddleware.js +0 -23
- package/src/redux/middleware/updateLocationMiddleware.js +0 -28
- package/src/session/InMemorySession.js +0 -13
- package/src/session/ServerSideRenderSession.js +0 -9
- package/src/session/WebBrowserSession.js +0 -13
- package/test/middlewareTestUtil.js +0 -31
- package/test/redux/Action.test.js +0 -73
- package/test/redux/ActionTypes.test.js +0 -13
- package/test/redux/createMiddlewares.test.js +0 -96
- package/test/redux/index.test.js +0 -10
- package/test/redux/locationReducer.test.js +0 -39
- package/test/redux/middleware/createAddInputLocationBasePathMiddleware.test.js +0 -40
- package/test/redux/middleware/createRemoveOutputLocationBasePathMiddleware.test.js +0 -51
- package/test/redux/middleware/navigationOperationMiddleware.test.js +0 -78
- package/test/redux/middleware/parseInputLocationMiddleware.test.js +0 -62
- package/test/testUtil.js +0 -3
- package/types/data-storage/index.d.ts +0 -35
- package/types/redux/index.d.ts +0 -90
- package/types/scroll-position/index.d.ts +0 -107
- /package/lib/cjs/{session → environment}/lifecycle/InMemorySessionLifecycle.js +0 -0
- /package/lib/cjs/{session → environment}/lifecycle/WebBrowserSessionLifecycle.js +0 -0
- /package/lib/cjs/{session → environment}/lifecycle/page-lifecycle/PageLifecycle.js +0 -0
- /package/lib/cjs/{session → environment}/lifecycle/page-lifecycle/PageLifecycleInstance.js +0 -0
- /package/lib/cjs/{session → environment}/lifecycle/page-lifecycle/supportsConstructableEventTarget.js +0 -0
- /package/lib/cjs/{session → environment}/navigation/error/NavigationOutOfBoundsError.js +0 -0
- /package/lib/cjs/{session → environment}/navigation/operation/operations.js +0 -0
- /package/lib/esm/{session → environment}/lifecycle/InMemorySessionLifecycle.js +0 -0
- /package/lib/esm/{session → environment}/lifecycle/WebBrowserSessionLifecycle.js +0 -0
- /package/lib/esm/{session → environment}/lifecycle/page-lifecycle/PageLifecycle.js +0 -0
- /package/lib/esm/{session → environment}/lifecycle/page-lifecycle/PageLifecycleInstance.js +0 -0
- /package/lib/esm/{session → environment}/lifecycle/page-lifecycle/supportsConstructableEventTarget.js +0 -0
- /package/lib/esm/{session → environment}/navigation/error/NavigationOutOfBoundsError.js +0 -0
- /package/lib/esm/{session → environment}/navigation/operation/operations.js +0 -0
- /package/src/{session → environment}/lifecycle/InMemorySessionLifecycle.js +0 -0
- /package/src/{session → environment}/lifecycle/WebBrowserSessionLifecycle.js +0 -0
- /package/src/{session → environment}/lifecycle/page-lifecycle/PageLifecycle.js +0 -0
- /package/src/{session → environment}/lifecycle/page-lifecycle/PageLifecycleInstance.js +0 -0
- /package/src/{session → environment}/lifecycle/page-lifecycle/supportsConstructableEventTarget.js +0 -0
- /package/src/{session → environment}/navigation/error/NavigationOutOfBoundsError.js +0 -0
- /package/src/{session → environment}/navigation/operation/operations.js +0 -0
- /package/test/{parseInputLocationMiddleware.test.js → parseInputLocation.test.js} +0 -0
|
@@ -1,42 +1,34 @@
|
|
|
1
1
|
import delay from 'delay';
|
|
2
2
|
import pDefer from 'p-defer';
|
|
3
|
-
import { applyMiddleware, createStore } from 'redux';
|
|
4
3
|
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import InMemorySession from '../../../src/session/InMemorySession';
|
|
10
|
-
import { shouldWarn } from '../../testUtil';
|
|
4
|
+
import shouldWarn from './shouldWarn';
|
|
5
|
+
import NavigationStack from '../src/NavigationStack';
|
|
6
|
+
import addNavigationBlockerOriginal from '../src/addNavigationBlocker';
|
|
7
|
+
import InMemoryEnvironment from '../src/environment/InMemoryEnvironment';
|
|
11
8
|
|
|
12
|
-
describe('
|
|
9
|
+
describe('NavigationStack (blockProgrammaticNavigationIfRequired)', () => {
|
|
13
10
|
// const sandbox = sinon.createSandbox();
|
|
14
11
|
|
|
15
12
|
let session;
|
|
16
|
-
let
|
|
13
|
+
let navigationStack;
|
|
17
14
|
|
|
18
15
|
function addNavigationBlocker(blocker) {
|
|
19
16
|
return addNavigationBlockerOriginal(session, blocker);
|
|
20
17
|
}
|
|
21
18
|
|
|
22
19
|
beforeEach(() => {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
),
|
|
32
|
-
);
|
|
33
|
-
store.dispatch(Actions.init('/initial'));
|
|
34
|
-
|
|
35
|
-
sinon.spy(session.lifecycle, 'addTerminationBlocker');
|
|
20
|
+
navigationStack = new NavigationStack(InMemoryEnvironment);
|
|
21
|
+
|
|
22
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
23
|
+
session = navigationStack._session;
|
|
24
|
+
|
|
25
|
+
navigationStack.init('/initial');
|
|
26
|
+
|
|
27
|
+
sinon.spy(session.environment.lifecycle, 'addTerminationBlocker');
|
|
36
28
|
});
|
|
37
29
|
|
|
38
30
|
afterEach(() => {
|
|
39
|
-
|
|
31
|
+
navigationStack.stop();
|
|
40
32
|
|
|
41
33
|
// sandbox.restore();
|
|
42
34
|
});
|
|
@@ -46,8 +38,8 @@ describe('createProgrammaticNavigationBlockerMiddleware', () => {
|
|
|
46
38
|
const blocker = sinon.stub().returns(true);
|
|
47
39
|
addNavigationBlocker(blocker);
|
|
48
40
|
|
|
49
|
-
|
|
50
|
-
expect(
|
|
41
|
+
navigationStack.push('/new');
|
|
42
|
+
expect(navigationStack.current().pathname).to.equal('/initial');
|
|
51
43
|
|
|
52
44
|
expect(blocker).to.have.been.calledOnce();
|
|
53
45
|
|
|
@@ -60,8 +52,8 @@ describe('createProgrammaticNavigationBlockerMiddleware', () => {
|
|
|
60
52
|
it('should allow navigation when blocker returns `undefined`', () => {
|
|
61
53
|
addNavigationBlocker(() => undefined);
|
|
62
54
|
|
|
63
|
-
|
|
64
|
-
expect(
|
|
55
|
+
navigationStack.push('/new');
|
|
56
|
+
expect(navigationStack.current().pathname).to.equal('/new');
|
|
65
57
|
});
|
|
66
58
|
|
|
67
59
|
it("should fall through when first blocker doesn't return `true`", () => {
|
|
@@ -71,8 +63,8 @@ describe('createProgrammaticNavigationBlockerMiddleware', () => {
|
|
|
71
63
|
addNavigationBlocker(blocker1);
|
|
72
64
|
addNavigationBlocker(blocker2);
|
|
73
65
|
|
|
74
|
-
|
|
75
|
-
expect(
|
|
66
|
+
navigationStack.push('/new');
|
|
67
|
+
expect(navigationStack.current().pathname).to.equal('/initial');
|
|
76
68
|
|
|
77
69
|
expect(blocker1).to.have.been.calledOnce();
|
|
78
70
|
expect(blocker2).to.have.been.calledOnce();
|
|
@@ -85,8 +77,8 @@ describe('createProgrammaticNavigationBlockerMiddleware', () => {
|
|
|
85
77
|
addNavigationBlocker(blocker1);
|
|
86
78
|
addNavigationBlocker(blocker2);
|
|
87
79
|
|
|
88
|
-
|
|
89
|
-
expect(
|
|
80
|
+
navigationStack.push('/new');
|
|
81
|
+
expect(navigationStack.current().pathname).to.equal('/initial');
|
|
90
82
|
|
|
91
83
|
expect(blocker1).to.have.been.calledOnce();
|
|
92
84
|
expect(blocker2).not.to.have.been.called();
|
|
@@ -103,8 +95,8 @@ describe('createProgrammaticNavigationBlockerMiddleware', () => {
|
|
|
103
95
|
|
|
104
96
|
addNavigationBlocker(syncBlocker);
|
|
105
97
|
|
|
106
|
-
|
|
107
|
-
expect(
|
|
98
|
+
navigationStack.push('/new');
|
|
99
|
+
expect(navigationStack.current().pathname).to.equal('/new');
|
|
108
100
|
});
|
|
109
101
|
|
|
110
102
|
// it('should show a confirmation dialog and allow navigation on string', () => {
|
|
@@ -112,8 +104,8 @@ describe('createProgrammaticNavigationBlockerMiddleware', () => {
|
|
|
112
104
|
//
|
|
113
105
|
// addNavigationBlocker(({ pathname }) => pathname);
|
|
114
106
|
//
|
|
115
|
-
//
|
|
116
|
-
// expect(
|
|
107
|
+
// navigationStack.push('/new'));
|
|
108
|
+
// expect(navigationStack.current().pathname).to.equal('/new');
|
|
117
109
|
//
|
|
118
110
|
// expect(window.confirm)
|
|
119
111
|
// .to.have.been.calledOnce()
|
|
@@ -125,8 +117,8 @@ describe('createProgrammaticNavigationBlockerMiddleware', () => {
|
|
|
125
117
|
//
|
|
126
118
|
// addNavigationBlocker(({ pathname }) => pathname);
|
|
127
119
|
//
|
|
128
|
-
//
|
|
129
|
-
// expect(
|
|
120
|
+
// navigationStack.push('/new'));
|
|
121
|
+
// expect(navigationStack.current().pathname).to.equal('/initial');
|
|
130
122
|
//
|
|
131
123
|
// expect(window.confirm)
|
|
132
124
|
// .to.have.been.calledOnce()
|
|
@@ -137,26 +129,26 @@ describe('createProgrammaticNavigationBlockerMiddleware', () => {
|
|
|
137
129
|
const navigationBlockerDeferred = pDefer();
|
|
138
130
|
addNavigationBlocker(() => navigationBlockerDeferred.promise);
|
|
139
131
|
|
|
140
|
-
|
|
141
|
-
expect(
|
|
132
|
+
navigationStack.push('/new');
|
|
133
|
+
expect(navigationStack.current().pathname).to.equal('/initial');
|
|
142
134
|
|
|
143
135
|
navigationBlockerDeferred.resolve(undefined);
|
|
144
136
|
await delay(10);
|
|
145
137
|
|
|
146
|
-
expect(
|
|
138
|
+
expect(navigationStack.current().pathname).to.equal('/new');
|
|
147
139
|
});
|
|
148
140
|
|
|
149
141
|
it('should block navigation when blocker returns `true` (async)', async () => {
|
|
150
142
|
const navigationBlockerDeferred = pDefer();
|
|
151
143
|
addNavigationBlocker(() => navigationBlockerDeferred.promise);
|
|
152
144
|
|
|
153
|
-
|
|
154
|
-
expect(
|
|
145
|
+
navigationStack.push('/new');
|
|
146
|
+
expect(navigationStack.current().pathname).to.equal('/initial');
|
|
155
147
|
|
|
156
148
|
navigationBlockerDeferred.resolve(true);
|
|
157
149
|
await delay(10);
|
|
158
150
|
|
|
159
|
-
expect(
|
|
151
|
+
expect(navigationStack.current().pathname).to.equal('/initial');
|
|
160
152
|
});
|
|
161
153
|
|
|
162
154
|
it('should allow chaining async blockers', async () => {
|
|
@@ -166,18 +158,18 @@ describe('createProgrammaticNavigationBlockerMiddleware', () => {
|
|
|
166
158
|
addNavigationBlocker(() => navigationBlockerDeferred1.promise);
|
|
167
159
|
addNavigationBlocker(() => navigationBlockerDeferred2.promise);
|
|
168
160
|
|
|
169
|
-
|
|
170
|
-
expect(
|
|
161
|
+
navigationStack.push('/new');
|
|
162
|
+
expect(navigationStack.current().pathname).to.equal('/initial');
|
|
171
163
|
|
|
172
164
|
navigationBlockerDeferred1.resolve(undefined);
|
|
173
165
|
await delay(10);
|
|
174
166
|
|
|
175
|
-
expect(
|
|
167
|
+
expect(navigationStack.current().pathname).to.equal('/initial');
|
|
176
168
|
|
|
177
169
|
navigationBlockerDeferred2.resolve(undefined);
|
|
178
170
|
await delay(10);
|
|
179
171
|
|
|
180
|
-
expect(
|
|
172
|
+
expect(navigationStack.current().pathname).to.equal('/new');
|
|
181
173
|
});
|
|
182
174
|
|
|
183
175
|
it('should warn on and ignore async blockers that throw an error', async () => {
|
|
@@ -192,24 +184,24 @@ describe('createProgrammaticNavigationBlockerMiddleware', () => {
|
|
|
192
184
|
|
|
193
185
|
addNavigationBlocker(asyncBlocker);
|
|
194
186
|
|
|
195
|
-
|
|
196
|
-
expect(
|
|
187
|
+
navigationStack.push('/new');
|
|
188
|
+
expect(navigationStack.current().pathname).to.equal('/initial');
|
|
197
189
|
|
|
198
190
|
await delay(10);
|
|
199
191
|
|
|
200
|
-
expect(
|
|
192
|
+
expect(navigationStack.current().pathname).to.equal('/new');
|
|
201
193
|
});
|
|
202
194
|
|
|
203
195
|
it('should allow removing blockers', () => {
|
|
204
196
|
const removeNavigationBlocker = addNavigationBlocker(() => true);
|
|
205
197
|
|
|
206
|
-
|
|
207
|
-
expect(
|
|
198
|
+
navigationStack.push('/new');
|
|
199
|
+
expect(navigationStack.current().pathname).to.equal('/initial');
|
|
208
200
|
|
|
209
201
|
removeNavigationBlocker();
|
|
210
202
|
|
|
211
|
-
|
|
212
|
-
expect(
|
|
203
|
+
navigationStack.push('/new');
|
|
204
|
+
expect(navigationStack.current().pathname).to.equal('/new');
|
|
213
205
|
});
|
|
214
206
|
});
|
|
215
207
|
});
|
|
@@ -218,43 +210,46 @@ describe('addTerminationBlocker', () => {
|
|
|
218
210
|
// const sandbox = sinon.createSandbox();
|
|
219
211
|
|
|
220
212
|
let session;
|
|
221
|
-
let
|
|
213
|
+
let navigationStack;
|
|
222
214
|
|
|
223
215
|
function addNavigationBlocker(blocker) {
|
|
224
216
|
return addNavigationBlockerOriginal(session, blocker);
|
|
225
217
|
}
|
|
226
218
|
|
|
227
219
|
beforeEach(() => {
|
|
228
|
-
|
|
220
|
+
navigationStack = new NavigationStack(InMemoryEnvironment);
|
|
221
|
+
|
|
222
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
223
|
+
session = navigationStack._session;
|
|
229
224
|
|
|
230
|
-
|
|
231
|
-
internalLocationReducer,
|
|
232
|
-
applyMiddleware(...createMiddlewares(session)),
|
|
233
|
-
);
|
|
234
|
-
store.dispatch(Actions.init('/initial'));
|
|
225
|
+
navigationStack.init('/initial');
|
|
235
226
|
|
|
236
|
-
sinon.spy(session.lifecycle, 'addTerminationBlocker');
|
|
227
|
+
sinon.spy(session.environment.lifecycle, 'addTerminationBlocker');
|
|
237
228
|
|
|
238
229
|
// sandbox.stub(window, 'addEventListener');
|
|
239
230
|
// sandbox.stub(window, 'removeEventListener');
|
|
240
231
|
});
|
|
241
232
|
|
|
242
233
|
afterEach(() => {
|
|
243
|
-
if (
|
|
244
|
-
|
|
234
|
+
if (navigationStack) {
|
|
235
|
+
navigationStack.stop();
|
|
245
236
|
}
|
|
246
237
|
|
|
247
238
|
// sandbox.restore();
|
|
248
239
|
});
|
|
249
240
|
|
|
250
241
|
it('should add/remove event blocker', () => {
|
|
251
|
-
expect(
|
|
242
|
+
expect(
|
|
243
|
+
session.environment.lifecycle.addTerminationBlocker,
|
|
244
|
+
).not.to.have.been.called();
|
|
252
245
|
// expect(window.addEventListener).not.to.have.been.called();
|
|
253
246
|
|
|
254
247
|
const removeNavigationBlocker1 = addNavigationBlocker(() => null, {
|
|
255
248
|
beforeUnload: true,
|
|
256
249
|
});
|
|
257
|
-
expect(
|
|
250
|
+
expect(
|
|
251
|
+
session.environment.lifecycle.addTerminationBlocker,
|
|
252
|
+
).to.have.been.calledOnce();
|
|
258
253
|
// expect(window.addEventListener)
|
|
259
254
|
// .to.have.been.calledOnce()
|
|
260
255
|
// .and.to.have.been.called.with('beforeunload');
|
|
@@ -262,7 +257,9 @@ describe('addTerminationBlocker', () => {
|
|
|
262
257
|
const removeNavigationBlocker2 = addNavigationBlocker(() => null, {
|
|
263
258
|
beforeUnload: true,
|
|
264
259
|
});
|
|
265
|
-
expect(
|
|
260
|
+
expect(
|
|
261
|
+
session.environment.lifecycle.addTerminationBlocker,
|
|
262
|
+
).to.have.been.calledOnce();
|
|
266
263
|
// expect(window.addEventListener)
|
|
267
264
|
// .to.have.been.calledOnce()
|
|
268
265
|
// .and.to.have.been.called.with('beforeunload');
|
|
@@ -282,6 +279,39 @@ describe('addTerminationBlocker', () => {
|
|
|
282
279
|
expect(removeTerminationBlocker).to.have.been.calledOnce();
|
|
283
280
|
});
|
|
284
281
|
|
|
282
|
+
// it('should not add a global "before destroy" listener when no `beforeTermination` blocker has been added', () => {
|
|
283
|
+
// const removeNavigationBlocker = addNavigationBlocker(() => null);
|
|
284
|
+
// expect(window.addEventListener).not.to.have.been.called();
|
|
285
|
+
//
|
|
286
|
+
// removeNavigationBlocker();
|
|
287
|
+
// expect(window.removeEventListener).not.to.have.been.called();
|
|
288
|
+
// });
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
describe('NavigationStack (blockProgrammaticNavigationIfRequired) (stop)', () => {
|
|
292
|
+
let session;
|
|
293
|
+
let navigationStack;
|
|
294
|
+
|
|
295
|
+
function addNavigationBlocker(blocker) {
|
|
296
|
+
return addNavigationBlockerOriginal(session, blocker);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
beforeEach(() => {
|
|
300
|
+
navigationStack = new NavigationStack(InMemoryEnvironment);
|
|
301
|
+
|
|
302
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
303
|
+
session = navigationStack._session;
|
|
304
|
+
|
|
305
|
+
navigationStack.init('/initial');
|
|
306
|
+
|
|
307
|
+
sinon.spy(session.environment.lifecycle, 'addTerminationBlocker');
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
afterEach(() => {
|
|
311
|
+
// Don't call `navigationStack.stop()` here because it was already stopped in the test case.
|
|
312
|
+
// navigationStack.stop();
|
|
313
|
+
});
|
|
314
|
+
|
|
285
315
|
it('should remove event blocker on stop', () => {
|
|
286
316
|
addNavigationBlocker(() => null);
|
|
287
317
|
|
|
@@ -292,21 +322,11 @@ describe('addTerminationBlocker', () => {
|
|
|
292
322
|
// expect(window.removeEventListener).not.to.have.been.called();
|
|
293
323
|
expect(removeTerminationBlocker).not.to.have.been.called();
|
|
294
324
|
|
|
295
|
-
|
|
296
|
-
// Prevent `store.dispatch(Actions.stop())` in `afterEach()`.
|
|
297
|
-
store = undefined;
|
|
325
|
+
navigationStack.stop();
|
|
298
326
|
|
|
299
327
|
// expect(window.removeEventListener)
|
|
300
328
|
// .to.have.been.calledOnce()
|
|
301
329
|
// .and.to.have.been.called.with('beforeunload');
|
|
302
330
|
expect(removeTerminationBlocker).to.have.been.calledOnce();
|
|
303
331
|
});
|
|
304
|
-
|
|
305
|
-
// it('should not add a global "before destroy" listener when no `beforeTermination` blocker has been added', () => {
|
|
306
|
-
// const removeNavigationBlocker = addNavigationBlocker(() => null);
|
|
307
|
-
// expect(window.addEventListener).not.to.have.been.called();
|
|
308
|
-
//
|
|
309
|
-
// removeNavigationBlocker();
|
|
310
|
-
// expect(window.removeEventListener).not.to.have.been.called();
|
|
311
|
-
// });
|
|
312
332
|
});
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import NavigationStack from '../src/NavigationStack';
|
|
2
|
+
import InMemoryEnvironment from '../src/environment/InMemoryEnvironment';
|
|
3
|
+
|
|
4
|
+
describe('NavigationStack (general)', () => {
|
|
5
|
+
let navigationStack;
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
navigationStack = new NavigationStack(InMemoryEnvironment);
|
|
9
|
+
navigationStack.init('/initial');
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
afterEach(() => {
|
|
13
|
+
navigationStack.stop();
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
it('should support `push` and `shift` navigation actions', () => {
|
|
17
|
+
navigationStack.push('/new');
|
|
18
|
+
expect(navigationStack.current()).to.include({
|
|
19
|
+
pathname: '/new',
|
|
20
|
+
index: 1,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
navigationStack.shift(-1);
|
|
24
|
+
expect(navigationStack.current()).to.include({
|
|
25
|
+
pathname: '/initial',
|
|
26
|
+
index: 0,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
navigationStack.shift(+1);
|
|
30
|
+
expect(navigationStack.current()).to.include({
|
|
31
|
+
pathname: '/new',
|
|
32
|
+
index: 1,
|
|
33
|
+
});
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should support `replace` navigation action', () => {
|
|
37
|
+
navigationStack.replace('/new');
|
|
38
|
+
expect(navigationStack.current()).to.include({
|
|
39
|
+
pathname: '/new',
|
|
40
|
+
index: 0,
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe('NavigationStack (basePath)', () => {
|
|
46
|
+
it('should support `basePath` option', () => {
|
|
47
|
+
const navigationStack = new NavigationStack(InMemoryEnvironment, {
|
|
48
|
+
basePath: '/base',
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
52
|
+
const session = navigationStack._session;
|
|
53
|
+
|
|
54
|
+
navigationStack.init('/initial');
|
|
55
|
+
|
|
56
|
+
navigationStack.push('/new');
|
|
57
|
+
|
|
58
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
59
|
+
expect(session._subscription._latest.pathname).to.equal('/base/new');
|
|
60
|
+
|
|
61
|
+
expect(navigationStack.current()).to.include({
|
|
62
|
+
pathname: '/new',
|
|
63
|
+
index: 1,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
navigationStack.stop();
|
|
67
|
+
});
|
|
68
|
+
});
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import NavigationStack from '../src/NavigationStack';
|
|
2
|
+
import InMemoryEnvironment from '../src/environment/InMemoryEnvironment';
|
|
3
|
+
|
|
4
|
+
describe('NavigationStack (parseInputLocation)', () => {
|
|
5
|
+
let navigationStack;
|
|
6
|
+
|
|
7
|
+
beforeEach(() => {
|
|
8
|
+
navigationStack = new NavigationStack(InMemoryEnvironment);
|
|
9
|
+
|
|
10
|
+
// should transform input location of `.init()` method (`string` to `object`)
|
|
11
|
+
navigationStack.init('/foo?bar=baz#qux');
|
|
12
|
+
|
|
13
|
+
expect(navigationStack.current()).to.deep.include({
|
|
14
|
+
pathname: '/foo',
|
|
15
|
+
search: '?bar=baz',
|
|
16
|
+
query: {
|
|
17
|
+
bar: 'baz',
|
|
18
|
+
},
|
|
19
|
+
hash: '#qux',
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
afterEach(() => {
|
|
24
|
+
navigationStack.stop();
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('should transform input location of `.push()` method (`string` to `object`)', () => {
|
|
28
|
+
navigationStack.push('/foo?bar=baz#qux');
|
|
29
|
+
|
|
30
|
+
expect(navigationStack.current()).to.deep.include({
|
|
31
|
+
pathname: '/foo',
|
|
32
|
+
search: '?bar=baz',
|
|
33
|
+
query: {
|
|
34
|
+
bar: 'baz',
|
|
35
|
+
},
|
|
36
|
+
hash: '#qux',
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('should transform input location of `.replace()` method (`string` to `object`)', () => {
|
|
41
|
+
navigationStack.replace('/foo?bar=baz#qux');
|
|
42
|
+
|
|
43
|
+
expect(navigationStack.current()).to.deep.include({
|
|
44
|
+
pathname: '/foo',
|
|
45
|
+
search: '?bar=baz',
|
|
46
|
+
query: {
|
|
47
|
+
bar: 'baz',
|
|
48
|
+
},
|
|
49
|
+
hash: '#qux',
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
});
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import NavigationStack from '../src/NavigationStack';
|
|
2
|
+
import InMemoryEnvironment from '../src/environment/InMemoryEnvironment';
|
|
3
|
+
import parseInputLocation from '../src/parseInputLocation';
|
|
4
|
+
|
|
5
|
+
describe('NavigationStack (removeBasePath)', () => {
|
|
6
|
+
it('should strip `basePath` from `location.pathname`', () => {
|
|
7
|
+
const navigationStack = new NavigationStack(InMemoryEnvironment, {
|
|
8
|
+
basePath: '/base',
|
|
9
|
+
});
|
|
10
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
11
|
+
const session = navigationStack._session;
|
|
12
|
+
session.start(parseInputLocation('/base/path'));
|
|
13
|
+
expect(navigationStack.current().pathname).to.equal('/path');
|
|
14
|
+
navigationStack.stop();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('should strip `basePath` (with a trailing slash) from `location.pathname`', () => {
|
|
18
|
+
const navigationStack = new NavigationStack(InMemoryEnvironment, {
|
|
19
|
+
basePath: '/base/',
|
|
20
|
+
});
|
|
21
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
22
|
+
const session = navigationStack._session;
|
|
23
|
+
session.start(parseInputLocation('/base/path'));
|
|
24
|
+
expect(navigationStack.current().pathname).to.equal('/path');
|
|
25
|
+
navigationStack.stop();
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
it('should not strip `basePath` from `location.pathname` when it does not contain the `basePath`', () => {
|
|
29
|
+
const navigationStack = new NavigationStack(InMemoryEnvironment, {
|
|
30
|
+
basePath: '/base',
|
|
31
|
+
});
|
|
32
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
33
|
+
const session = navigationStack._session;
|
|
34
|
+
session.start(parseInputLocation('/path'));
|
|
35
|
+
expect(navigationStack.current().pathname).to.equal('/path');
|
|
36
|
+
navigationStack.stop();
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('should not strip `basePath` (with a trailing slash) from `location.pathname` when it does not contain the `basePath`', () => {
|
|
40
|
+
const navigationStack = new NavigationStack(InMemoryEnvironment, {
|
|
41
|
+
basePath: '/base/',
|
|
42
|
+
});
|
|
43
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
44
|
+
const session = navigationStack._session;
|
|
45
|
+
session.start(parseInputLocation('/path'));
|
|
46
|
+
expect(navigationStack.current().pathname).to.equal('/path');
|
|
47
|
+
navigationStack.stop();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should not modify `location.pathname` when no `basePath` was specified', () => {
|
|
51
|
+
const navigationStack = new NavigationStack(InMemoryEnvironment);
|
|
52
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
53
|
+
const session = navigationStack._session;
|
|
54
|
+
session.start(parseInputLocation('/path'));
|
|
55
|
+
expect(navigationStack.current().pathname).to.equal('/path');
|
|
56
|
+
navigationStack.stop();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('should not modify `location.pathname` when `basePath: "/"` was specified', () => {
|
|
60
|
+
const navigationStack = new NavigationStack(InMemoryEnvironment, {
|
|
61
|
+
basePath: '/',
|
|
62
|
+
});
|
|
63
|
+
// eslint-disable-next-line no-underscore-dangle
|
|
64
|
+
const session = navigationStack._session;
|
|
65
|
+
session.start(parseInputLocation('/path'));
|
|
66
|
+
expect(navigationStack.current().pathname).to.equal('/path');
|
|
67
|
+
navigationStack.stop();
|
|
68
|
+
});
|
|
69
|
+
});
|