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.
Files changed (210) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +144 -282
  3. package/karma.conf.cjs +1 -1
  4. package/lib/cjs/NavigationStack.js +138 -49
  5. package/lib/cjs/data-storage/DataStorage.js +7 -6
  6. package/lib/cjs/environment/InMemoryEnvironment.js +6 -0
  7. package/lib/cjs/{session/ServerSideRenderSession.js → environment/ServerSideRenderEnvironment.js} +5 -6
  8. package/lib/cjs/environment/WebBrowserEnvironment.js +6 -0
  9. package/lib/cjs/environment/log/InMemoryLog.js +23 -0
  10. package/lib/cjs/environment/log/WebBrowserLog.js +22 -0
  11. package/lib/cjs/{session → environment}/navigation/InMemoryNavigation.js +16 -5
  12. package/lib/cjs/{session → environment}/navigation/ServerSideNavigation.js +16 -7
  13. package/lib/cjs/{session → environment}/navigation/WebBrowserNavigation.js +48 -8
  14. package/lib/cjs/{session/navigation/error/ServerSideNavigationError.js → environment/navigation/error/ServerSideRedirectError.js} +2 -2
  15. package/lib/cjs/environment/scroll-position/WebBrowserScrollPosition.js +15 -0
  16. package/lib/cjs/getLocationBaseFromLocation.js +14 -0
  17. package/lib/cjs/getLocationUrl.js +3 -5
  18. package/lib/cjs/index.js +10 -16
  19. package/lib/cjs/navigationBlockers.js +34 -32
  20. package/lib/cjs/navigationBlockersEvaluation.js +150 -0
  21. package/lib/cjs/parseInputLocation.js +2 -2
  22. package/lib/cjs/parseQueryFromSearch.js +3 -6
  23. package/lib/cjs/parseQueryString.js +77 -0
  24. package/lib/cjs/scroll-position/ScrollPositionAutoSaver.js +7 -6
  25. package/lib/cjs/scroll-position/ScrollPositionRestoration.js +31 -27
  26. package/lib/cjs/scroll-position/ScrollPositionSaver.js +6 -4
  27. package/lib/cjs/session/Session.js +61 -26
  28. package/lib/cjs/session/subscription/Subscription.js +36 -18
  29. package/lib/cjs/stringifyQuery.js +66 -0
  30. package/lib/cjs/stringifyQueryAsSearch.js +14 -0
  31. package/lib/esm/NavigationStack.js +138 -49
  32. package/lib/esm/data-storage/DataStorage.js +7 -6
  33. package/lib/esm/environment/InMemoryEnvironment.js +6 -0
  34. package/lib/esm/environment/ServerSideRenderEnvironment.js +10 -0
  35. package/lib/esm/environment/WebBrowserEnvironment.js +6 -0
  36. package/lib/esm/environment/log/InMemoryLog.js +17 -0
  37. package/lib/esm/environment/log/WebBrowserLog.js +16 -0
  38. package/lib/esm/{session → environment}/navigation/InMemoryNavigation.js +16 -5
  39. package/lib/esm/{session → environment}/navigation/ServerSideNavigation.js +16 -7
  40. package/lib/esm/{session → environment}/navigation/WebBrowserNavigation.js +48 -8
  41. package/lib/esm/{session/navigation/error/ServerSideNavigationError.js → environment/navigation/error/ServerSideRedirectError.js} +1 -1
  42. package/lib/esm/environment/scroll-position/WebBrowserScrollPosition.js +15 -0
  43. package/lib/esm/getLocationBaseFromLocation.js +9 -0
  44. package/lib/esm/getLocationUrl.js +2 -5
  45. package/lib/esm/index.js +5 -8
  46. package/lib/esm/navigationBlockers.js +34 -32
  47. package/lib/esm/navigationBlockersEvaluation.js +145 -0
  48. package/lib/esm/parseInputLocation.js +2 -2
  49. package/lib/esm/parseQueryFromSearch.js +2 -6
  50. package/lib/esm/parseQueryString.js +72 -0
  51. package/lib/esm/scroll-position/ScrollPositionAutoSaver.js +7 -6
  52. package/lib/esm/scroll-position/ScrollPositionRestoration.js +31 -27
  53. package/lib/esm/scroll-position/ScrollPositionSaver.js +6 -4
  54. package/lib/esm/session/Session.js +61 -26
  55. package/lib/esm/session/subscription/Subscription.js +36 -18
  56. package/lib/esm/stringifyQuery.js +61 -0
  57. package/lib/esm/stringifyQueryAsSearch.js +8 -0
  58. package/lib/index.d.ts +180 -34
  59. package/package.json +4 -7
  60. package/src/NavigationStack.js +166 -56
  61. package/src/data-storage/DataStorage.js +9 -6
  62. package/src/environment/InMemoryEnvironment.js +6 -0
  63. package/src/environment/ServerSideRenderEnvironment.js +10 -0
  64. package/src/environment/WebBrowserEnvironment.js +6 -0
  65. package/src/environment/log/InMemoryLog.js +20 -0
  66. package/src/environment/log/WebBrowserLog.js +18 -0
  67. package/src/{session → environment}/navigation/InMemoryNavigation.js +16 -5
  68. package/src/{session → environment}/navigation/ServerSideNavigation.js +16 -7
  69. package/src/{session → environment}/navigation/WebBrowserNavigation.js +48 -8
  70. package/src/{session/navigation/error/ServerSideNavigationError.js → environment/navigation/error/ServerSideRedirectError.js} +1 -1
  71. package/src/environment/scroll-position/WebBrowserScrollPosition.js +15 -0
  72. package/src/getLocationBaseFromLocation.js +7 -0
  73. package/src/getLocationUrl.js +2 -5
  74. package/src/index.js +10 -13
  75. package/src/navigationBlockers.js +55 -34
  76. package/src/navigationBlockersEvaluation.js +161 -0
  77. package/src/parseInputLocation.js +2 -2
  78. package/src/parseQueryFromSearch.js +2 -6
  79. package/src/parseQueryString.js +81 -0
  80. package/src/scroll-position/ScrollPositionAutoSaver.js +10 -6
  81. package/src/scroll-position/ScrollPositionRestoration.js +36 -30
  82. package/src/scroll-position/ScrollPositionSaver.js +6 -4
  83. package/src/scroll-position/index.js +1 -1
  84. package/src/session/Session.js +68 -24
  85. package/src/session/subscription/Subscription.js +36 -11
  86. package/src/stringifyQuery.js +71 -0
  87. package/src/stringifyQueryAsSearch.js +9 -0
  88. package/test/NavigationStack.addBasePath.test.js +50 -0
  89. package/test/{redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.test.js → NavigationStack.blockNonProgrammaticNavigationIfRequired.test.js} +51 -63
  90. package/test/{redux/middleware/createProgrammaticNavigationBlockerMiddleware.test.js → NavigationStack.blockProgrammaticNavigationIfRequired.test.js} +98 -78
  91. package/test/NavigationStack.general.test.js +68 -0
  92. package/test/NavigationStack.parseInputLocation.test.js +52 -0
  93. package/test/NavigationStack.removeBasePath.test.js +69 -0
  94. package/test/NavigationStack.test.js +97 -29
  95. package/test/data-storage/LocationDataStorage.test.js +3 -2
  96. package/test/index.js +7 -31
  97. package/test/index.test.js +4 -5
  98. package/test/parseQueryFromSearch.test.js +19 -0
  99. package/test/parseQueryString.test.js +18 -0
  100. package/test/scroll-position/ScrollPositionRestoration.test.js +34 -13
  101. package/test/scroll-position/createApp.js +8 -8
  102. package/test/scroll-position/withScrollableContainerAtIndexPageWithDisabledAutomaticScrollPositionRestoration.js +4 -4
  103. package/test/session/{InMemorySession.test.js → Session.InMemoryEnvironment.test.js} +10 -9
  104. package/test/session/{ServerSession.test.js → Session.ServerSideRenderEnvironment.test.js} +5 -4
  105. package/test/session/{WebBrowserSession.test.js → Session.WebBrowserEnvironment.test.js} +63 -13
  106. package/test/shouldWarn.js +44 -0
  107. package/test/stringifyQuery.test.js +65 -0
  108. package/types/index.d.ts +180 -34
  109. package/types/tsconfig.json +0 -1
  110. package/data-storage/package.json +0 -7
  111. package/lib/cjs/createSearchFromQuery.js +0 -13
  112. package/lib/cjs/debug.js +0 -12
  113. package/lib/cjs/redux/ActionTypes.js +0 -14
  114. package/lib/cjs/redux/ActionTypesInternal.js +0 -8
  115. package/lib/cjs/redux/Actions.js +0 -28
  116. package/lib/cjs/redux/createMiddlewares.js +0 -60
  117. package/lib/cjs/redux/index.js +0 -13
  118. package/lib/cjs/redux/internalLocationReducer.js +0 -14
  119. package/lib/cjs/redux/locationReducer.js +0 -13
  120. package/lib/cjs/redux/middleware/createAddInputLocationBasePathMiddleware.js +0 -32
  121. package/lib/cjs/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.js +0 -113
  122. package/lib/cjs/redux/middleware/createProgrammaticNavigationBlockerMiddleware.js +0 -94
  123. package/lib/cjs/redux/middleware/createRemoveOutputLocationBasePathMiddleware.js +0 -30
  124. package/lib/cjs/redux/middleware/createUpdateInternalLocationMiddleware.js +0 -73
  125. package/lib/cjs/redux/middleware/navigationOperationMiddleware.js +0 -40
  126. package/lib/cjs/redux/middleware/parseInputLocationMiddleware.js +0 -29
  127. package/lib/cjs/redux/middleware/updateLocationMiddleware.js +0 -34
  128. package/lib/cjs/session/InMemorySession.js +0 -22
  129. package/lib/cjs/session/WebBrowserSession.js +0 -20
  130. package/lib/data-storage/index.d.ts +0 -35
  131. package/lib/esm/createSearchFromQuery.js +0 -8
  132. package/lib/esm/debug.js +0 -7
  133. package/lib/esm/redux/ActionTypes.js +0 -9
  134. package/lib/esm/redux/ActionTypesInternal.js +0 -3
  135. package/lib/esm/redux/Actions.js +0 -22
  136. package/lib/esm/redux/createMiddlewares.js +0 -54
  137. package/lib/esm/redux/index.js +0 -4
  138. package/lib/esm/redux/internalLocationReducer.js +0 -8
  139. package/lib/esm/redux/locationReducer.js +0 -7
  140. package/lib/esm/redux/middleware/createAddInputLocationBasePathMiddleware.js +0 -27
  141. package/lib/esm/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.js +0 -108
  142. package/lib/esm/redux/middleware/createProgrammaticNavigationBlockerMiddleware.js +0 -88
  143. package/lib/esm/redux/middleware/createRemoveOutputLocationBasePathMiddleware.js +0 -25
  144. package/lib/esm/redux/middleware/createUpdateInternalLocationMiddleware.js +0 -68
  145. package/lib/esm/redux/middleware/navigationOperationMiddleware.js +0 -35
  146. package/lib/esm/redux/middleware/parseInputLocationMiddleware.js +0 -24
  147. package/lib/esm/redux/middleware/updateLocationMiddleware.js +0 -28
  148. package/lib/esm/session/InMemorySession.js +0 -15
  149. package/lib/esm/session/ServerSideRenderSession.js +0 -11
  150. package/lib/esm/session/WebBrowserSession.js +0 -13
  151. package/lib/redux/index.d.ts +0 -90
  152. package/lib/scroll-position/index.d.ts +0 -107
  153. package/redux/package.json +0 -7
  154. package/scroll-position/package.json +0 -7
  155. package/src/createSearchFromQuery.js +0 -9
  156. package/src/debug.js +0 -8
  157. package/src/redux/ActionTypes.js +0 -9
  158. package/src/redux/ActionTypesInternal.js +0 -3
  159. package/src/redux/Actions.js +0 -27
  160. package/src/redux/createMiddlewares.js +0 -65
  161. package/src/redux/index.js +0 -4
  162. package/src/redux/internalLocationReducer.js +0 -9
  163. package/src/redux/locationReducer.js +0 -8
  164. package/src/redux/middleware/createAddInputLocationBasePathMiddleware.js +0 -27
  165. package/src/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.js +0 -119
  166. package/src/redux/middleware/createProgrammaticNavigationBlockerMiddleware.js +0 -94
  167. package/src/redux/middleware/createRemoveOutputLocationBasePathMiddleware.js +0 -26
  168. package/src/redux/middleware/createUpdateInternalLocationMiddleware.js +0 -72
  169. package/src/redux/middleware/navigationOperationMiddleware.js +0 -34
  170. package/src/redux/middleware/parseInputLocationMiddleware.js +0 -23
  171. package/src/redux/middleware/updateLocationMiddleware.js +0 -28
  172. package/src/session/InMemorySession.js +0 -13
  173. package/src/session/ServerSideRenderSession.js +0 -9
  174. package/src/session/WebBrowserSession.js +0 -13
  175. package/test/middlewareTestUtil.js +0 -31
  176. package/test/redux/Action.test.js +0 -73
  177. package/test/redux/ActionTypes.test.js +0 -13
  178. package/test/redux/createMiddlewares.test.js +0 -96
  179. package/test/redux/index.test.js +0 -10
  180. package/test/redux/locationReducer.test.js +0 -39
  181. package/test/redux/middleware/createAddInputLocationBasePathMiddleware.test.js +0 -40
  182. package/test/redux/middleware/createRemoveOutputLocationBasePathMiddleware.test.js +0 -51
  183. package/test/redux/middleware/navigationOperationMiddleware.test.js +0 -78
  184. package/test/redux/middleware/parseInputLocationMiddleware.test.js +0 -62
  185. package/test/testUtil.js +0 -3
  186. package/types/data-storage/index.d.ts +0 -35
  187. package/types/redux/index.d.ts +0 -90
  188. package/types/scroll-position/index.d.ts +0 -107
  189. /package/lib/cjs/{session → environment}/lifecycle/InMemorySessionLifecycle.js +0 -0
  190. /package/lib/cjs/{session → environment}/lifecycle/WebBrowserSessionLifecycle.js +0 -0
  191. /package/lib/cjs/{session → environment}/lifecycle/page-lifecycle/PageLifecycle.js +0 -0
  192. /package/lib/cjs/{session → environment}/lifecycle/page-lifecycle/PageLifecycleInstance.js +0 -0
  193. /package/lib/cjs/{session → environment}/lifecycle/page-lifecycle/supportsConstructableEventTarget.js +0 -0
  194. /package/lib/cjs/{session → environment}/navigation/error/NavigationOutOfBoundsError.js +0 -0
  195. /package/lib/cjs/{session → environment}/navigation/operation/operations.js +0 -0
  196. /package/lib/esm/{session → environment}/lifecycle/InMemorySessionLifecycle.js +0 -0
  197. /package/lib/esm/{session → environment}/lifecycle/WebBrowserSessionLifecycle.js +0 -0
  198. /package/lib/esm/{session → environment}/lifecycle/page-lifecycle/PageLifecycle.js +0 -0
  199. /package/lib/esm/{session → environment}/lifecycle/page-lifecycle/PageLifecycleInstance.js +0 -0
  200. /package/lib/esm/{session → environment}/lifecycle/page-lifecycle/supportsConstructableEventTarget.js +0 -0
  201. /package/lib/esm/{session → environment}/navigation/error/NavigationOutOfBoundsError.js +0 -0
  202. /package/lib/esm/{session → environment}/navigation/operation/operations.js +0 -0
  203. /package/src/{session → environment}/lifecycle/InMemorySessionLifecycle.js +0 -0
  204. /package/src/{session → environment}/lifecycle/WebBrowserSessionLifecycle.js +0 -0
  205. /package/src/{session → environment}/lifecycle/page-lifecycle/PageLifecycle.js +0 -0
  206. /package/src/{session → environment}/lifecycle/page-lifecycle/PageLifecycleInstance.js +0 -0
  207. /package/src/{session → environment}/lifecycle/page-lifecycle/supportsConstructableEventTarget.js +0 -0
  208. /package/src/{session → environment}/navigation/error/NavigationOutOfBoundsError.js +0 -0
  209. /package/src/{session → environment}/navigation/operation/operations.js +0 -0
  210. /package/test/{parseInputLocationMiddleware.test.js → parseInputLocation.test.js} +0 -0
