navigation-stack 0.4.0 → 0.5.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.
Files changed (49) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +20 -12
  3. package/lib/cjs/NavigationStack.js +17 -2
  4. package/lib/cjs/debug.js +12 -0
  5. package/lib/cjs/getLocationFromInternalLocation.js +2 -2
  6. package/lib/cjs/navigationBlockers.js +3 -0
  7. package/lib/cjs/scroll-position/ScrollPositionAutoSaver.js +13 -2
  8. package/lib/cjs/scroll-position/ScrollPositionRestoration.js +29 -5
  9. package/lib/cjs/scroll-position/ScrollPositionSaver.js +8 -2
  10. package/lib/cjs/session/Session.js +6 -0
  11. package/lib/cjs/session/navigation/operation/operations.js +4 -4
  12. package/lib/esm/NavigationStack.js +17 -2
  13. package/lib/esm/debug.js +7 -0
  14. package/lib/esm/getLocationFromInternalLocation.js +2 -2
  15. package/lib/esm/navigationBlockers.js +3 -0
  16. package/lib/esm/scroll-position/ScrollPositionAutoSaver.js +13 -2
  17. package/lib/esm/scroll-position/ScrollPositionRestoration.js +29 -5
  18. package/lib/esm/scroll-position/ScrollPositionSaver.js +8 -2
  19. package/lib/esm/session/Session.js +6 -0
  20. package/lib/esm/session/navigation/operation/operations.js +4 -4
  21. package/lib/index.d.ts +10 -9
  22. package/lib/scroll-position/index.d.ts +3 -3
  23. package/package.json +1 -1
  24. package/src/NavigationStack.js +18 -2
  25. package/src/debug.js +8 -0
  26. package/src/getLocationFromInternalLocation.js +2 -2
  27. package/src/navigationBlockers.js +3 -0
  28. package/src/scroll-position/ScrollPositionAutoSaver.js +19 -2
  29. package/src/scroll-position/ScrollPositionRestoration.js +92 -47
  30. package/src/scroll-position/ScrollPositionSaver.js +21 -1
  31. package/src/session/Session.js +22 -0
  32. package/src/session/navigation/operation/operations.js +4 -4
  33. package/test/NavigationStack.test.js +14 -14
  34. package/test/middlewareTestUtil.js +1 -1
  35. package/test/redux/locationReducer.test.js +1 -1
  36. package/test/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.test.js +5 -5
  37. package/test/redux/middleware/createProgrammaticNavigationBlockerMiddleware.test.js +2 -2
  38. package/test/redux/middleware/navigationOperationMiddleware.test.js +2 -2
  39. package/test/scroll-position/ScrollPositionRestoration.test.js +73 -56
  40. package/test/scroll-position/addScrollableContainer.js +5 -2
  41. package/test/scroll-position/{addScrollableContainerWithHyperlink.js → addScrollableContainerWithAnchors.js} +8 -2
  42. package/test/scroll-position/createApp.js +20 -0
  43. package/test/scroll-position/withScrollableContainerAtIndexPageWithDisabledAutomaticScrollPositionRestoration.js +72 -0
  44. package/test/session/InMemorySession.test.js +28 -28
  45. package/test/session/ServerSession.test.js +1 -1
  46. package/test/session/WebBrowserSession.test.js +17 -17
  47. package/types/index.d.ts +10 -9
  48. package/types/scroll-position/index.d.ts +3 -3
  49. package/test/scroll-position/withScrollableContainerAtIndexPage.js +0 -62
@@ -5,6 +5,7 @@ import ScrollPositionSaver from './ScrollPositionSaver';
5
5
  import ScrollPositionSetter from './ScrollPositionSetter';
6
6
  import { PAGE_SCROLLABLE_CONTAINER_KEY } from './constants';
7
7
  import LocationDataStorage from '../data-storage/LocationDataStorage';
8
+ import debug from '../debug';
8
9
 