@@ -1,72 +0,0 @@
1
- import ActionTypes from '../ActionTypes';
2
- import ActionTypesInternal from '../ActionTypesInternal';
3
-
4
- // Creates a "middleware" that performs the actual navigation according to the `session` being used.
5
- // For example, when `WebBrowserSession` is used, it calls methods of the `window.history` object.
6
- export default function createUpdateInternalLocationMiddleware(
7
- session,
8
- { shouldIgnoreNavigationLocationSubscriptionEvents },
9
- ) {
10
- return function updateInternalLocationMiddleware() {
11
- return (next) => {
12
- // Whenever browser location changes,
13
- // perform the same changes with the internal `location` object.
14
- const unsubscribe = session.subscribe((location) => {
15
- if (!shouldIgnoreNavigationLocationSubscriptionEvents()) {
16
- next({
17
- // eslint-disable-next-line no-underscore-dangle
18
- type: ActionTypesInternal.INTERNAL_LOCATION_UPDATE,
19
- payload: location,
20
- });
21
- }
22
- });
23
-
24
- return (action) => {
25
- const { type, payload } = action;
26
-
27
- switch (type) {
28
- case ActionTypes.INIT:
29
- // `init()` will trigger the `subscribe()` listener,
30
- // which will call `updateLocation()`.
31
- session.start(payload);
32
- // eslint-disable-next-line consistent-return
33
- return;
34
-
35
- case ActionTypes.NAVIGATE:
36
- // `navigate()` will trigger the `subscribe()` listener,
37
- // which will call `updateLocation()`.
38
- session.navigate(payload.operation, payload.location);
39
- // eslint-disable-next-line consistent-return
40
- return;
41
-
42
- case ActionTypes.SHIFT:
43
- // `shift()` will trigger the `subscribe()` listener,
44
- // which will call `updateLocation()`.
45
- session.shift(payload);
46
- // eslint-disable-next-line consistent-return
47
- return;
48
-
49
- case ActionTypes.STOP:
50
- // Remove location change subscription.
51
- unsubscribe();
52
- // Even if it calls `unsubscribe()` function above, any other subscriptions
53
- // would still stay. We're not talking about `navigationStack.subscribe()`
54
- // subscriptions because those don't really matter in terms of cleaning them up:
55
- // those're just Redux store subscriptions that don't have any side effects.
56
- // Subscriptions we're talking here are `Session`'s own subscription
57
- // via `session.subscribe()` and any hypothetical manual `session.subscribe()`
58
- // calls that could be made by the application code for whatever purpose.
59
- // Both of those should be cleared.
60
- // To work around that, `.stop()` function removes all subscriptions.
61
- session.stop();
62
- // eslint-disable-next-line consistent-return
63
- return next(action);
64
-
65
- default:
66
- // eslint-disable-next-line consistent-return
67
- return next(action);
68
- }
69
- };
70
- };
71
- };
72
- }
@@ -1,34 +0,0 @@
1
- import Operations from '../../session/navigation/operation/operations';
2
- import ActionTypes from '../ActionTypes';
3
-
4
- // This "middleware" transforms a `PUSH` / `REPLACE` action into a `NAVIGATE` action.
5
- export default function navigationOperationMiddleware() {
6
- return (next) => (action) => {
7
- const { type, payload } = action;
8
-
9
- switch (type) {
10
- // Converts a `PUSH` action into a `NAVIGATE` action.
11
- case ActionTypes.PUSH:
12
- return next({
13
- type: ActionTypes.NAVIGATE,
14
- payload: {
15
- operation: Operations.PUSH,
16
- location: payload,
17
- },
18
- });
19
-
20
- // Converts a `REPLACE` action into a `NAVIGATE` action.
21
- case ActionTypes.REPLACE:
22
- return next({
23
- type: ActionTypes.NAVIGATE,
24
- payload: {
25
- operation: Operations.REPLACE,
26
- location: payload,
27
- },
28
- });
29
-
30
- default:
31
- return next(action);
32
- }
33
- };
34
- }
@@ -1,23 +0,0 @@
1
- import parseInputLocation from '../../parseInputLocation';
2
- import ActionTypes from '../ActionTypes';
3
-
4
- // This "middleware" transforms input location argument into a proper `NormalizedInputLocation`.
5
- export default function parseInputLocationMiddleware() {
6
- return (next) => (action) => {
7
- const { type, payload } = action;
8
-
9
- switch (type) {
10
- case ActionTypes.INIT:
11
- case ActionTypes.PUSH:
12
- case ActionTypes.REPLACE:
13
- return next({
14
- type,
15
- // `payload` is optional in `INIT` action.
16
- payload: payload && parseInputLocation(payload),
17
- });
18
-
19
- default:
20
- return next(action);
21
- }
22
- };
23
- }
@@ -1,28 +0,0 @@
1
- import getLocationFromInternalLocation from '../../getLocationFromInternalLocation';
2
- import ActionTypes from '../ActionTypes';
3
- import ActionTypesInternal from '../ActionTypesInternal';
4
-
5
- export default function updateLocationMiddleware() {
6
- return (next) => (action) => {
7
- const { type, payload } = action;
8
-
9
- switch (type) {
10
- // Convert `LocationInternal` object to a publicly-visible `Location` object.
11
- // It hides non-essential properties of location such as `operation`, `index`, `delta`.
12
- // eslint-disable-next-line no-underscore-dangle
13
- case ActionTypesInternal.INTERNAL_LOCATION_UPDATE:
14
- // Dispatch a "public" `UPDATE` Redux action.
15
- // This is what users of this package should use
16
- // rather than `INTERNAL_LOCATION_UPDATE` which is for internal purposes.
17
- next({
18
- type: ActionTypes.UPDATE,
19
- payload: getLocationFromInternalLocation(payload),
20
- });
21
- return;
22
-
23
- default:
24
- // eslint-disable-next-line consistent-return
25
- return next(action);
26
- }
27
- };
28
- }
@@ -1,13 +0,0 @@
1
- import Session from './Session';
2
- import InMemoryEnvironment from '../environment/InMemoryEnvironment';
3
- import InMemorySessionLifecycle from './lifecycle/InMemorySessionLifecycle';
4
- import InMemoryNavigation from './navigation/InMemoryNavigation';
5
-
6
- export default class InMemorySession extends Session {
7
- constructor({ navigation = new InMemoryNavigation() } = {}) {
8
- super({ navigation });
9
-
10
- this.environment = new InMemoryEnvironment();
11
- this.lifecycle = new InMemorySessionLifecycle();
12
- }
13
- }
@@ -1,9 +0,0 @@
1
- import InMemorySession from './InMemorySession';
2
- import ServerSideNavigation from './navigation/ServerSideNavigation';
3
-
4
- // `ServerSideRenderSession` is just a `InMemorySession` that specifically prohibits any navigation.
5
- export default class ServerSideRenderSession extends InMemorySession {
6
- constructor() {
7
- super({ navigation: new ServerSideNavigation() });
8
- }
9
- }
@@ -1,13 +0,0 @@
1
- import Session from './Session';
2
- import WebBrowserEnvironment from '../environment/WebBrowserEnvironment';
3
- import WebBrowserSessionLifecycle from './lifecycle/WebBrowserSessionLifecycle';
4
- import WebBrowserNavigation from './navigation/WebBrowserNavigation';
5
-
6
- export default class WebBrowserSession extends Session {
7
- constructor() {
8
- super({ navigation: new WebBrowserNavigation() });
9
-
10
- this.environment = new WebBrowserEnvironment();
11
- this.lifecycle = new WebBrowserSessionLifecycle();
12
- }
13
- }
@@ -1,31 +0,0 @@
1
- import ActionTypes from '../src/redux/ActionTypes';
2
- import ActionTypesInternal from '../src/redux/ActionTypesInternal';
3
-
4
- export function invokeLocationMiddleware(middleware, action) {
5
- let result;
6
-
7
- function next(nextAction) {
8
- result = nextAction;
9
- }
10
-
11
- middleware()(next)(action);
12
-
13
- return result;
14
- }
15
-
16
- export function transformInputLocationUsingMiddleware(middleware, location) {
17
- return invokeLocationMiddleware(middleware, {
18
- type: ActionTypes.NAVIGATE,
19
- payload: {
20
- operation: 'push',
21
- location,
22
- },
23
- }).payload.location;
24
- }
25
-
26
- export function transformOutputLocationUsingMiddleware(middleware, location) {
27
- return invokeLocationMiddleware(middleware, {
28
- type: ActionTypesInternal.INTERNAL_LOCATION_UPDATE,
29
- payload: location,
30
- }).payload;
31
- }
@@ -1,73 +0,0 @@
1
- import ActionTypes from '../../src/redux/ActionTypes';
2
- import Actions from '../../src/redux/Actions';
3
-
4
- describe('Actions', () => {
5
- it('#init should create an INIT action', () => {
6
- expect(Actions.init('/foo?bar=baz#qux')).to.eql({
7
- type: ActionTypes.INIT,
8
- payload: '/foo?bar=baz#qux',
9
- });
10
- });
11
-
12
- it('#push should create a PUSH action with location', () => {
13
- expect(Actions.push('/foo?bar=baz#qux')).to.eql({
14
- type: ActionTypes.PUSH,
15
- payload: '/foo?bar=baz#qux',
16
- });
17
-
18
- expect(
19
- Actions.push({
20
- pathname: '/foo',
21
- search: '?bar=baz',
22
- hash: '#qux',
23
- }),
24
- ).to.eql({
25
- type: ActionTypes.PUSH,
26
- payload: {
27
- pathname: '/foo',
28
- search: '?bar=baz',
29
- hash: '#qux',
30
- },
31
- });
32
- });
33
-
34
- it('#replace should create a REPLACE action with location', () => {
35
- expect(Actions.replace('/foo?bar=baz#qux')).to.eql({
36
- type: ActionTypes.REPLACE,
37
- payload: '/foo?bar=baz#qux',
38
- });
39
-
40
- expect(
41
- Actions.replace({
42
- pathname: '/foo',
43
- search: '?bar=baz',
44
- hash: '#qux',
45
- }),
46
- ).to.eql({
47
- type: ActionTypes.REPLACE,
48
- payload: {
49
- pathname: '/foo',
50
- search: '?bar=baz',
51
- hash: '#qux',
52
- },
53
- });
54
- });
55
-
56
- it('#go should create a SHIFT action with delta', () => {
57
- expect(Actions.shift(1)).to.eql({
58
- type: ActionTypes.SHIFT,
59
- payload: 1,
60
- });
61
-
62
- expect(Actions.shift(-1)).to.eql({
63
- type: ActionTypes.SHIFT,
64
- payload: -1,
65
- });
66
- });
67
-
68
- it('#stop should create a STOP action', () => {
69
- expect(Actions.stop()).to.eql({
70
- type: ActionTypes.STOP,
71
- });
72
- });
73
- });
@@ -1,13 +0,0 @@
1
- import ActionTypes from '../../src/redux/ActionTypes';
2
-
3
- describe('ActionTypes', () => {
4
- it('should have the correct exports', () => {
5
- expect(ActionTypes.INIT).to.exist();
6
- expect(ActionTypes.PUSH).to.exist();
7
- expect(ActionTypes.REPLACE).to.exist();
8
- expect(ActionTypes.NAVIGATE).to.exist();
9
- expect(ActionTypes.SHIFT).to.exist();
10
- expect(ActionTypes.UPDATE).to.exist();
11
- expect(ActionTypes.STOP).to.exist();
12
- });
13
- });
@@ -1,96 +0,0 @@
1
- import { applyMiddleware, createStore } from 'redux';
2
-
3
- import Actions from '../../src/redux/Actions';
4
- import createMiddlewares from '../../src/redux/createMiddlewares';
5
- import internalLocationReducer from '../../src/redux/internalLocationReducer';
6
- import InMemorySession from '../../src/session/InMemorySession';
7
-
8
- describe('createMiddlewares', () => {
9
- let store;
10
-
11
- beforeEach(() => {
12
- store = createStore(
13
- internalLocationReducer,
14
- applyMiddleware(
15
- ...createMiddlewares(new InMemorySession(), {
16
- _internalLocationReducer: true,
17
- }),
18
- ),
19
- );
20
- store.dispatch(Actions.init('/initial'));
21
- });
22
-
23
- afterEach(() => {
24
- store.dispatch(Actions.stop());
25
- });
26
-
27
- it('should support `push` and `shift` navigation actions', () => {
28
- store.dispatch(Actions.push('/new'));
29
- expect(store.getState()).to.include({
30
- pathname: '/new',
31
- index: 1,
32
- });
33
-
34
- store.dispatch(Actions.shift(-1));
35
- expect(store.getState()).to.include({
36
- pathname: '/initial',
37
- index: 0,
38
- });
39
-
40
- store.dispatch(Actions.shift(+1));
41
- expect(store.getState()).to.include({
42
- pathname: '/new',
43
- index: 1,
44
- });
45
- });
46
-
47
- it('should support `replace` navigation action', () => {
48
- store.dispatch(Actions.replace('/new'));
49
- expect(store.getState()).to.include({
50
- pathname: '/new',
51
- index: 0,
52
- });
53
- });
54
-
55
- it('should ignore other actions', () => {
56
- expect(
57
- store.dispatch({
58
- type: 'UNKNOWN',
59
- payload: { unknown: {} },
60
- }),
61
- ).to.eql({
62
- type: 'UNKNOWN',
63
- payload: { unknown: {} },
64
- });
65
- });
66
- });
67
-
68
- describe('createMiddlewares.basePath', () => {
69
- it('should support `basePath`', () => {
70
- const session = new InMemorySession();
71
-
72
- const store = createStore(
73
- internalLocationReducer,
74
- applyMiddleware(
75
- ...createMiddlewares(session, {
76
- basePath: '/base',
77
- _internalLocationReducer: true,
78
- }),
79
- ),
80
- );
81
-
82
- store.dispatch(Actions.init('/initial'));
83
-
84
- store.dispatch(Actions.push('/new'));
85
-
86
- // eslint-disable-next-line no-underscore-dangle
87
- expect(session._subscription._latest.pathname).to.equal('/base/new');
88
-
89
- expect(store.getState()).to.include({
90
- pathname: '/new',
91
- index: 1,
92
- });
93
-
94
- store.dispatch(Actions.stop());
95
- });
96
- });
@@ -1,10 +0,0 @@
1
- import * as exports from '../../src/redux';
2
-
3
- describe('redux', () => {
4
- it('should export top level correctly', () => {
5
- expect(exports.Actions).to.exist();
6
- expect(exports.ActionTypes).to.exist();
7
- expect(exports.createMiddlewares).to.exist();
8
- expect(exports.locationReducer).to.exist();
9
- });
10
- });
@@ -1,39 +0,0 @@
1
- import ActionTypes from '../../src/redux/ActionTypes';
2
- import locationReducer from '../../src/redux/locationReducer';
3
-
4
- describe('locationReducer', () => {
5
- const prevState = {
6
- operation: 'push',
7
- delta: 1,
8
- hash: '',
9
- index: 5,
10
- key: 'h0j8qq:4',
11
- pathname: '/new/path',
12
- query: {},
13
- search: '',
14
- };
15
-
16
- it('should handle UPDATE', () => {
17
- const newLocation = {
18
- key: 'h0j8qq:5',
19
- pathname: '/foo',
20
- query: {
21
- bar: 'baz',
22
- },
23
- search: '?bar=baz',
24
- hash: '#qux',
25
- };
26
- const action = {
27
- type: ActionTypes.UPDATE,
28
- payload: newLocation,
29
- };
30
- expect(locationReducer(prevState, action)).to.eql(newLocation);
31
- });
32
-
33
- it('should not handle unknown action', () => {
34
- const unknownAction = {
35
- type: 'UNKNOWN',
36
- };
37
- expect(locationReducer(prevState, unknownAction)).to.equal(prevState);
38
- });
39
- });
@@ -1,40 +0,0 @@
1
- import createAddInputLocationBasePathMiddleware from '../../../src/redux/middleware/createAddInputLocationBasePathMiddleware';
2
- import { transformInputLocationUsingMiddleware } from '../../middlewareTestUtil';
3
-
4
- describe('createAddInputLocationBasePathMiddleware', () => {
5
- [
6
- ['/base', 'generic `basePath`'],
7
- ['/base/', '`basePath` with a trailing slash'],
8
- ].forEach(([basePath, title]) => {
9
- describe(title, () => {
10
- const addInputLocationBasePathMiddleware =
11
- createAddInputLocationBasePathMiddleware(basePath);
12
-
13
- it('should prepend `basePath` to `location.pathname` on input locations', () => {
14
- expect(
15
- transformInputLocationUsingMiddleware(
16
- addInputLocationBasePathMiddleware,
17
- { pathname: '/path' },
18
- ),
19
- ).to.eql({
20
- pathname: '/base/path',
21
- });
22
- });
23
- });
24
- });
25
-
26
- describe('No `basePath` specified', () => {
27
- const addInputLocationBasePathMiddleware =
28
- createAddInputLocationBasePathMiddleware('/');
29
-
30
- it('should not modify `location.pathname` of input locations', () => {
31
- const location = { pathname: '/path' };
32
- expect(
33
- transformInputLocationUsingMiddleware(
34
- addInputLocationBasePathMiddleware,
35
- location,
36
- ),
37
- ).to.equal(location);
38
- });
39
- });
40
- });
@@ -1,51 +0,0 @@
1
- import createRemoveOutputLocationBasePathMiddleware from '../../../src/redux/middleware/createRemoveOutputLocationBasePathMiddleware';
2
- import { transformOutputLocationUsingMiddleware } from '../../middlewareTestUtil';
3
-
4
- describe('createRemoveOutputLocationBasePathMiddleware', () => {
5
- [
6
- ['/base', 'generic `basePath`'],
7
- ['/base/', '`basePath` with a trailing slash'],
8
- ].forEach(([basePath, title]) => {
9
- describe(title, () => {
10
- const removeOutputLocationBasePathMiddleware =
11
- createRemoveOutputLocationBasePathMiddleware(basePath);
12
-
13
- it('should strip `basePath` from `location.pathname` on subscription locations', () => {
14
- expect(
15
- transformOutputLocationUsingMiddleware(
16
- removeOutputLocationBasePathMiddleware,
17
- { pathname: '/base/path' },
18
- ),
19
- ).to.eql({
20
- pathname: '/path',
21
- });
22
- });
23
-
24
- it('should handle unrecognized paths on subscription locations', () => {
25
- expect(
26
- transformOutputLocationUsingMiddleware(
27
- removeOutputLocationBasePathMiddleware,
28
- { pathname: '/path' },
29
- ),
30
- ).to.eql({
31
- pathname: '/path',
32
- });
33
- });
34
- });
35
- });
36
-
37
- describe('No `basePath` specified', () => {
38
- const removeOutputLocationBasePathMiddleware =
39
- createRemoveOutputLocationBasePathMiddleware('/');
40
-
41
- it('should not modify `location.pathname` of subscription locations', () => {
42
- const location = { pathname: '/path' };
43
- expect(
44
- transformOutputLocationUsingMiddleware(
45
- removeOutputLocationBasePathMiddleware,
46
- location,
47
- ),
48
- ).to.equal(location);
49
- });
50
- });
51
- });
@@ -1,78 +0,0 @@
1
- import ActionTypes from '../../../src/redux/ActionTypes';
2
- import navigationOperationMiddleware from '../../../src/redux/middleware/navigationOperationMiddleware';
3
-
4
- describe('navigationOperationMiddleware', () => {
5
- let next;
6
- let dispatch;
7
- beforeEach(() => {
8
- next = sinon.spy();
9
- dispatch = navigationOperationMiddleware()(next);
10
- });
11
-
12
- it('should change `type` of PUSH action', () => {
13
- dispatch({
14
- type: ActionTypes.PUSH,
15
- payload: {
16
- pathname: '/foo',
17
- search: '?bar=baz',
18
- hash: '#qux',
19
- },
20
- });
21
-
22
- expect(next).to.be.calledWith({
23
- type: ActionTypes.NAVIGATE,
24
- payload: {
25
- operation: 'push',
26
- location: {
27
- pathname: '/foo',
28
- search: '?bar=baz',
29
- hash: '#qux',
30
- },
31
- },
32
- });
33
- });
34
-
35
- it('should change `type` of REPLACE action', () => {
36
- dispatch({
37
- type: ActionTypes.REPLACE,
38
- payload: {
39
- pathname: '/foo',
40
- search: '?bar=baz',
41
- hash: '#qux',
42
- },
43
- });
44
-
45
- expect(next).to.be.calledWith({
46
- type: ActionTypes.NAVIGATE,
47
- payload: {
48
- operation: 'replace',
49
- location: {
50
- pathname: '/foo',
51
- search: '?bar=baz',
52
- hash: '#qux',
53
- },
54
- },
55
- });
56
- });
57
-
58
- it('should not affect other action', () => {
59
- const UNKNOWN = 'UNKNOWN';
60
- dispatch({
61
- type: UNKNOWN,
62
- payload: {
63
- pathname: '/foo',
64
- search: '?bar=baz',
65
- hash: '#qux',
66
- },
67
- });
68
-
69
- expect(next).to.be.calledWith({
70
- type: UNKNOWN,
71
- payload: {
72
- pathname: '/foo',
73
- search: '?bar=baz',
74
- hash: '#qux',
75
- },
76
- });
77
- });
78
- });