9
10
  function areEqualScrollPositions(scrollPosition1, scrollPosition2) {
10
11
  let i = 0;
@@ -81,12 +82,22 @@ export default class ScrollPositionRestoration {
81
82
  // this._scrollableContainerKeyCounter++;
82
83
  // const scrollableContainerKey = String(this._scrollableContainerKeyCounter);
83
84
 
85
+ // Validate `scrollableContainerKey`.
84
86
  if (scrollableContainerKey === PAGE_SCROLLABLE_CONTAINER_KEY) {
85
87
  throw new Error(
86
88
  `Scrollable container key "${scrollableContainerKey}" is not allowed`,
87
89
  );
88
90
  }
89
91
 
92
+ // Check that it hasn't already been added.
93
+ if (this._scrollableContainers[scrollableContainerKey]) {
94
+ throw new Error(
95
+ `Scrollable container key "${scrollableContainerKey}" is already added`,
96
+ );
97
+ }
98
+
99
+ debug('add scrollable container', scrollableContainerKey);
100
+
90
101
  // Add scrollable container entry.
91
102
  this._scrollableContainers[scrollableContainerKey] = {
92
103
  // Scrollable container element.
@@ -126,11 +137,22 @@ export default class ScrollPositionRestoration {
126
137
  scrollableContainerKey,
127
138
  );
128
139
  if (previouslySavedScrollPosition) {
140
+ debug(
141
+ 'restore scroll position on add scrollable container',
142
+ this._location.pathname,
143
+ scrollableContainerKey,
144
+ previouslySavedScrollPosition,
145
+ );
129
146
  this._scrollPosition.setScrollableContainerScrollPosition(
130
147
  scrollableContainer,
131
148
  previouslySavedScrollPosition,
132
149
  );
133
150
  } else {
151
+ debug(
152
+ 'save scroll position on add scrollable container',
153
+ this._location.pathname,
154
+ scrollableContainerKey,
155
+ );
134
156
  this._scrollPositionSaver.saveScrollableContainerScrollPosition(
135
157
  scrollableContainerKey,
136
158
  scrollableContainer,
@@ -146,12 +168,16 @@ export default class ScrollPositionRestoration {
146
168
 
147
169
  // Removes the scrollable container.
148
170
  return () => {
171
+ debug('remove scrollable container', scrollableContainerKey);
172
+
149
173
  this._scrollPositionSaver._scrollPositionAutoSaver.cancelSaveScrollableContainerScrollPosition(
150
174
  scrollableContainerKey,
151
175
  );
176
+
152
177
  this._scrollPositionSaver._scrollPositionAutoSaver.removeScrollableContainerScrollListener(
153
178
  scrollableContainerKey,
154
179
  );
180
+
155
181
  delete this._scrollableContainers[scrollableContainerKey];
156
182
  };
157
183
  }
@@ -231,8 +257,10 @@ export default class ScrollPositionRestoration {
231
257
  //
232
258
  _sessionExecutionStatusListener = ({ running }) => {
233
259
  if (running) {
260
+ debug('▶ running');
234
261
  this._disableAutomaticScrollRestoration();
235
262
  } else {
263
+ debug('⏹ not running');
236
264
  this._enableAutomaticScrollRestoration();
237
265
 
238
266
  // There might be previous scroll position already saved in the data storage.
@@ -266,15 +294,22 @@ export default class ScrollPositionRestoration {
266
294
  //
267
295
  // // Save the current scroll position on the current page while it's still rendered.
268
296
  // // This saved scroll position could later be restored in case of returing to this page.
297
+ // // Even if the current scroll position is a default one (scrolled to top), it should still
298
+ // // be saved in order to overwrite any potential previously-saved non-default scroll position.
269
299
  // this._scrollPositionSaver.saveScrollPosition();
270
300
  // };
271
301
 
302
+ // Should be called whenever a different location has been rendered (i.e. immediately after).
303
+ // Returns a Promise that resolves when finished restoring scroll position.
304
+ // There's no need to await for that Promise. It's just there because it exists.
272
305
  locationRendered(location) {
273
306
  // Validate that `location` has a `key`.
274
307
  if (!location.key) {
275
308
  throw new Error('`location` must have a `key`');
276
309
  }
277
310
 
311
+ debug('rendered location', location.pathname);
312
+
278
313
  this._prevLocation = this._location;
279
314
  this._location = location;
280
315
 
@@ -307,7 +342,7 @@ export default class ScrollPositionRestoration {
307
342
 
308
343
  // Set the scroll position for the new page:
309
344
  // either restore a previously-saved one or set it to a default scroll position.
310
- this._setScrollPosition();
345
+ return this._setScrollPosition();
311
346
  }
312
347
 
313
348
  // Tells if the current scroll position is the default one.
@@ -343,59 +378,69 @@ export default class ScrollPositionRestoration {
343
378
  return true;
344
379
  }
345
380
 
381
+ // Restores scroll position.
382
+ // Returns a Promise that resolves when finished setting scroll position.
383
+ // There's no need to await for this Promise. It just exists.
346
384
  _setScrollPosition() {
347
- for (const scrollableContainerKey of Object.keys(
348
- this._scrollableContainers,
349
- )) {
350
- const scrollableContainerEntry =
351
- this._scrollableContainers[scrollableContainerKey];
385
+ return Promise.all(
386
+ Object.keys(this._scrollableContainers).map((scrollableContainerKey) => {
387
+ const scrollableContainerEntry =
388
+ this._scrollableContainers[scrollableContainerKey];
352
389
 
353
- // This function is only used in tests.
354
- // There seems to be no use of it in real life, hence it's not public API.
355
- // It's only used in tests.
356
- if (scrollableContainerEntry._shouldUpdateScrollPositionForLocation) {
357
- if (
358
- !scrollableContainerEntry._shouldUpdateScrollPositionForLocation(
359
- this._location,
360
- this._prevLocation,
361
- )
362
- ) {
363
- continue;
390
+ // This function is only used in tests.
391
+ // There seems to be no use of it in real life, hence it's not public API.
392
+ // It's only used in tests.
393
+ if (scrollableContainerEntry._shouldUpdateScrollPositionForLocation) {
394
+ if (
395
+ !scrollableContainerEntry._shouldUpdateScrollPositionForLocation(
396
+ this._location,
397
+ this._prevLocation,
398
+ )
399
+ ) {
400
+ return Promise.resolve();
401
+ }
364
402
  }
365
- }
366
403
 
367
- // Scroll position (or anchor) to set.
368
- let scrollPositionOrAnchorToSet;
404
+ // Scroll position (or anchor) to set.
405
+ let scrollPositionOrAnchorToSet;
406
+
407
+ // This function is only used in tests.
408
+ // There seems to be no use of it in real life, hence it's not public API.
409
+ // It's only used in tests.
410
+ if (scrollableContainerEntry._getScrollPositionForLocation) {
411
+ scrollPositionOrAnchorToSet =
412
+ scrollableContainerEntry._getScrollPositionForLocation(
413
+ this._location,
414
+ this._prevLocation,
415
+ );
416
+ }
369
417
 
370
- // This function is only used in tests.
371
- // There seems to be no use of it in real life, hence it's not public API.
372
- // It's only used in tests.
373
- if (scrollableContainerEntry._getScrollPositionForLocation) {
374
- scrollPositionOrAnchorToSet =
375
- scrollableContainerEntry._getScrollPositionForLocation(
376
- this._location,
377
- this._prevLocation,
378
- );
379
- }
418
+ // Get scroll position (or anchor) to set.
419
+ if (!scrollPositionOrAnchorToSet) {
420
+ scrollPositionOrAnchorToSet =
421
+ scrollableContainerKey === PAGE_SCROLLABLE_CONTAINER_KEY
422
+ ? this._getPageScrollPositionOrAnchorToSet(this._location)
423
+ : this._getScrollableContainerScrollPositionToSet(
424
+ this._location,
425
+ scrollableContainerKey,
426
+ );
427
+ }
380
428
 
381
- // Get scroll position (or anchor) to set.
382
- if (!scrollPositionOrAnchorToSet) {
383
- scrollPositionOrAnchorToSet =
384
- scrollableContainerKey === PAGE_SCROLLABLE_CONTAINER_KEY
385
- ? this._getPageScrollPositionOrAnchorToSet(this._location)
386
- : this._getScrollableContainerScrollPositionToSet(
387
- this._location,
388
- scrollableContainerKey,
389
- );
390
- }
429
+ debug(
430
+ 'restore scroll position',
431
+ this._location.pathname,
432
+ scrollableContainerKey,
433
+ scrollPositionOrAnchorToSet,
434
+ );
391
435
 
392
- // Set scroll position of scrollable container.
393
- scrollableContainerEntry.scrollPositionSetter.set(
394
- scrollableContainerEntry.scrollableContainer,
395
- scrollPositionOrAnchorToSet,
396
- this._scrollPosition,
397
- );
398
- }
436
+ // Set scroll position of scrollable container.
437
+ return scrollableContainerEntry.scrollPositionSetter.set(
438
+ scrollableContainerEntry.scrollableContainer,
439
+ scrollPositionOrAnchorToSet,
440
+ this._scrollPosition,
441
+ );
442
+ }),
443
+ );
399
444
  }
400
445
 
401
446
  // Overrides the default `window.history.scrollRestoration` value.
@@ -2,6 +2,7 @@
2
2
 
3
3
  import ScrollPositionAutoSaver from './ScrollPositionAutoSaver';
4
4
  import { PAGE_SCROLLABLE_CONTAINER_KEY } from './constants';
5
+ import debug from '../debug';
5
6
 
6
7
  export default class ScrollPositionSaver {
7
8
  constructor({
@@ -43,6 +44,8 @@ export default class ScrollPositionSaver {
43
44
  return;
44
45
  }
45
46
 
47
+ debug('save scroll position', this._getLocation().pathname);
48
+
46
49
  // Get scrollable containers.
47
50
  const scrollableContainers = this._getScrollableContainers();
48
51
 
@@ -60,12 +63,19 @@ export default class ScrollPositionSaver {
60
63
  }
61
64
 
62
65
  savePageScrollPosition() {
66
+ debug(
67
+ 'save scroll position',
68
+ this._getLocation().pathname,
69
+ PAGE_SCROLLABLE_CONTAINER_KEY,
70
+ this._scrollPosition.getPageScrollPosition(),
71
+ );
72
+
63
73
  // * If this is not a scheduled "auto-save" of scroll position
64
74
  // and there already exists any scheduled "auto-save" of scroll position,
65
75
  // cancel it and save scroll position right now instead.
66
76
  // * If this is a scheduled "auto-save" of scroll position,
67
77
  // clear the "cancel" function because it's no longer of use.
68
- this._scrollPositionAutoSaver.cancelSavePageScrollPosition();
78
+ this._scrollPositionAutoSaver.cancelSavePageScrollPosition(true);
69
79
 
70
80
  // Save scroll position.
71
81
  this._saveScrollPositionForLocation(
@@ -79,6 +89,15 @@ export default class ScrollPositionSaver {
79
89
  scrollableContainerKey,
80
90
  scrollableContainer,
81
91
  ) {
92
+ debug(
93
+ 'save scroll position',
94
+ this._getLocation().pathname,
95
+ scrollableContainerKey,
96
+ this._scrollPosition.getScrollableContainerScrollPosition(
97
+ scrollableContainer,
98
+ ),
99
+ );
100
+
82
101
  // * If this is not a scheduled "auto-save" of scroll position
83
102
  // and there already exists any scheduled "auto-save" of scroll position,
84
103
  // cancel it and save scroll position right now instead.
@@ -86,6 +105,7 @@ export default class ScrollPositionSaver {
86
105
  // clear the "cancel" function because it's no longer of use.
87
106
  this._scrollPositionAutoSaver.cancelSaveScrollableContainerScrollPosition(
88
107
  scrollableContainerKey,
108
+ true,
89
109
  );
90
110
 
91
111
  // Save scroll position.
@@ -1,3 +1,4 @@
1
+ import debug from '../debug';
1
2
  import parseInputLocation from '../parseInputLocation';
2
3
  import createSessionKey from './key/createSessionKey';
3
4
  import NavigationOutOfBoundsError from './navigation/error/NavigationOutOfBoundsError';
@@ -48,6 +49,13 @@ export default class Session {
48
49
  // but if it was possible, this call would be required. It would also be required
49
50
  // by `navigation` to call `session.getNextKey()` function to increment `locationKeyIndex`.
50
51
  this._updateTerminalLocationIndex(location);
52
+
53
+ debug(
54
+ 'current location',
55
+ location.pathname,
56
+ 'index',
57
+ this._currentLocationIndex,
58
+ );
51
59
  });
52
60
  }
53
61
 
@@ -94,6 +102,8 @@ export default class Session {
94
102
  throw new Error('Already started');
95
103
  }
96
104
 
105
+ debug('▶ start session', initialLocation.pathname);
106
+
97
107
  this._started = true;
98
108
 
99
109
  const key = this._getNextLocationKey();
@@ -117,6 +127,8 @@ export default class Session {
117
127
  throw Error('Already stopped');
118
128
  }
119
129
 
130
+ debug('⏹ stop session');
131
+
120
132
  // Once stopped, it won't be able to be restarted.
121
133
  this._stopped = true;
122
134
 
@@ -148,6 +160,14 @@ export default class Session {
148
160
  const key = this._getNextLocationKey();
149
161
  const index = this._currentLocationIndex + delta;
150
162
 
163
+ debug(
164
+ operation === NavigationOperations.PUSH ? '↓' : '⇅',
165
+ operation,
166
+ location.pathname,
167
+ 'index',
168
+ index,
169
+ );
170
+
151
171
  // Navigate to the location.
152
172
  const locationResult = this._navigation.navigate(location, {
153
173
  operation,
@@ -173,6 +193,8 @@ export default class Session {
173
193
 
174
194
  const index = this._currentLocationIndex + delta;
175
195
 
196
+ debug(delta > 0 ? '→' : '←', 'shift', delta, 'index', index);
197
+
176
198
  // Validate that the new `index` is not out of bounds.
177
199
  if (index < 0 || index > this._terminalLocationIndex) {
178
200
  throw new NavigationOutOfBoundsError(index);
@@ -1,6 +1,6 @@
1
1
  export default {
2
- INIT: 'INIT',
3
- PUSH: 'PUSH',
4
- REPLACE: 'REPLACE',
5
- SHIFT: 'SHIFT',
2
+ INIT: 'init',
3
+ PUSH: 'push',
4
+ REPLACE: 'replace',
5
+ SHIFT: 'shift',
6
6
  };
@@ -23,19 +23,19 @@ describe('NavigationStack', () => {
23
23
  navigationStack.push('/new');
24
24
  expect(navigationStack.current()).to.include({
25
25
  pathname: '/new',
26
- // index: 1,
26
+ index: 1,
27
27
  });
28
28
 
29
29
  navigationStack.shift(-1);
30
30
  expect(navigationStack.current()).to.include({
31
31
  pathname: '/initial',
32
- // index: 0,
32
+ index: 0,
33
33
  });
34
34
 
35
35
  navigationStack.shift(+1);
36
36
  expect(navigationStack.current()).to.include({
37
37
  pathname: '/new',
38
- // index: 1,
38
+ index: 1,
39
39
  });
40
40
  });
41
41
 
@@ -43,7 +43,7 @@ describe('NavigationStack', () => {
43
43
  navigationStack.replace('/new');
44
44
  expect(navigationStack.current()).to.include({
45
45
  pathname: '/new',
46
- // index: 0,
46
+ index: 0,
47
47
  });
48
48
  });
49
49
  });
@@ -71,21 +71,21 @@ describe('NavigationStack (WebBrowserSession)', () => {
71
71
  await delay(20);
72
72
  expect(navigationStack.current()).to.include({
73
73
  pathname: '/new',
74
- // index: 1,
74
+ index: 1,
75
75
  });
76
76
 
77
77
  navigationStack.shift(-1);
78
78
  await delay(20);
79
79
  expect(navigationStack.current()).to.include({
80
80
  pathname: '/initial',
81
- // index: 0,
81
+ index: 0,
82
82
  });
83
83
 
84
84
  navigationStack.shift(+1);
85
85
  await delay(20);
86
86
  expect(navigationStack.current()).to.include({
87
87
  pathname: '/new',
88
- // index: 1,
88
+ index: 1,
89
89
  });
90
90
  });
91
91
 
@@ -94,7 +94,7 @@ describe('NavigationStack (WebBrowserSession)', () => {
94
94
  await delay(20);
95
95
  expect(navigationStack.current()).to.include({
96
96
  pathname: '/new',
97
- // index: 0,
97
+ index: 0,
98
98
  });
99
99
  });
100
100
  });
@@ -121,7 +121,7 @@ describe('NavigationStack.subscribe', () => {
121
121
  // `.init()` calls subscription listeners.
122
122
  expect(listener).to.have.been.calledOnce();
123
123
  expect(listener.lastCall.args[0]).to.include({
124
- // operation: 'INIT',
124
+ // operation: 'init',
125
125
  pathname: '/initial',
126
126
  });
127
127
  listener.resetHistory();
@@ -130,7 +130,7 @@ describe('NavigationStack.subscribe', () => {
130
130
 
131
131
  expect(listener).to.have.been.calledOnce();
132
132
  expect(listener.lastCall.args[0]).to.include({
133
- // operation: 'PUSH',
133
+ // operation: 'push',
134
134
  pathname: '/new',
135
135
  });
136
136
  listener.resetHistory();
@@ -139,7 +139,7 @@ describe('NavigationStack.subscribe', () => {
139
139
 
140
140
  expect(listener).to.have.been.calledOnce();
141
141
  expect(listener.lastCall.args[0]).to.include({
142
- // operation: 'REPLACE',
142
+ // operation: 'replace',
143
143
  pathname: '/new-2',
144
144
  });
145
145
  listener.resetHistory();
@@ -148,7 +148,7 @@ describe('NavigationStack.subscribe', () => {
148
148
 
149
149
  expect(listener).to.have.been.calledOnce();
150
150
  expect(listener.lastCall.args[0]).to.include({
151
- // operation: 'SHIFT',
151
+ // operation: 'shift',
152
152
  // delta: -1,
153
153
  pathname: '/initial',
154
154
  });
@@ -176,7 +176,7 @@ describe('NavigationStack.subscribe', () => {
176
176
  // `.init()` calls subscription listeners.
177
177
  expect(listener).to.have.been.calledOnce();
178
178
  expect(listener.lastCall.args[0]).to.include({
179
- // operation: 'INIT',
179
+ // operation: 'init',
180
180
  pathname: '/initial',
181
181
  });
182
182
  listener.resetHistory();
@@ -252,7 +252,7 @@ describe('NavigationStack', () => {
252
252
 
253
253
  expect(navigationStack.current()).to.include({
254
254
  pathname: '/new',
255
- // index: 1,
255
+ index: 1,
256
256
  });
257
257
  });
258
258
 
@@ -17,7 +17,7 @@ export function transformInputLocationUsingMiddleware(middleware, location) {
17
17
  return invokeLocationMiddleware(middleware, {
18
18
  type: ActionTypes.NAVIGATE,
19
19
  payload: {
20
- operation: 'PUSH',
20
+ operation: 'push',
21
21
  location,
22
22
  },
23
23
  }).payload.location;
@@ -3,7 +3,7 @@ import locationReducer from '../../src/redux/locationReducer';
3
3
 
4
4
  describe('locationReducer', () => {
5
5
  const prevState = {
6
- operation: 'PUSH',
6
+ operation: 'push',
7
7
  delta: 1,
8
8
  hash: '',
9
9
  index: 5,
@@ -40,7 +40,7 @@ describe('createNonProgrammaticNavigationBlockerMiddleware', () => {
40
40
  // sandbox.restore();
41
41
  });
42
42
 
43
- describe('SHIFT navigation', () => {
43
+ describe('shift navigation', () => {
44
44
  beforeEach(() => {
45
45
  store.dispatch(Actions.push('/new'));
46
46
  });
@@ -53,7 +53,7 @@ describe('createNonProgrammaticNavigationBlockerMiddleware', () => {
53
53
  expect(store.getState().pathname).to.equal('/initial');
54
54
 
55
55
  expect(blocker.firstCall.args[0]).to.include({
56
- // operation: 'SHIFT',
56
+ // operation: 'shift',
57
57
  pathname: '/initial',
58
58
  // delta: -1,
59
59
  });
@@ -199,7 +199,7 @@ describe('createNonProgrammaticNavigationBlockerMiddleware', () => {
199
199
  // session._currentLocationIndex = 0;
200
200
  // session._navigation._triggerUpdateInternalLocationMiddlewareListener(
201
201
  // session._navigation._createLocationObject({
202
- // operation: 'SHIFT',
202
+ // operation: 'shift',
203
203
  // delta: null,
204
204
  // }),
205
205
  // );
@@ -222,7 +222,7 @@ describe('createNonProgrammaticNavigationBlockerMiddleware', () => {
222
222
  // /* eslint-disable no-underscore-dangle */
223
223
  // session._navigation._index = 0;
224
224
  // session._navigation._subscriptionListener(session._navigation._createLocationObject({
225
- // operation: 'SHIFT',
225
+ // operation: 'shift',
226
226
  // delta: null,
227
227
  // }));
228
228
  // /* eslint-enable no-underscore-dangle */
@@ -245,7 +245,7 @@ describe('createNonProgrammaticNavigationBlockerMiddleware', () => {
245
245
  // /* eslint-disable no-underscore-dangle */
246
246
  // session._navigation._index = 0;
247
247
  // session._navigation._subscriptionListener(session._navigation._createLocationObject({
248
- // operation: 'SHIFT',
248
+ // operation: 'shift',
249
249
  // delta: null,
250
250
  // }));
251
251
  // /* eslint-enable no-underscore-dangle */
@@ -41,7 +41,7 @@ describe('createProgrammaticNavigationBlockerMiddleware', () => {
41
41
  // sandbox.restore();
42
42
  });
43
43
 
44
- describe('PUSH navigation', () => {
44
+ describe('push navigation', () => {
45
45
  it('should block navigation when blocker returns `true`', () => {
46
46
  const blocker = sinon.stub().returns(true);
47
47
  addNavigationBlocker(blocker);
@@ -52,7 +52,7 @@ describe('createProgrammaticNavigationBlockerMiddleware', () => {
52
52
  expect(blocker).to.have.been.calledOnce();
53
53
 
54
54
  expect(blocker.firstCall.args[0]).to.include({
55
- // operation: 'PUSH',
55
+ // operation: 'push',
56
56
  pathname: '/new',
57
57
  });
58
58
  });
@@ -22,7 +22,7 @@ describe('navigationOperationMiddleware', () => {
22
22
  expect(next).to.be.calledWith({
23
23
  type: ActionTypes.NAVIGATE,
24
24
  payload: {
25
- operation: 'PUSH',
25
+ operation: 'push',
26
26
  location: {
27
27
  pathname: '/foo',
28
28
  search: '?bar=baz',
@@ -45,7 +45,7 @@ describe('navigationOperationMiddleware', () => {
45
45
  expect(next).to.be.calledWith({
46
46
  type: ActionTypes.NAVIGATE,
47
47
  payload: {
48
- operation: 'REPLACE',
48
+ operation: 'replace',
49
49
  location: {
50
50
  pathname: '/foo',
51
51
  search: '?bar=baz',