one 1.1.473 → 1.1.475

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 (245) hide show
  1. package/dist/cjs/Root.cjs +5 -1
  2. package/dist/cjs/Root.js +2 -2
  3. package/dist/cjs/Root.js.map +1 -1
  4. package/dist/cjs/Root.native.js +5 -2
  5. package/dist/cjs/Root.native.js.map +2 -2
  6. package/dist/cjs/createApp.cjs +2 -0
  7. package/dist/cjs/createApp.js +16 -2
  8. package/dist/cjs/createApp.js.map +1 -1
  9. package/dist/cjs/createApp.native.js +1 -0
  10. package/dist/cjs/createApp.native.js.map +2 -2
  11. package/dist/cjs/fork/__tests__/getPathFromState.test.cjs +1440 -0
  12. package/dist/cjs/fork/__tests__/getPathFromState.test.js +1559 -0
  13. package/dist/cjs/fork/__tests__/getPathFromState.test.js.map +6 -0
  14. package/dist/cjs/fork/__tests__/getPathFromState.test.native.js +1726 -0
  15. package/dist/cjs/fork/__tests__/getPathFromState.test.native.js.map +6 -0
  16. package/dist/cjs/fork/__tests__/getStateFromPath.test.cjs +2565 -0
  17. package/dist/cjs/fork/__tests__/getStateFromPath.test.js +2702 -0
  18. package/dist/cjs/fork/__tests__/getStateFromPath.test.js.map +6 -0
  19. package/dist/cjs/fork/__tests__/getStateFromPath.test.native.js +2861 -0
  20. package/dist/cjs/fork/__tests__/getStateFromPath.test.native.js.map +6 -0
  21. package/dist/cjs/fork/getPathFromState.cjs +2 -1
  22. package/dist/cjs/fork/getPathFromState.js +1 -1
  23. package/dist/cjs/fork/getPathFromState.js.map +1 -1
  24. package/dist/cjs/fork/getPathFromState.native.js +10 -5
  25. package/dist/cjs/fork/getPathFromState.native.js.map +1 -1
  26. package/dist/cjs/fork/getPathFromState.test.cjs +113 -0
  27. package/dist/cjs/fork/getPathFromState.test.js +122 -0
  28. package/dist/cjs/fork/getPathFromState.test.js.map +6 -0
  29. package/dist/cjs/fork/getPathFromState.test.native.js +135 -0
  30. package/dist/cjs/fork/getPathFromState.test.native.js.map +6 -0
  31. package/dist/cjs/fork/getStateFromPath.test.cjs +229 -0
  32. package/dist/cjs/fork/getStateFromPath.test.js +290 -0
  33. package/dist/cjs/fork/getStateFromPath.test.js.map +6 -0
  34. package/dist/cjs/fork/getStateFromPath.test.native.js +374 -0
  35. package/dist/cjs/fork/getStateFromPath.test.native.js.map +6 -0
  36. package/dist/cjs/render.cjs +1 -1
  37. package/dist/cjs/render.js +1 -1
  38. package/dist/cjs/render.js.map +1 -1
  39. package/dist/cjs/router/FlagsContext.cjs +27 -0
  40. package/dist/cjs/router/FlagsContext.js +22 -0
  41. package/dist/cjs/router/FlagsContext.js.map +6 -0
  42. package/dist/cjs/router/FlagsContext.native.js +26 -0
  43. package/dist/cjs/router/FlagsContext.native.js.map +6 -0
  44. package/dist/cjs/router/getRoutes.cjs +11 -1
  45. package/dist/cjs/router/getRoutes.js +11 -1
  46. package/dist/cjs/router/getRoutes.js.map +1 -1
  47. package/dist/cjs/router/getRoutes.native.js +11 -1
  48. package/dist/cjs/router/getRoutes.native.js.map +2 -2
  49. package/dist/cjs/router/matchers.test.cjs +38 -0
  50. package/dist/cjs/router/matchers.test.js +42 -0
  51. package/dist/cjs/router/matchers.test.js.map +6 -0
  52. package/dist/cjs/router/matchers.test.native.js +39 -0
  53. package/dist/cjs/router/matchers.test.native.js.map +6 -0
  54. package/dist/cjs/router/router.cjs +3 -35
  55. package/dist/cjs/router/router.js +2 -26
  56. package/dist/cjs/router/router.js.map +1 -1
  57. package/dist/cjs/router/router.native.js +2 -33
  58. package/dist/cjs/router/router.native.js.map +2 -2
  59. package/dist/cjs/router/utils/getNavigateAction.cjs +61 -0
  60. package/dist/cjs/router/utils/getNavigateAction.js +46 -0
  61. package/dist/cjs/router/utils/getNavigateAction.js.map +6 -0
  62. package/dist/cjs/router/utils/getNavigateAction.native.js +58 -0
  63. package/dist/cjs/router/utils/getNavigateAction.native.js.map +6 -0
  64. package/dist/cjs/router/utils/getNavigateAction.test.cjs +259 -0
  65. package/dist/cjs/router/utils/getNavigateAction.test.js +295 -0
  66. package/dist/cjs/router/utils/getNavigateAction.test.js.map +6 -0
  67. package/dist/cjs/router/utils/getNavigateAction.test.native.js +330 -0
  68. package/dist/cjs/router/utils/getNavigateAction.test.native.js.map +6 -0
  69. package/dist/cjs/testing-utils.cjs +63 -0
  70. package/dist/cjs/testing-utils.js +55 -0
  71. package/dist/cjs/testing-utils.js.map +6 -0
  72. package/dist/cjs/testing-utils.native.js +79 -0
  73. package/dist/cjs/testing-utils.native.js.map +6 -0
  74. package/dist/cjs/views/Navigator.cjs +8 -1
  75. package/dist/cjs/views/Navigator.js +25 -11
  76. package/dist/cjs/views/Navigator.js.map +1 -1
  77. package/dist/cjs/views/Navigator.native.js +7 -4
  78. package/dist/cjs/views/Navigator.native.js.map +2 -2
  79. package/dist/cjs/vite/one.cjs +6 -1
  80. package/dist/cjs/vite/one.js +6 -1
  81. package/dist/cjs/vite/one.js.map +1 -1
  82. package/dist/cjs/vite/one.native.js +7 -2
  83. package/dist/cjs/vite/one.native.js.map +2 -2
  84. package/dist/cjs/vite/plugins/virtualEntryPlugin.cjs +2 -0
  85. package/dist/cjs/vite/plugins/virtualEntryPlugin.js +2 -0
  86. package/dist/cjs/vite/plugins/virtualEntryPlugin.js.map +1 -1
  87. package/dist/cjs/vite/plugins/virtualEntryPlugin.native.js +2 -0
  88. package/dist/cjs/vite/plugins/virtualEntryPlugin.native.js.map +2 -2
  89. package/dist/esm/Root.js +2 -1
  90. package/dist/esm/Root.js.map +1 -1
  91. package/dist/esm/Root.mjs +5 -1
  92. package/dist/esm/Root.mjs.map +1 -1
  93. package/dist/esm/Root.native.js +5 -1
  94. package/dist/esm/Root.native.js.map +1 -1
  95. package/dist/esm/createApp.js +16 -2
  96. package/dist/esm/createApp.js.map +1 -1
  97. package/dist/esm/createApp.mjs +2 -0
  98. package/dist/esm/createApp.mjs.map +1 -1
  99. package/dist/esm/createApp.native.js +1 -0
  100. package/dist/esm/createApp.native.js.map +1 -1
  101. package/dist/esm/fork/__tests__/getPathFromState.test.js +1561 -0
  102. package/dist/esm/fork/__tests__/getPathFromState.test.js.map +6 -0
  103. package/dist/esm/fork/__tests__/getPathFromState.test.mjs +1441 -0
  104. package/dist/esm/fork/__tests__/getPathFromState.test.mjs.map +1 -0
  105. package/dist/esm/fork/__tests__/getPathFromState.test.native.js +1580 -0
  106. package/dist/esm/fork/__tests__/getPathFromState.test.native.js.map +1 -0
  107. package/dist/esm/fork/__tests__/getStateFromPath.test.js +2706 -0
  108. package/dist/esm/fork/__tests__/getStateFromPath.test.js.map +6 -0
  109. package/dist/esm/fork/__tests__/getStateFromPath.test.mjs +2566 -0
  110. package/dist/esm/fork/__tests__/getStateFromPath.test.mjs.map +1 -0
  111. package/dist/esm/fork/__tests__/getStateFromPath.test.native.js +2636 -0
  112. package/dist/esm/fork/__tests__/getStateFromPath.test.native.js.map +1 -0
  113. package/dist/esm/fork/getPathFromState.js +1 -1
  114. package/dist/esm/fork/getPathFromState.js.map +1 -1
  115. package/dist/esm/fork/getPathFromState.mjs +2 -1
  116. package/dist/esm/fork/getPathFromState.mjs.map +1 -1
  117. package/dist/esm/fork/getPathFromState.native.js +9 -5
  118. package/dist/esm/fork/getPathFromState.native.js.map +1 -1
  119. package/dist/esm/fork/getPathFromState.test.js +123 -0
  120. package/dist/esm/fork/getPathFromState.test.js.map +6 -0
  121. package/dist/esm/fork/getPathFromState.test.mjs +114 -0
  122. package/dist/esm/fork/getPathFromState.test.mjs.map +1 -0
  123. package/dist/esm/fork/getPathFromState.test.native.js +122 -0
  124. package/dist/esm/fork/getPathFromState.test.native.js.map +1 -0
  125. package/dist/esm/fork/getStateFromPath.test.js +294 -0
  126. package/dist/esm/fork/getStateFromPath.test.js.map +6 -0
  127. package/dist/esm/fork/getStateFromPath.test.mjs +230 -0
  128. package/dist/esm/fork/getStateFromPath.test.mjs.map +1 -0
  129. package/dist/esm/fork/getStateFromPath.test.native.js +233 -0
  130. package/dist/esm/fork/getStateFromPath.test.native.js.map +1 -0
  131. package/dist/esm/render.js +1 -1
  132. package/dist/esm/render.js.map +1 -1
  133. package/dist/esm/render.mjs +1 -1
  134. package/dist/esm/render.mjs.map +1 -1
  135. package/dist/esm/router/FlagsContext.js +6 -0
  136. package/dist/esm/router/FlagsContext.js.map +6 -0
  137. package/dist/esm/router/FlagsContext.mjs +4 -0
  138. package/dist/esm/router/FlagsContext.mjs.map +1 -0
  139. package/dist/esm/router/FlagsContext.native.js +4 -0
  140. package/dist/esm/router/FlagsContext.native.js.map +1 -0
  141. package/dist/esm/router/getRoutes.js +11 -1
  142. package/dist/esm/router/getRoutes.js.map +1 -1
  143. package/dist/esm/router/getRoutes.mjs +11 -1
  144. package/dist/esm/router/getRoutes.mjs.map +1 -1
  145. package/dist/esm/router/getRoutes.native.js +11 -1
  146. package/dist/esm/router/getRoutes.native.js.map +1 -1
  147. package/dist/esm/router/matchers.test.js +50 -0
  148. package/dist/esm/router/matchers.test.js.map +6 -0
  149. package/dist/esm/router/matchers.test.mjs +39 -0
  150. package/dist/esm/router/matchers.test.mjs.map +1 -0
  151. package/dist/esm/router/matchers.test.native.js +39 -0
  152. package/dist/esm/router/matchers.test.native.js.map +1 -0
  153. package/dist/esm/router/router.js +1 -26
  154. package/dist/esm/router/router.js.map +1 -1
  155. package/dist/esm/router/router.mjs +1 -33
  156. package/dist/esm/router/router.mjs.map +1 -1
  157. package/dist/esm/router/router.native.js +1 -37
  158. package/dist/esm/router/router.native.js.map +1 -1
  159. package/dist/esm/router/utils/getNavigateAction.js +32 -0
  160. package/dist/esm/router/utils/getNavigateAction.js.map +6 -0
  161. package/dist/esm/router/utils/getNavigateAction.mjs +38 -0
  162. package/dist/esm/router/utils/getNavigateAction.mjs.map +1 -0
  163. package/dist/esm/router/utils/getNavigateAction.native.js +42 -0
  164. package/dist/esm/router/utils/getNavigateAction.native.js.map +1 -0
  165. package/dist/esm/router/utils/getNavigateAction.test.js +296 -0
  166. package/dist/esm/router/utils/getNavigateAction.test.js.map +6 -0
  167. package/dist/esm/router/utils/getNavigateAction.test.mjs +260 -0
  168. package/dist/esm/router/utils/getNavigateAction.test.mjs.map +1 -0
  169. package/dist/esm/router/utils/getNavigateAction.test.native.js +273 -0
  170. package/dist/esm/router/utils/getNavigateAction.test.native.js.map +1 -0
  171. package/dist/esm/testing-utils.js +33 -0
  172. package/dist/esm/testing-utils.js.map +6 -0
  173. package/dist/esm/testing-utils.mjs +27 -0
  174. package/dist/esm/testing-utils.mjs.map +1 -0
  175. package/dist/esm/testing-utils.native.js +38 -0
  176. package/dist/esm/testing-utils.native.js.map +1 -0
  177. package/dist/esm/views/Navigator.js +29 -11
  178. package/dist/esm/views/Navigator.js.map +1 -1
  179. package/dist/esm/views/Navigator.mjs +8 -1
  180. package/dist/esm/views/Navigator.mjs.map +1 -1
  181. package/dist/esm/views/Navigator.native.js +8 -2
  182. package/dist/esm/views/Navigator.native.js.map +1 -1
  183. package/dist/esm/vite/one.js +6 -1
  184. package/dist/esm/vite/one.js.map +1 -1
  185. package/dist/esm/vite/one.mjs +6 -1
  186. package/dist/esm/vite/one.mjs.map +1 -1
  187. package/dist/esm/vite/one.native.js +9 -2
  188. package/dist/esm/vite/one.native.js.map +1 -1
  189. package/dist/esm/vite/plugins/virtualEntryPlugin.js +2 -0
  190. package/dist/esm/vite/plugins/virtualEntryPlugin.js.map +1 -1
  191. package/dist/esm/vite/plugins/virtualEntryPlugin.mjs +2 -0
  192. package/dist/esm/vite/plugins/virtualEntryPlugin.mjs.map +1 -1
  193. package/dist/esm/vite/plugins/virtualEntryPlugin.native.js +2 -0
  194. package/dist/esm/vite/plugins/virtualEntryPlugin.native.js.map +1 -1
  195. package/package.json +13 -10
  196. package/src/Root.tsx +12 -2
  197. package/src/createApp.native.tsx +8 -2
  198. package/src/createApp.tsx +18 -3
  199. package/src/fork/__tests__/README.md +8 -0
  200. package/src/fork/__tests__/getPathFromState.test.tsx +1809 -0
  201. package/src/fork/__tests__/getStateFromPath.test.tsx +3188 -0
  202. package/src/fork/getPathFromState.test.ts +146 -0
  203. package/src/fork/getPathFromState.ts +1 -1
  204. package/src/fork/getStateFromPath.test.ts +345 -0
  205. package/src/render.tsx +3 -3
  206. package/src/router/FlagsContext.ts +4 -0
  207. package/src/router/getRoutes.ts +14 -2
  208. package/src/router/matchers.test.ts +120 -0
  209. package/src/router/router.ts +1 -113
  210. package/src/router/utils/getNavigateAction.test.ts +334 -0
  211. package/src/router/utils/getNavigateAction.ts +120 -0
  212. package/src/testing-utils.ts +56 -0
  213. package/src/views/Navigator.tsx +34 -10
  214. package/src/vite/one.ts +5 -0
  215. package/src/vite/plugins/virtualEntryPlugin.ts +4 -1
  216. package/src/vite/types.ts +18 -0
  217. package/types/Root.d.ts +1 -0
  218. package/types/Root.d.ts.map +1 -1
  219. package/types/createApp.d.ts +2 -0
  220. package/types/createApp.d.ts.map +1 -1
  221. package/types/createApp.native.d.ts +2 -0
  222. package/types/createApp.native.d.ts.map +1 -1
  223. package/types/fork/getPathFromState.test.d.ts +2 -0
  224. package/types/fork/getPathFromState.test.d.ts.map +1 -0
  225. package/types/fork/getStateFromPath.test.d.ts +2 -0
  226. package/types/fork/getStateFromPath.test.d.ts.map +1 -0
  227. package/types/router/FlagsContext.d.ts +3 -0
  228. package/types/router/FlagsContext.d.ts.map +1 -0
  229. package/types/router/getRoutes.d.ts.map +1 -1
  230. package/types/router/matchers.test.d.ts +2 -0
  231. package/types/router/matchers.test.d.ts.map +1 -0
  232. package/types/router/router.d.ts.map +1 -1
  233. package/types/router/utils/getNavigateAction.d.ts +17 -0
  234. package/types/router/utils/getNavigateAction.d.ts.map +1 -0
  235. package/types/router/utils/getNavigateAction.test.d.ts +2 -0
  236. package/types/router/utils/getNavigateAction.test.d.ts.map +1 -0
  237. package/types/testing-utils.d.ts +26 -0
  238. package/types/testing-utils.d.ts.map +1 -0
  239. package/types/views/Navigator.d.ts +1 -1
  240. package/types/views/Navigator.d.ts.map +1 -1
  241. package/types/vite/one.d.ts.map +1 -1
  242. package/types/vite/plugins/virtualEntryPlugin.d.ts +2 -0
  243. package/types/vite/plugins/virtualEntryPlugin.d.ts.map +1 -1
  244. package/types/vite/types.d.ts +16 -0
  245. package/types/vite/types.d.ts.map +1 -1
@@ -0,0 +1,2706 @@
1
+ import { expect, test } from "vitest";
2
+ import { produce } from "immer";
3
+ import { findFocusedRoute } from "../findFocusedRoute";
4
+ import { getPathFromState } from "../getPathFromState";
5
+ import { getStateFromPath } from "../getStateFromPath";
6
+ const changePath = (state, path) => produce(state, (draftState) => {
7
+ const route = findFocusedRoute(draftState);
8
+ route.path = path;
9
+ });
10
+ test("returns undefined for invalid path", () => {
11
+ expect(getStateFromPath("//")).toBeUndefined();
12
+ });
13
+ test.skip("converts path string to initial state", () => {
14
+ const path = "foo/bar/baz%20qux?author=jane%20%26%20co&valid=true", state = {
15
+ routes: [
16
+ {
17
+ name: "foo",
18
+ state: {
19
+ routes: [
20
+ {
21
+ name: "bar",
22
+ state: {
23
+ routes: [
24
+ {
25
+ name: "baz qux",
26
+ params: { author: "jane & co", valid: "true" },
27
+ path
28
+ }
29
+ ]
30
+ }
31
+ }
32
+ ]
33
+ }
34
+ }
35
+ ]
36
+ };
37
+ expect(getStateFromPath(path)).toEqual(state), expect(getStateFromPath(getPathFromState(state))).toEqual(
38
+ changePath(state, "/foo/bar/baz%20qux?author=jane%20%26%20co&valid=true")
39
+ );
40
+ });
41
+ test.skip("decodes encoded params in path", () => {
42
+ const path = "/foo/bar/bar_%23_foo", config = {
43
+ screens: {
44
+ Foo: {
45
+ path: "foo",
46
+ screens: {
47
+ Bar: {
48
+ path: "/bar/:id"
49
+ }
50
+ }
51
+ }
52
+ }
53
+ }, state = {
54
+ routes: [
55
+ {
56
+ name: "Foo",
57
+ state: {
58
+ routes: [
59
+ {
60
+ name: "Bar",
61
+ params: { id: "bar_#_foo" },
62
+ path
63
+ }
64
+ ]
65
+ }
66
+ }
67
+ ]
68
+ };
69
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
70
+ getPathFromState(getStateFromPath(path, config), config)
71
+ ).toEqual(path);
72
+ });
73
+ test.skip("decodes encoded params in path that have encoded /", () => {
74
+ const path = "/foo/bar/bar_%2F_foo", config = {
75
+ screens: {
76
+ Foo: {
77
+ path: "foo",
78
+ screens: {
79
+ Bar: {
80
+ path: "/bar/:id"
81
+ }
82
+ }
83
+ }
84
+ }
85
+ }, state = {
86
+ routes: [
87
+ {
88
+ name: "Foo",
89
+ state: {
90
+ routes: [
91
+ {
92
+ name: "Bar",
93
+ params: { id: "bar_/_foo" },
94
+ path
95
+ }
96
+ ]
97
+ }
98
+ }
99
+ ]
100
+ };
101
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
102
+ getPathFromState(getStateFromPath(path, config), config)
103
+ ).toEqual(path);
104
+ });
105
+ test.skip("converts path string to initial state with config", () => {
106
+ const path = "/foo/bar/sweet/apple/baz/jane?count=10&answer=42&valid=true", config = {
107
+ screens: {
108
+ Foo: {
109
+ path: "foo",
110
+ screens: {
111
+ Bar: {
112
+ path: "bar/:type/:fruit",
113
+ screens: {
114
+ Baz: {
115
+ path: "baz/:author",
116
+ parse: {
117
+ author: (author) => author.replace(/^\w/, (c) => c.toUpperCase()),
118
+ count: Number,
119
+ valid: Boolean
120
+ },
121
+ stringify: {
122
+ author: (author) => author.toLowerCase()
123
+ }
124
+ }
125
+ }
126
+ }
127
+ }
128
+ }
129
+ }
130
+ }, state = {
131
+ routes: [
132
+ {
133
+ name: "Foo",
134
+ state: {
135
+ routes: [
136
+ {
137
+ name: "Bar",
138
+ params: { fruit: "apple", type: "sweet" },
139
+ state: {
140
+ routes: [
141
+ {
142
+ name: "Baz",
143
+ params: {
144
+ author: "Jane",
145
+ count: 10,
146
+ answer: "42",
147
+ valid: !0
148
+ },
149
+ path
150
+ }
151
+ ]
152
+ }
153
+ }
154
+ ]
155
+ }
156
+ }
157
+ ]
158
+ };
159
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
160
+ getStateFromPath(getPathFromState(state, config), config)
161
+ ).toEqual(state);
162
+ });
163
+ test("handles leading slash when converting", () => {
164
+ const path = "/foo/bar/?count=42";
165
+ expect(getStateFromPath(path)).toEqual({
166
+ routes: [
167
+ {
168
+ name: "foo",
169
+ state: {
170
+ routes: [
171
+ {
172
+ name: "bar",
173
+ params: { count: "42" },
174
+ path
175
+ }
176
+ ]
177
+ }
178
+ }
179
+ ]
180
+ });
181
+ });
182
+ test("handles ending slash when converting", () => {
183
+ const path = "foo/bar/?count=42";
184
+ expect(getStateFromPath(path)).toEqual({
185
+ routes: [
186
+ {
187
+ name: "foo",
188
+ state: {
189
+ routes: [
190
+ {
191
+ name: "bar",
192
+ params: { count: "42" },
193
+ path
194
+ }
195
+ ]
196
+ }
197
+ }
198
+ ]
199
+ });
200
+ });
201
+ test("handles route without param", () => {
202
+ const path = "foo/bar", state = {
203
+ routes: [
204
+ {
205
+ name: "foo",
206
+ state: {
207
+ routes: [{ name: "bar", path }]
208
+ }
209
+ }
210
+ ]
211
+ };
212
+ expect(getStateFromPath(path)).toEqual(state), expect(getStateFromPath(getPathFromState(state))).toEqual(
213
+ changePath(state, "/foo/bar")
214
+ );
215
+ });
216
+ test.skip("converts path string to initial state with config with nested screens", () => {
217
+ const path = "/foe/bar/sweet/apple/baz/jane?count=10&answer=42&valid=true", config = {
218
+ screens: {
219
+ Foo: {
220
+ path: "foo",
221
+ screens: {
222
+ Foe: {
223
+ path: "foe",
224
+ exact: !0,
225
+ screens: {
226
+ Bar: {
227
+ path: "bar/:type/:fruit",
228
+ screens: {
229
+ Baz: {
230
+ path: "baz/:author",
231
+ parse: {
232
+ author: (author) => author.replace(/^\w/, (c) => c.toUpperCase()),
233
+ count: Number,
234
+ valid: Boolean
235
+ },
236
+ stringify: {
237
+ author: (author) => author.toLowerCase()
238
+ }
239
+ }
240
+ }
241
+ }
242
+ }
243
+ }
244
+ }
245
+ }
246
+ }
247
+ }, state = {
248
+ routes: [
249
+ {
250
+ name: "Foo",
251
+ state: {
252
+ routes: [
253
+ {
254
+ name: "Foe",
255
+ state: {
256
+ routes: [
257
+ {
258
+ name: "Bar",
259
+ params: { fruit: "apple", type: "sweet" },
260
+ state: {
261
+ routes: [
262
+ {
263
+ name: "Baz",
264
+ params: {
265
+ author: "Jane",
266
+ count: 10,
267
+ answer: "42",
268
+ valid: !0
269
+ },
270
+ path
271
+ }
272
+ ]
273
+ }
274
+ }
275
+ ]
276
+ }
277
+ }
278
+ ]
279
+ }
280
+ }
281
+ ]
282
+ };
283
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
284
+ getStateFromPath(getPathFromState(state, config), config)
285
+ ).toEqual(state);
286
+ });
287
+ test.skip("converts path string to initial state with config with nested screens and unused parse functions", () => {
288
+ const path = "/foe/baz/jane?count=10&answer=42&valid=true", config = {
289
+ screens: {
290
+ Foo: {
291
+ path: "foo",
292
+ screens: {
293
+ Foe: {
294
+ path: "foe",
295
+ exact: !0,
296
+ screens: {
297
+ Baz: {
298
+ path: "baz/:author",
299
+ parse: {
300
+ author: (author) => author.replace(/^\w/, (c) => c.toUpperCase()),
301
+ count: Number,
302
+ valid: Boolean,
303
+ id: Boolean
304
+ }
305
+ }
306
+ }
307
+ }
308
+ }
309
+ }
310
+ }
311
+ }, state = {
312
+ routes: [
313
+ {
314
+ name: "Foo",
315
+ state: {
316
+ routes: [
317
+ {
318
+ name: "Foe",
319
+ state: {
320
+ routes: [
321
+ {
322
+ name: "Baz",
323
+ params: {
324
+ author: "Jane",
325
+ count: 10,
326
+ answer: "42",
327
+ valid: !0
328
+ },
329
+ path
330
+ }
331
+ ]
332
+ }
333
+ }
334
+ ]
335
+ }
336
+ }
337
+ ]
338
+ };
339
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
340
+ getStateFromPath(getPathFromState(state, config), config)
341
+ ).toEqual(changePath(state, "/foe/baz/Jane?count=10&answer=42&valid=true"));
342
+ });
343
+ test.skip("handles nested object with unused configs and with parse in it", () => {
344
+ const path = "/bar/sweet/apple/foe/bis/jane?count=10&answer=42&valid=true", config = {
345
+ screens: {
346
+ Bar: {
347
+ path: "bar/:type/:fruit",
348
+ screens: {
349
+ Foo: {
350
+ screens: {
351
+ Foe: {
352
+ path: "foe",
353
+ screens: {
354
+ Baz: {
355
+ screens: {
356
+ Bos: {
357
+ path: "bos",
358
+ exact: !0
359
+ },
360
+ Bis: {
361
+ path: "bis/:author",
362
+ stringify: {
363
+ author: (author) => author.replace(/^\w/, (c) => c.toLowerCase())
364
+ },
365
+ parse: {
366
+ author: (author) => author.replace(/^\w/, (c) => c.toUpperCase()),
367
+ count: Number,
368
+ valid: Boolean
369
+ }
370
+ }
371
+ }
372
+ }
373
+ }
374
+ }
375
+ }
376
+ }
377
+ }
378
+ }
379
+ }
380
+ }, state = {
381
+ routes: [
382
+ {
383
+ name: "Bar",
384
+ params: { fruit: "apple", type: "sweet" },
385
+ state: {
386
+ routes: [
387
+ {
388
+ name: "Foo",
389
+ state: {
390
+ routes: [
391
+ {
392
+ name: "Foe",
393
+ state: {
394
+ routes: [
395
+ {
396
+ name: "Baz",
397
+ state: {
398
+ routes: [
399
+ {
400
+ name: "Bis",
401
+ params: {
402
+ author: "Jane",
403
+ count: 10,
404
+ answer: "42",
405
+ valid: !0
406
+ },
407
+ path
408
+ }
409
+ ]
410
+ }
411
+ }
412
+ ]
413
+ }
414
+ }
415
+ ]
416
+ }
417
+ }
418
+ ]
419
+ }
420
+ }
421
+ ]
422
+ };
423
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
424
+ getStateFromPath(getPathFromState(state, config), config)
425
+ ).toEqual(state);
426
+ });
427
+ test("handles parse in nested object for second route depth", () => {
428
+ const path = "/baz", config = {
429
+ screens: {
430
+ Foo: {
431
+ path: "foo",
432
+ screens: {
433
+ Foe: {
434
+ path: "foe",
435
+ exact: !0
436
+ },
437
+ Bar: {
438
+ path: "bar",
439
+ exact: !0,
440
+ screens: {
441
+ Baz: {
442
+ path: "baz",
443
+ exact: !0
444
+ }
445
+ }
446
+ }
447
+ }
448
+ }
449
+ }
450
+ }, state = {
451
+ routes: [
452
+ {
453
+ name: "Foo",
454
+ state: {
455
+ routes: [
456
+ {
457
+ name: "Bar",
458
+ state: {
459
+ routes: [{ name: "Baz", path }]
460
+ }
461
+ }
462
+ ]
463
+ }
464
+ }
465
+ ]
466
+ };
467
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
468
+ getStateFromPath(getPathFromState(state, config), config)
469
+ ).toEqual(state);
470
+ });
471
+ test("handles parse in nested object for second route depth and and path and parse in roots", () => {
472
+ const path = "/baz", config = {
473
+ screens: {
474
+ Foo: {
475
+ path: "foo/:id",
476
+ parse: {
477
+ id: Number
478
+ },
479
+ stringify: {
480
+ id: (id) => `id=${id}`
481
+ },
482
+ screens: {
483
+ Foe: "foe",
484
+ Bar: {
485
+ screens: {
486
+ Baz: {
487
+ path: "baz",
488
+ exact: !0
489
+ }
490
+ }
491
+ }
492
+ }
493
+ }
494
+ }
495
+ }, state = {
496
+ routes: [
497
+ {
498
+ name: "Foo",
499
+ state: {
500
+ routes: [
501
+ {
502
+ name: "Bar",
503
+ state: {
504
+ routes: [{ name: "Baz", path }]
505
+ }
506
+ }
507
+ ]
508
+ }
509
+ }
510
+ ]
511
+ };
512
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
513
+ getStateFromPath(getPathFromState(state, config), config)
514
+ ).toEqual(state);
515
+ });
516
+ test.skip("handles path at top level", () => {
517
+ const path = "/foo/fruits/apple", config = {
518
+ path: "foo",
519
+ screens: {
520
+ Foo: {
521
+ screens: {
522
+ Fruits: "fruits/:fruit"
523
+ }
524
+ }
525
+ }
526
+ }, state = {
527
+ routes: [
528
+ {
529
+ name: "Foo",
530
+ state: {
531
+ routes: [
532
+ {
533
+ name: "Fruits",
534
+ params: { fruit: "apple" },
535
+ path
536
+ }
537
+ ]
538
+ }
539
+ }
540
+ ]
541
+ };
542
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
543
+ getStateFromPath(getPathFromState(state, config), config)
544
+ ).toEqual(state);
545
+ });
546
+ test("handles initialRouteName at top level", () => {
547
+ const path = "/baz", config = {
548
+ initialRouteName: "Boo",
549
+ screens: {
550
+ Foo: {
551
+ screens: {
552
+ Foe: "foe",
553
+ Bar: {
554
+ screens: {
555
+ Baz: "baz"
556
+ }
557
+ }
558
+ }
559
+ }
560
+ }
561
+ }, state = {
562
+ index: 1,
563
+ routes: [
564
+ { name: "Boo" },
565
+ {
566
+ name: "Foo",
567
+ state: {
568
+ routes: [
569
+ {
570
+ name: "Bar",
571
+ state: {
572
+ routes: [{ name: "Baz", path }]
573
+ }
574
+ }
575
+ ]
576
+ }
577
+ }
578
+ ]
579
+ };
580
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
581
+ getStateFromPath(getPathFromState(state, config), config)
582
+ ).toEqual(state);
583
+ });
584
+ test("handles initialRouteName inside a screen", () => {
585
+ const path = "/baz", config = {
586
+ screens: {
587
+ Foo: {
588
+ initialRouteName: "Foe",
589
+ screens: {
590
+ Foe: "foe",
591
+ Bar: {
592
+ screens: {
593
+ Baz: "baz"
594
+ }
595
+ }
596
+ }
597
+ }
598
+ }
599
+ }, state = {
600
+ routes: [
601
+ {
602
+ name: "Foo",
603
+ state: {
604
+ index: 1,
605
+ routes: [
606
+ {
607
+ name: "Foe"
608
+ },
609
+ {
610
+ name: "Bar",
611
+ state: {
612
+ routes: [{ name: "Baz", path }]
613
+ }
614
+ }
615
+ ]
616
+ }
617
+ }
618
+ ]
619
+ };
620
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
621
+ getStateFromPath(getPathFromState(state, config), config)
622
+ ).toEqual(state);
623
+ });
624
+ test("handles initialRouteName included in path", () => {
625
+ const path = "/baz", config = {
626
+ screens: {
627
+ Foo: {
628
+ initialRouteName: "Foe",
629
+ screens: {
630
+ Foe: {
631
+ screens: {
632
+ Baz: "baz"
633
+ }
634
+ },
635
+ Bar: "bar"
636
+ }
637
+ }
638
+ }
639
+ }, state = {
640
+ routes: [
641
+ {
642
+ name: "Foo",
643
+ state: {
644
+ routes: [
645
+ {
646
+ name: "Foe",
647
+ state: {
648
+ routes: [{ name: "Baz", path }]
649
+ }
650
+ }
651
+ ]
652
+ }
653
+ }
654
+ ]
655
+ };
656
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
657
+ getStateFromPath(getPathFromState(state, config), config)
658
+ ).toEqual(state);
659
+ });
660
+ test.skip("handles two initialRouteNames", () => {
661
+ const path = "/bar/sweet/apple/foe/bis/jane?answer=42&count=10&valid=true", config = {
662
+ screens: {
663
+ Bar: {
664
+ path: "bar/:type/:fruit",
665
+ screens: {
666
+ Foo: {
667
+ screens: {
668
+ Foe: {
669
+ path: "foe",
670
+ screens: {
671
+ Baz: {
672
+ initialRouteName: "Bos",
673
+ screens: {
674
+ Bos: {
675
+ path: "bos",
676
+ exact: !0
677
+ },
678
+ Bis: {
679
+ path: "bis/:author",
680
+ stringify: {
681
+ author: (author) => author.replace(/^\w/, (c) => c.toLowerCase())
682
+ },
683
+ parse: {
684
+ author: (author) => author.replace(/^\w/, (c) => c.toUpperCase()),
685
+ count: Number,
686
+ valid: Boolean
687
+ }
688
+ }
689
+ }
690
+ }
691
+ }
692
+ }
693
+ }
694
+ }
695
+ }
696
+ }
697
+ }
698
+ }, state = {
699
+ routes: [
700
+ {
701
+ name: "Bar",
702
+ params: { fruit: "apple", type: "sweet" },
703
+ state: {
704
+ routes: [
705
+ {
706
+ name: "Foo",
707
+ state: {
708
+ routes: [
709
+ {
710
+ name: "Foe",
711
+ state: {
712
+ routes: [
713
+ {
714
+ name: "Baz",
715
+ state: {
716
+ index: 1,
717
+ routes: [
718
+ { name: "Bos" },
719
+ {
720
+ name: "Bis",
721
+ params: {
722
+ answer: "42",
723
+ author: "Jane",
724
+ count: 10,
725
+ valid: !0
726
+ },
727
+ path
728
+ }
729
+ ]
730
+ }
731
+ }
732
+ ]
733
+ }
734
+ }
735
+ ]
736
+ }
737
+ }
738
+ ]
739
+ }
740
+ }
741
+ ]
742
+ };
743
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
744
+ getStateFromPath(getPathFromState(state, config), config)
745
+ ).toEqual(state);
746
+ });
747
+ test.skip("accepts initialRouteName without config for it", () => {
748
+ const path = "/bar/sweet/apple/foe/bis/jane?answer=42&count=10&valid=true", config = {
749
+ screens: {
750
+ Bar: {
751
+ path: "bar/:type/:fruit",
752
+ screens: {
753
+ Foo: {
754
+ screens: {
755
+ Foe: {
756
+ path: "foe",
757
+ screens: {
758
+ Baz: {
759
+ initialRouteName: "Bas",
760
+ screens: {
761
+ Bos: {
762
+ path: "bos",
763
+ exact: !0
764
+ },
765
+ Bis: {
766
+ path: "bis/:author",
767
+ stringify: {
768
+ author: (author) => author.replace(/^\w/, (c) => c.toLowerCase())
769
+ },
770
+ parse: {
771
+ author: (author) => author.replace(/^\w/, (c) => c.toUpperCase()),
772
+ count: Number,
773
+ valid: Boolean
774
+ }
775
+ }
776
+ }
777
+ }
778
+ }
779
+ }
780
+ }
781
+ }
782
+ }
783
+ }
784
+ }
785
+ }, state = {
786
+ routes: [
787
+ {
788
+ name: "Bar",
789
+ params: { fruit: "apple", type: "sweet" },
790
+ state: {
791
+ routes: [
792
+ {
793
+ name: "Foo",
794
+ state: {
795
+ routes: [
796
+ {
797
+ name: "Foe",
798
+ state: {
799
+ routes: [
800
+ {
801
+ name: "Baz",
802
+ state: {
803
+ index: 1,
804
+ routes: [
805
+ { name: "Bas" },
806
+ {
807
+ name: "Bis",
808
+ params: {
809
+ answer: "42",
810
+ author: "Jane",
811
+ count: 10,
812
+ valid: !0
813
+ },
814
+ path
815
+ }
816
+ ]
817
+ }
818
+ }
819
+ ]
820
+ }
821
+ }
822
+ ]
823
+ }
824
+ }
825
+ ]
826
+ }
827
+ }
828
+ ]
829
+ };
830
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
831
+ getStateFromPath(getPathFromState(state, config), config)
832
+ ).toEqual(state);
833
+ });
834
+ test("returns undefined if no matching screen is present (top level path)", () => {
835
+ expect(getStateFromPath("/foo/bar", {
836
+ path: "qux",
837
+ screens: {
838
+ Foo: {
839
+ screens: {
840
+ Foe: "foo",
841
+ Bar: {
842
+ screens: {
843
+ Baz: "bar"
844
+ }
845
+ }
846
+ }
847
+ }
848
+ }
849
+ })).toBeUndefined();
850
+ });
851
+ test("returns undefined if no matching screen is present", () => {
852
+ expect(getStateFromPath("/baz", {
853
+ screens: {
854
+ Foo: {
855
+ path: "foo",
856
+ screens: {
857
+ Foe: "foe",
858
+ Bar: {
859
+ screens: {
860
+ Baz: "baz"
861
+ }
862
+ }
863
+ }
864
+ }
865
+ }
866
+ })).toBeUndefined();
867
+ });
868
+ test("returns undefined if path is empty and no matching screen is present", () => {
869
+ expect(getStateFromPath("", {
870
+ screens: {
871
+ Foo: {
872
+ screens: {
873
+ Foe: "foe",
874
+ Bar: {
875
+ screens: {
876
+ Baz: "baz"
877
+ }
878
+ }
879
+ }
880
+ }
881
+ }
882
+ })).toBeUndefined();
883
+ });
884
+ test.skip("returns matching screen if path is empty", () => {
885
+ const path = "", config = {
886
+ screens: {
887
+ Foo: {
888
+ screens: {
889
+ Foe: "foe",
890
+ Bar: {
891
+ screens: {
892
+ Qux: "",
893
+ Baz: "baz"
894
+ }
895
+ }
896
+ }
897
+ }
898
+ }
899
+ }, state = {
900
+ routes: [
901
+ {
902
+ name: "Foo",
903
+ state: {
904
+ routes: [
905
+ {
906
+ name: "Bar",
907
+ state: {
908
+ routes: [{ name: "Qux", path }]
909
+ }
910
+ }
911
+ ]
912
+ }
913
+ }
914
+ ]
915
+ };
916
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
917
+ getStateFromPath(getPathFromState(state, config), config)
918
+ ).toEqual(changePath(state, ""));
919
+ });
920
+ test.skip("returns matching screen if path is only slash", () => {
921
+ const path = "/", config = {
922
+ screens: {
923
+ Foo: {
924
+ screens: {
925
+ Foe: "foe",
926
+ Bar: {
927
+ screens: {
928
+ Qux: "",
929
+ Baz: "baz"
930
+ }
931
+ }
932
+ }
933
+ }
934
+ }
935
+ }, state = {
936
+ routes: [
937
+ {
938
+ name: "Foo",
939
+ state: {
940
+ routes: [
941
+ {
942
+ name: "Bar",
943
+ state: {
944
+ routes: [{ name: "Qux", path: "" }]
945
+ }
946
+ }
947
+ ]
948
+ }
949
+ }
950
+ ]
951
+ };
952
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
953
+ getStateFromPath(getPathFromState(state, config), config)
954
+ ).toEqual(changePath(state, ""));
955
+ });
956
+ test("returns matching screen with params if path is empty", () => {
957
+ const path = "?foo=42", config = {
958
+ screens: {
959
+ Foo: {
960
+ screens: {
961
+ Foe: "foe",
962
+ Bar: {
963
+ screens: {
964
+ Qux: {
965
+ path: "",
966
+ parse: { foo: Number }
967
+ },
968
+ Baz: "baz"
969
+ }
970
+ }
971
+ }
972
+ }
973
+ }
974
+ }, state = {
975
+ routes: [
976
+ {
977
+ name: "Foo",
978
+ state: {
979
+ routes: [
980
+ {
981
+ name: "Bar",
982
+ state: {
983
+ routes: [{ name: "Qux", params: { foo: 42 }, path }]
984
+ }
985
+ }
986
+ ]
987
+ }
988
+ }
989
+ ]
990
+ };
991
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
992
+ getStateFromPath(getPathFromState(state, config), config)
993
+ ).toEqual(changePath(state, "/?foo=42"));
994
+ });
995
+ test("doesn't match nested screen if path is empty", () => {
996
+ expect(getStateFromPath("", {
997
+ screens: {
998
+ Foo: {
999
+ screens: {
1000
+ Foe: "foe",
1001
+ Bar: {
1002
+ path: "bar",
1003
+ screens: {
1004
+ Qux: {
1005
+ path: "",
1006
+ parse: { foo: Number }
1007
+ }
1008
+ }
1009
+ }
1010
+ }
1011
+ }
1012
+ }
1013
+ })).toBeUndefined();
1014
+ });
1015
+ test.skip("chooses more exhaustive pattern", () => {
1016
+ const path = "/foo/5", config = {
1017
+ screens: {
1018
+ Foe: {
1019
+ path: "/",
1020
+ initialRouteName: "Foo",
1021
+ screens: {
1022
+ Foo: "foo",
1023
+ Bis: {
1024
+ path: "foo/:id",
1025
+ parse: {
1026
+ id: Number
1027
+ }
1028
+ }
1029
+ }
1030
+ }
1031
+ }
1032
+ }, state = {
1033
+ routes: [
1034
+ {
1035
+ name: "Foe",
1036
+ state: {
1037
+ index: 1,
1038
+ routes: [
1039
+ {
1040
+ name: "Foo"
1041
+ },
1042
+ {
1043
+ name: "Bis",
1044
+ params: { id: 5 },
1045
+ path
1046
+ }
1047
+ ]
1048
+ }
1049
+ }
1050
+ ]
1051
+ };
1052
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
1053
+ getStateFromPath(getPathFromState(state, config), config)
1054
+ ).toEqual(state);
1055
+ });
1056
+ test("handles same paths beginnings", () => {
1057
+ const path = "/foos", config = {
1058
+ screens: {
1059
+ Foe: {
1060
+ path: "/",
1061
+ initialRouteName: "Foo",
1062
+ screens: {
1063
+ Foo: "foo",
1064
+ Bis: {
1065
+ path: "foos"
1066
+ }
1067
+ }
1068
+ }
1069
+ }
1070
+ }, state = {
1071
+ routes: [
1072
+ {
1073
+ name: "Foe",
1074
+ state: {
1075
+ index: 1,
1076
+ routes: [
1077
+ {
1078
+ name: "Foo"
1079
+ },
1080
+ {
1081
+ name: "Bis",
1082
+ path
1083
+ }
1084
+ ]
1085
+ }
1086
+ }
1087
+ ]
1088
+ };
1089
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
1090
+ getStateFromPath(getPathFromState(state, config), config)
1091
+ ).toEqual(state);
1092
+ });
1093
+ test.skip("handles same paths beginnings with params", () => {
1094
+ const path = "/foos/5", config = {
1095
+ screens: {
1096
+ Foe: {
1097
+ path: "/",
1098
+ initialRouteName: "Foo",
1099
+ screens: {
1100
+ Foo: "foo",
1101
+ Bis: {
1102
+ path: "foos/:id",
1103
+ parse: {
1104
+ id: Number
1105
+ }
1106
+ }
1107
+ }
1108
+ }
1109
+ }
1110
+ }, state = {
1111
+ routes: [
1112
+ {
1113
+ name: "Foe",
1114
+ state: {
1115
+ index: 1,
1116
+ routes: [
1117
+ {
1118
+ name: "Foo"
1119
+ },
1120
+ {
1121
+ name: "Bis",
1122
+ params: { id: 5 },
1123
+ path
1124
+ }
1125
+ ]
1126
+ }
1127
+ }
1128
+ ]
1129
+ };
1130
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
1131
+ getStateFromPath(getPathFromState(state, config), config)
1132
+ ).toEqual(state);
1133
+ });
1134
+ test.skip("handles not taking path with too many segments", () => {
1135
+ const path = "/foos/5", config = {
1136
+ screens: {
1137
+ Foe: {
1138
+ path: "/",
1139
+ initialRouteName: "Foo",
1140
+ screens: {
1141
+ Foo: "foo",
1142
+ Bis: {
1143
+ path: "foos/:id",
1144
+ parse: {
1145
+ id: Number
1146
+ }
1147
+ },
1148
+ Bas: {
1149
+ path: "foos/:id/:nip",
1150
+ parse: {
1151
+ id: Number,
1152
+ pwd: Number
1153
+ }
1154
+ }
1155
+ }
1156
+ }
1157
+ }
1158
+ }, state = {
1159
+ routes: [
1160
+ {
1161
+ name: "Foe",
1162
+ state: {
1163
+ index: 1,
1164
+ routes: [
1165
+ {
1166
+ name: "Foo"
1167
+ },
1168
+ {
1169
+ name: "Bis",
1170
+ params: { id: 5 },
1171
+ path
1172
+ }
1173
+ ]
1174
+ }
1175
+ }
1176
+ ]
1177
+ };
1178
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
1179
+ getStateFromPath(getPathFromState(state, config), config)
1180
+ ).toEqual(state);
1181
+ });
1182
+ test.skip("handles differently ordered params v1", () => {
1183
+ const path = "/foos/5/res/20", config = {
1184
+ screens: {
1185
+ Foe: {
1186
+ path: "/",
1187
+ initialRouteName: "Foo",
1188
+ screens: {
1189
+ Foo: "foo",
1190
+ Bis: {
1191
+ path: "foos/:id",
1192
+ parse: {
1193
+ id: Number
1194
+ }
1195
+ },
1196
+ Bas: {
1197
+ path: "foos/:id/res/:pwd",
1198
+ parse: {
1199
+ id: Number,
1200
+ pwd: Number
1201
+ }
1202
+ }
1203
+ }
1204
+ }
1205
+ }
1206
+ }, state = {
1207
+ routes: [
1208
+ {
1209
+ name: "Foe",
1210
+ state: {
1211
+ index: 1,
1212
+ routes: [
1213
+ {
1214
+ name: "Foo"
1215
+ },
1216
+ {
1217
+ name: "Bas",
1218
+ params: { id: 5, pwd: 20 },
1219
+ path
1220
+ }
1221
+ ]
1222
+ }
1223
+ }
1224
+ ]
1225
+ };
1226
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
1227
+ getStateFromPath(getPathFromState(state, config), config)
1228
+ ).toEqual(state);
1229
+ });
1230
+ test.skip("handles differently ordered params v2", () => {
1231
+ const path = "/5/20/foos/res", config = {
1232
+ screens: {
1233
+ Foe: {
1234
+ path: "/",
1235
+ initialRouteName: "Foo",
1236
+ screens: {
1237
+ Foo: "foo",
1238
+ Bis: {
1239
+ path: "foos/:id",
1240
+ parse: {
1241
+ id: Number
1242
+ }
1243
+ },
1244
+ Bas: {
1245
+ path: ":id/:pwd/foos/res",
1246
+ parse: {
1247
+ id: Number,
1248
+ pwd: Number
1249
+ }
1250
+ }
1251
+ }
1252
+ }
1253
+ }
1254
+ }, state = {
1255
+ routes: [
1256
+ {
1257
+ name: "Foe",
1258
+ state: {
1259
+ index: 1,
1260
+ routes: [
1261
+ {
1262
+ name: "Foo"
1263
+ },
1264
+ {
1265
+ name: "Bas",
1266
+ params: { id: 5, pwd: 20 },
1267
+ path
1268
+ }
1269
+ ]
1270
+ }
1271
+ }
1272
+ ]
1273
+ };
1274
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
1275
+ getStateFromPath(getPathFromState(state, config), config)
1276
+ ).toEqual(state);
1277
+ });
1278
+ test.skip("handles differently ordered params v3", () => {
1279
+ const path = "/foos/5/20/res", config = {
1280
+ screens: {
1281
+ Foe: {
1282
+ path: "/",
1283
+ initialRouteName: "Foo",
1284
+ screens: {
1285
+ Foo: "foo",
1286
+ Bis: {
1287
+ path: "foos/:id",
1288
+ parse: {
1289
+ id: Number
1290
+ }
1291
+ },
1292
+ Bas: {
1293
+ path: "foos/:id/:pwd/res",
1294
+ parse: {
1295
+ id: Number,
1296
+ pwd: Number
1297
+ }
1298
+ }
1299
+ }
1300
+ }
1301
+ }
1302
+ }, state = {
1303
+ routes: [
1304
+ {
1305
+ name: "Foe",
1306
+ state: {
1307
+ index: 1,
1308
+ routes: [
1309
+ {
1310
+ name: "Foo"
1311
+ },
1312
+ {
1313
+ name: "Bas",
1314
+ params: { id: 5, pwd: 20 },
1315
+ path
1316
+ }
1317
+ ]
1318
+ }
1319
+ }
1320
+ ]
1321
+ };
1322
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
1323
+ getStateFromPath(getPathFromState(state, config), config)
1324
+ ).toEqual(state);
1325
+ });
1326
+ test.skip("handles differently ordered params v4", () => {
1327
+ const path = "5/foos/res/20", config = {
1328
+ screens: {
1329
+ Foe: {
1330
+ path: "/",
1331
+ initialRouteName: "Foo",
1332
+ screens: {
1333
+ Foo: "foo",
1334
+ Bis: {
1335
+ path: "foos/:id",
1336
+ parse: {
1337
+ id: Number
1338
+ }
1339
+ },
1340
+ Bas: {
1341
+ path: ":id/foos/res/:pwd",
1342
+ parse: {
1343
+ id: Number,
1344
+ pwd: Number
1345
+ }
1346
+ }
1347
+ }
1348
+ }
1349
+ }
1350
+ }, state = {
1351
+ routes: [
1352
+ {
1353
+ name: "Foe",
1354
+ state: {
1355
+ index: 1,
1356
+ routes: [
1357
+ {
1358
+ name: "Foo"
1359
+ },
1360
+ {
1361
+ name: "Bas",
1362
+ params: { id: 5, pwd: 20 },
1363
+ path
1364
+ }
1365
+ ]
1366
+ }
1367
+ }
1368
+ ]
1369
+ };
1370
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
1371
+ getStateFromPath(getPathFromState(state, config), config)
1372
+ ).toEqual(changePath(state, "/5/foos/res/20"));
1373
+ });
1374
+ test.skip("handles simple optional params", () => {
1375
+ const path = "/foos/5", config = {
1376
+ screens: {
1377
+ Foe: {
1378
+ path: "/",
1379
+ initialRouteName: "Foo",
1380
+ screens: {
1381
+ Foo: "foo",
1382
+ Bis: {
1383
+ path: "foo/:id",
1384
+ parse: {
1385
+ id: Number
1386
+ }
1387
+ },
1388
+ Bas: {
1389
+ path: "foos/:id/:nip?",
1390
+ parse: {
1391
+ id: Number,
1392
+ nip: Number
1393
+ }
1394
+ }
1395
+ }
1396
+ }
1397
+ }
1398
+ }, state = {
1399
+ routes: [
1400
+ {
1401
+ name: "Foe",
1402
+ state: {
1403
+ index: 1,
1404
+ routes: [
1405
+ {
1406
+ name: "Foo"
1407
+ },
1408
+ {
1409
+ name: "Bas",
1410
+ params: { id: 5 },
1411
+ path
1412
+ }
1413
+ ]
1414
+ }
1415
+ }
1416
+ ]
1417
+ };
1418
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
1419
+ getStateFromPath(getPathFromState(state, config), config)
1420
+ ).toEqual(state);
1421
+ });
1422
+ test.skip("handle 2 optional params at the end v1", () => {
1423
+ const path = "/foos/5", config = {
1424
+ screens: {
1425
+ Foe: {
1426
+ path: "/",
1427
+ initialRouteName: "Foo",
1428
+ screens: {
1429
+ Foo: "foo",
1430
+ Bis: {
1431
+ path: "foo/:id",
1432
+ parse: {
1433
+ id: Number
1434
+ }
1435
+ },
1436
+ Bas: {
1437
+ path: "foos/:id/:nip?/:pwd?",
1438
+ parse: {
1439
+ id: Number,
1440
+ nip: Number
1441
+ }
1442
+ }
1443
+ }
1444
+ }
1445
+ }
1446
+ }, state = {
1447
+ routes: [
1448
+ {
1449
+ name: "Foe",
1450
+ state: {
1451
+ index: 1,
1452
+ routes: [
1453
+ {
1454
+ name: "Foo"
1455
+ },
1456
+ {
1457
+ name: "Bas",
1458
+ params: { id: 5 },
1459
+ path
1460
+ }
1461
+ ]
1462
+ }
1463
+ }
1464
+ ]
1465
+ };
1466
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
1467
+ getStateFromPath(getPathFromState(state, config), config)
1468
+ ).toEqual(state);
1469
+ });
1470
+ test.skip("handle 2 optional params at the end v2", () => {
1471
+ const path = "/foos/5/10", config = {
1472
+ screens: {
1473
+ Foe: {
1474
+ path: "/",
1475
+ initialRouteName: "Foo",
1476
+ screens: {
1477
+ Foo: "foo",
1478
+ Bis: {
1479
+ path: "foo/:id",
1480
+ parse: {
1481
+ id: Number
1482
+ }
1483
+ },
1484
+ Bas: {
1485
+ path: "foos/:id/:nip?/:pwd?",
1486
+ parse: {
1487
+ id: Number,
1488
+ nip: Number
1489
+ }
1490
+ }
1491
+ }
1492
+ }
1493
+ }
1494
+ }, state = {
1495
+ routes: [
1496
+ {
1497
+ name: "Foe",
1498
+ state: {
1499
+ index: 1,
1500
+ routes: [
1501
+ {
1502
+ name: "Foo"
1503
+ },
1504
+ {
1505
+ name: "Bas",
1506
+ params: { id: 5, nip: 10 },
1507
+ path
1508
+ }
1509
+ ]
1510
+ }
1511
+ }
1512
+ ]
1513
+ };
1514
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
1515
+ getStateFromPath(getPathFromState(state, config), config)
1516
+ ).toEqual(state);
1517
+ });
1518
+ test.skip("handle 2 optional params at the end v3", () => {
1519
+ const path = "/foos/5/10/15", config = {
1520
+ screens: {
1521
+ Foe: {
1522
+ path: "/",
1523
+ initialRouteName: "Foo",
1524
+ screens: {
1525
+ Foo: "foo",
1526
+ Bis: {
1527
+ path: "foo/:id",
1528
+ parse: {
1529
+ id: Number
1530
+ }
1531
+ },
1532
+ Bas: {
1533
+ path: "foos/:id/:nip?/:pwd?",
1534
+ parse: {
1535
+ id: Number,
1536
+ nip: Number,
1537
+ pwd: Number
1538
+ }
1539
+ }
1540
+ }
1541
+ }
1542
+ }
1543
+ }, state = {
1544
+ routes: [
1545
+ {
1546
+ name: "Foe",
1547
+ state: {
1548
+ index: 1,
1549
+ routes: [
1550
+ {
1551
+ name: "Foo"
1552
+ },
1553
+ {
1554
+ name: "Bas",
1555
+ params: { id: 5, nip: 10, pwd: 15 },
1556
+ path
1557
+ }
1558
+ ]
1559
+ }
1560
+ }
1561
+ ]
1562
+ };
1563
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
1564
+ getStateFromPath(getPathFromState(state, config), config)
1565
+ ).toEqual(state);
1566
+ });
1567
+ test.skip("handle optional params in the middle v1", () => {
1568
+ const path = "/foos/5/10", config = {
1569
+ screens: {
1570
+ Foe: {
1571
+ path: "/",
1572
+ initialRouteName: "Foo",
1573
+ screens: {
1574
+ Foo: "foo",
1575
+ Bis: {
1576
+ path: "foo/:id",
1577
+ parse: {
1578
+ id: Number
1579
+ }
1580
+ },
1581
+ Bas: {
1582
+ path: "foos/:id/:nip?/:pwd",
1583
+ parse: {
1584
+ id: Number,
1585
+ nip: Number,
1586
+ pwd: Number
1587
+ }
1588
+ }
1589
+ }
1590
+ }
1591
+ }
1592
+ }, state = {
1593
+ routes: [
1594
+ {
1595
+ name: "Foe",
1596
+ state: {
1597
+ index: 1,
1598
+ routes: [
1599
+ {
1600
+ name: "Foo"
1601
+ },
1602
+ {
1603
+ name: "Bas",
1604
+ params: { id: 5, pwd: 10 },
1605
+ path
1606
+ }
1607
+ ]
1608
+ }
1609
+ }
1610
+ ]
1611
+ };
1612
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
1613
+ getStateFromPath(getPathFromState(state, config), config)
1614
+ ).toEqual(state);
1615
+ });
1616
+ test.skip("handle optional params in the middle v2", () => {
1617
+ const path = "/foos/5/10/15", config = {
1618
+ screens: {
1619
+ Foe: {
1620
+ path: "/",
1621
+ initialRouteName: "Foo",
1622
+ screens: {
1623
+ Foo: "foo",
1624
+ Bis: {
1625
+ path: "foo/:id",
1626
+ parse: {
1627
+ id: Number
1628
+ }
1629
+ },
1630
+ Bas: {
1631
+ path: "foos/:id/:nip?/:pwd",
1632
+ parse: {
1633
+ id: Number,
1634
+ nip: Number,
1635
+ pwd: Number
1636
+ }
1637
+ }
1638
+ }
1639
+ }
1640
+ }
1641
+ }, state = {
1642
+ routes: [
1643
+ {
1644
+ name: "Foe",
1645
+ state: {
1646
+ index: 1,
1647
+ routes: [
1648
+ {
1649
+ name: "Foo"
1650
+ },
1651
+ {
1652
+ name: "Bas",
1653
+ params: { id: 5, nip: 10, pwd: 15 },
1654
+ path
1655
+ }
1656
+ ]
1657
+ }
1658
+ }
1659
+ ]
1660
+ };
1661
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
1662
+ getStateFromPath(getPathFromState(state, config), config)
1663
+ ).toEqual(state);
1664
+ });
1665
+ test.skip("handle optional params in the middle v3", () => {
1666
+ const path = "/foos/5/10/15", config = {
1667
+ screens: {
1668
+ Foe: {
1669
+ path: "/",
1670
+ initialRouteName: "Foo",
1671
+ screens: {
1672
+ Foo: "foo",
1673
+ Bis: {
1674
+ path: "foo/:id",
1675
+ parse: {
1676
+ id: Number
1677
+ }
1678
+ },
1679
+ Bas: {
1680
+ path: "foos/:id/:nip?/:pwd/:smh",
1681
+ parse: {
1682
+ id: Number,
1683
+ nip: Number,
1684
+ pwd: Number,
1685
+ smh: Number
1686
+ }
1687
+ }
1688
+ }
1689
+ }
1690
+ }
1691
+ }, state = {
1692
+ routes: [
1693
+ {
1694
+ name: "Foe",
1695
+ state: {
1696
+ index: 1,
1697
+ routes: [
1698
+ {
1699
+ name: "Foo"
1700
+ },
1701
+ {
1702
+ name: "Bas",
1703
+ params: { id: 5, pwd: 10, smh: 15 },
1704
+ path
1705
+ }
1706
+ ]
1707
+ }
1708
+ }
1709
+ ]
1710
+ };
1711
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
1712
+ getStateFromPath(getPathFromState(state, config), config)
1713
+ ).toEqual(state);
1714
+ });
1715
+ test.skip("handle optional params in the middle v4", () => {
1716
+ const path = "/foos/5/10", config = {
1717
+ screens: {
1718
+ Foe: {
1719
+ path: "/",
1720
+ initialRouteName: "Foo",
1721
+ screens: {
1722
+ Foo: "foo",
1723
+ Bis: {
1724
+ path: "foo/:id",
1725
+ parse: {
1726
+ id: Number
1727
+ }
1728
+ },
1729
+ Bas: {
1730
+ path: "foos/:nip?/:pwd/:smh?/:id",
1731
+ parse: {
1732
+ id: Number,
1733
+ nip: Number,
1734
+ pwd: Number,
1735
+ smh: Number
1736
+ }
1737
+ }
1738
+ }
1739
+ }
1740
+ }
1741
+ }, state = {
1742
+ routes: [
1743
+ {
1744
+ name: "Foe",
1745
+ state: {
1746
+ index: 1,
1747
+ routes: [
1748
+ {
1749
+ name: "Foo"
1750
+ },
1751
+ {
1752
+ name: "Bas",
1753
+ params: { pwd: 5, id: 10 },
1754
+ path
1755
+ }
1756
+ ]
1757
+ }
1758
+ }
1759
+ ]
1760
+ };
1761
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
1762
+ getStateFromPath(getPathFromState(state, config), config)
1763
+ ).toEqual(state);
1764
+ });
1765
+ test.skip("handle optional params in the middle v5", () => {
1766
+ const path = "/foos/5/10/15", config = {
1767
+ screens: {
1768
+ Foe: {
1769
+ path: "/",
1770
+ initialRouteName: "Foo",
1771
+ screens: {
1772
+ Foo: "foo",
1773
+ Bis: {
1774
+ path: "foo/:id",
1775
+ parse: {
1776
+ id: Number
1777
+ }
1778
+ },
1779
+ Bas: {
1780
+ path: "foos/:nip?/:pwd/:smh?/:id",
1781
+ parse: {
1782
+ id: Number,
1783
+ nip: Number,
1784
+ pwd: Number,
1785
+ smh: Number
1786
+ }
1787
+ }
1788
+ }
1789
+ }
1790
+ }
1791
+ }, state = {
1792
+ routes: [
1793
+ {
1794
+ name: "Foe",
1795
+ state: {
1796
+ index: 1,
1797
+ routes: [
1798
+ {
1799
+ name: "Foo"
1800
+ },
1801
+ {
1802
+ name: "Bas",
1803
+ params: { nip: 5, pwd: 10, id: 15 },
1804
+ path
1805
+ }
1806
+ ]
1807
+ }
1808
+ }
1809
+ ]
1810
+ };
1811
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
1812
+ getStateFromPath(getPathFromState(state, config), config)
1813
+ ).toEqual(state);
1814
+ });
1815
+ test.skip("handle optional params in the beginning v1", () => {
1816
+ const path = "5/10/foos/15", config = {
1817
+ screens: {
1818
+ Foe: {
1819
+ path: "/",
1820
+ initialRouteName: "Foo",
1821
+ screens: {
1822
+ Foo: "foo",
1823
+ Bis: {
1824
+ path: "foo/:id",
1825
+ parse: {
1826
+ id: Number
1827
+ }
1828
+ },
1829
+ Bas: {
1830
+ path: ":nip?/:pwd/foos/:smh?/:id",
1831
+ parse: {
1832
+ id: Number,
1833
+ nip: Number,
1834
+ pwd: Number,
1835
+ smh: Number
1836
+ }
1837
+ }
1838
+ }
1839
+ }
1840
+ }
1841
+ }, state = {
1842
+ routes: [
1843
+ {
1844
+ name: "Foe",
1845
+ state: {
1846
+ index: 1,
1847
+ routes: [
1848
+ {
1849
+ name: "Foo"
1850
+ },
1851
+ {
1852
+ name: "Bas",
1853
+ params: { nip: 5, pwd: 10, id: 15 },
1854
+ path
1855
+ }
1856
+ ]
1857
+ }
1858
+ }
1859
+ ]
1860
+ };
1861
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
1862
+ getStateFromPath(getPathFromState(state, config), config)
1863
+ ).toEqual(changePath(state, "/5/10/foos/15"));
1864
+ });
1865
+ test.skip("handle optional params in the beginning v2", () => {
1866
+ const path = "5/10/foos/15", config = {
1867
+ screens: {
1868
+ Foe: {
1869
+ path: "/",
1870
+ initialRouteName: "Foo",
1871
+ screens: {
1872
+ Foo: "foo",
1873
+ Bis: {
1874
+ path: "foo/:id",
1875
+ parse: {
1876
+ id: Number
1877
+ }
1878
+ },
1879
+ Bas: {
1880
+ path: ":nip?/:smh?/:pwd/foos/:id",
1881
+ parse: {
1882
+ id: Number,
1883
+ nip: Number,
1884
+ pwd: Number,
1885
+ smh: Number
1886
+ }
1887
+ }
1888
+ }
1889
+ }
1890
+ }
1891
+ }, state = {
1892
+ routes: [
1893
+ {
1894
+ name: "Foe",
1895
+ state: {
1896
+ index: 1,
1897
+ routes: [
1898
+ {
1899
+ name: "Foo"
1900
+ },
1901
+ {
1902
+ name: "Bas",
1903
+ params: { nip: 5, pwd: 10, id: 15 },
1904
+ path
1905
+ }
1906
+ ]
1907
+ }
1908
+ }
1909
+ ]
1910
+ };
1911
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
1912
+ getStateFromPath(getPathFromState(state, config), config)
1913
+ ).toEqual(changePath(state, "/5/10/foos/15"));
1914
+ });
1915
+ test.skip("merges parent patterns if needed", () => {
1916
+ const path = "foo/42/baz/babel", config = {
1917
+ screens: {
1918
+ Foo: {
1919
+ path: "foo/:bar",
1920
+ parse: {
1921
+ bar: Number
1922
+ },
1923
+ screens: {
1924
+ Baz: "baz/:qux"
1925
+ }
1926
+ }
1927
+ }
1928
+ }, state = {
1929
+ routes: [
1930
+ {
1931
+ name: "Foo",
1932
+ params: { bar: 42 },
1933
+ state: {
1934
+ routes: [
1935
+ {
1936
+ name: "Baz",
1937
+ params: { qux: "babel" },
1938
+ path
1939
+ }
1940
+ ]
1941
+ }
1942
+ }
1943
+ ]
1944
+ };
1945
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
1946
+ getStateFromPath(getPathFromState(state, config), config)
1947
+ ).toEqual(changePath(state, "/foo/42/baz/babel"));
1948
+ });
1949
+ test.skip("ignores extra slashes in the pattern", () => {
1950
+ const path = "/bar/42", config = {
1951
+ screens: {
1952
+ Foo: {
1953
+ screens: {
1954
+ Bar: {
1955
+ path: "/bar//:id/"
1956
+ }
1957
+ }
1958
+ }
1959
+ }
1960
+ }, state = {
1961
+ routes: [
1962
+ {
1963
+ name: "Foo",
1964
+ state: {
1965
+ routes: [
1966
+ {
1967
+ name: "Bar",
1968
+ params: { id: "42" },
1969
+ path
1970
+ }
1971
+ ]
1972
+ }
1973
+ }
1974
+ ]
1975
+ };
1976
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
1977
+ getStateFromPath(getPathFromState(state, config), config)
1978
+ ).toEqual(state);
1979
+ });
1980
+ test.skip("matches wildcard patterns at root", () => {
1981
+ const path = "/test/bar/42/whatever", config = {
1982
+ screens: {
1983
+ 404: "*",
1984
+ Foo: {
1985
+ screens: {
1986
+ Bar: {
1987
+ path: "/bar/:id/"
1988
+ }
1989
+ }
1990
+ }
1991
+ }
1992
+ }, state = {
1993
+ routes: [{ name: "404", path }]
1994
+ };
1995
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
1996
+ getStateFromPath(getPathFromState(state, config), config)
1997
+ ).toEqual(changePath(state, "/404"));
1998
+ });
1999
+ test.skip("matches wildcard patterns at nested level", () => {
2000
+ const path = "/bar/42/whatever/baz/initt", config = {
2001
+ screens: {
2002
+ Foo: {
2003
+ screens: {
2004
+ Bar: {
2005
+ path: "/bar/:id/",
2006
+ screens: {
2007
+ 404: "*"
2008
+ }
2009
+ }
2010
+ }
2011
+ }
2012
+ }
2013
+ }, state = {
2014
+ routes: [
2015
+ {
2016
+ name: "Foo",
2017
+ state: {
2018
+ routes: [
2019
+ {
2020
+ name: "Bar",
2021
+ params: { id: "42" },
2022
+ state: {
2023
+ routes: [{ name: "404", path }]
2024
+ }
2025
+ }
2026
+ ]
2027
+ }
2028
+ }
2029
+ ]
2030
+ };
2031
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
2032
+ getStateFromPath(getPathFromState(state, config), config)
2033
+ ).toEqual(changePath(state, "/bar/42/404"));
2034
+ });
2035
+ test.skip("matches wildcard patterns at nested level with exact", () => {
2036
+ const path = "/whatever", config = {
2037
+ screens: {
2038
+ Foo: {
2039
+ screens: {
2040
+ Bar: {
2041
+ path: "/bar/:id/",
2042
+ screens: {
2043
+ 404: {
2044
+ path: "*",
2045
+ exact: !0
2046
+ }
2047
+ }
2048
+ },
2049
+ Baz: {}
2050
+ }
2051
+ }
2052
+ }
2053
+ }, state = {
2054
+ routes: [
2055
+ {
2056
+ name: "Foo",
2057
+ state: {
2058
+ routes: [
2059
+ {
2060
+ name: "Bar",
2061
+ state: {
2062
+ routes: [{ name: "404", path }]
2063
+ }
2064
+ }
2065
+ ]
2066
+ }
2067
+ }
2068
+ ]
2069
+ };
2070
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
2071
+ getStateFromPath(getPathFromState(state, config), config)
2072
+ ).toEqual(changePath(state, "/404"));
2073
+ });
2074
+ test.skip("tries to match wildcard patterns at the end", () => {
2075
+ const path = "/bar/42/test", config = {
2076
+ screens: {
2077
+ Foo: {
2078
+ screens: {
2079
+ Bar: {
2080
+ path: "/bar/:id/",
2081
+ screens: {
2082
+ 404: "*",
2083
+ UserProfile: ":userSlug",
2084
+ Test: "test"
2085
+ }
2086
+ }
2087
+ }
2088
+ }
2089
+ }
2090
+ }, state = {
2091
+ routes: [
2092
+ {
2093
+ name: "Foo",
2094
+ state: {
2095
+ routes: [
2096
+ {
2097
+ name: "Bar",
2098
+ params: { id: "42" },
2099
+ state: {
2100
+ routes: [{ name: "Test", path }]
2101
+ }
2102
+ }
2103
+ ]
2104
+ }
2105
+ }
2106
+ ]
2107
+ };
2108
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
2109
+ getStateFromPath(getPathFromState(state, config), config)
2110
+ ).toEqual(state);
2111
+ });
2112
+ test.skip("uses nearest parent wildcard match for unmatched paths", () => {
2113
+ const path = "/bar/42/baz/test", config = {
2114
+ screens: {
2115
+ Foo: {
2116
+ screens: {
2117
+ Bar: {
2118
+ path: "/bar/:id/",
2119
+ screens: {
2120
+ Baz: "baz"
2121
+ }
2122
+ },
2123
+ 404: "*"
2124
+ }
2125
+ }
2126
+ }
2127
+ }, state = {
2128
+ routes: [
2129
+ {
2130
+ name: "Foo",
2131
+ state: {
2132
+ routes: [{ name: "404", path }]
2133
+ }
2134
+ }
2135
+ ]
2136
+ };
2137
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
2138
+ getStateFromPath(getPathFromState(state, config), config)
2139
+ ).toEqual(changePath(state, "/404"));
2140
+ });
2141
+ test.skip("matches screen with overlapping initial path and wildcard", () => {
2142
+ const path = "/bar/42/baz/test/whatever", config = {
2143
+ screens: {
2144
+ Foo: {
2145
+ screens: {
2146
+ Bar: {
2147
+ path: "/bar/:id/",
2148
+ screens: {
2149
+ Baz: "baz"
2150
+ }
2151
+ },
2152
+ Baz: "/bar/:id/*"
2153
+ }
2154
+ }
2155
+ }
2156
+ }, state = {
2157
+ routes: [
2158
+ {
2159
+ name: "Foo",
2160
+ state: {
2161
+ routes: [{ name: "Baz", params: { id: "42" }, path }]
2162
+ }
2163
+ }
2164
+ ]
2165
+ };
2166
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
2167
+ getStateFromPath(getPathFromState(state, config), config)
2168
+ ).toEqual(changePath(state, "/bar/42/Baz"));
2169
+ });
2170
+ test("throws if two screens map to the same pattern", () => {
2171
+ const path = "/bar/42/baz/test";
2172
+ expect(
2173
+ () => getStateFromPath(path, {
2174
+ screens: {
2175
+ Foo: {
2176
+ screens: {
2177
+ Bar: {
2178
+ path: "/bar/:id/",
2179
+ screens: {
2180
+ Baz: "baz"
2181
+ }
2182
+ },
2183
+ Bax: "/bar/:id/baz"
2184
+ }
2185
+ }
2186
+ }
2187
+ })
2188
+ ).toThrow(
2189
+ "Found conflicting screens with the same pattern. The pattern 'bar/:id/baz' resolves to both 'Foo > Bax' and 'Foo > Bar > Baz'. Patterns must be unique and cannot resolve to more than one screen."
2190
+ ), expect(
2191
+ () => getStateFromPath(path, {
2192
+ screens: {
2193
+ Foo: {
2194
+ screens: {
2195
+ Bar: {
2196
+ path: "/bar/:id/",
2197
+ screens: {
2198
+ Baz: ""
2199
+ }
2200
+ }
2201
+ }
2202
+ }
2203
+ }
2204
+ })
2205
+ ).not.toThrow();
2206
+ });
2207
+ test("correctly applies initialRouteName for config with similar route names", () => {
2208
+ const path = "/weekly-earnings", config = {
2209
+ screens: {
2210
+ RootTabs: {
2211
+ screens: {
2212
+ HomeTab: {
2213
+ screens: {
2214
+ Home: "",
2215
+ WeeklyEarnings: "weekly-earnings",
2216
+ EventDetails: "event-details/:eventId"
2217
+ }
2218
+ },
2219
+ EarningsTab: {
2220
+ initialRouteName: "Earnings",
2221
+ path: "earnings",
2222
+ screens: {
2223
+ Earnings: "",
2224
+ WeeklyEarnings: "weekly-earnings"
2225
+ }
2226
+ }
2227
+ }
2228
+ }
2229
+ }
2230
+ }, state = {
2231
+ routes: [
2232
+ {
2233
+ name: "RootTabs",
2234
+ state: {
2235
+ routes: [
2236
+ {
2237
+ name: "HomeTab",
2238
+ state: {
2239
+ routes: [
2240
+ {
2241
+ name: "WeeklyEarnings",
2242
+ path
2243
+ }
2244
+ ]
2245
+ }
2246
+ }
2247
+ ]
2248
+ }
2249
+ }
2250
+ ]
2251
+ };
2252
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
2253
+ getStateFromPath(getPathFromState(state, config), config)
2254
+ ).toEqual(state);
2255
+ });
2256
+ test("correctly applies initialRouteName for config with similar route names v2", () => {
2257
+ const path = "/earnings/weekly-earnings", config = {
2258
+ screens: {
2259
+ RootTabs: {
2260
+ screens: {
2261
+ HomeTab: {
2262
+ initialRouteName: "Home",
2263
+ screens: {
2264
+ Home: "",
2265
+ WeeklyEarnings: "weekly-earnings"
2266
+ }
2267
+ },
2268
+ EarningsTab: {
2269
+ initialRouteName: "Earnings",
2270
+ path: "earnings",
2271
+ screens: {
2272
+ Earnings: "",
2273
+ WeeklyEarnings: "weekly-earnings"
2274
+ }
2275
+ }
2276
+ }
2277
+ }
2278
+ }
2279
+ }, state = {
2280
+ routes: [
2281
+ {
2282
+ name: "RootTabs",
2283
+ state: {
2284
+ routes: [
2285
+ {
2286
+ name: "EarningsTab",
2287
+ state: {
2288
+ index: 1,
2289
+ routes: [
2290
+ {
2291
+ name: "Earnings"
2292
+ },
2293
+ {
2294
+ name: "WeeklyEarnings",
2295
+ path
2296
+ }
2297
+ ]
2298
+ }
2299
+ }
2300
+ ]
2301
+ }
2302
+ }
2303
+ ]
2304
+ };
2305
+ expect(getStateFromPath(path, config)).toEqual(state), expect(
2306
+ getStateFromPath(getPathFromState(state, config), config)
2307
+ ).toEqual(state);
2308
+ });
2309
+ test.skip("throws when invalid properties are specified in the config", () => {
2310
+ expect(
2311
+ () => getStateFromPath("", {
2312
+ path: 42,
2313
+ Foo: "foo",
2314
+ Bar: {
2315
+ path: "bar"
2316
+ }
2317
+ })
2318
+ ).toThrowErrorMatchingInlineSnapshot(`
2319
+ "Found invalid properties in the configuration:
2320
+ - path (expected 'string', got 'number')
2321
+ - Foo (extraneous)
2322
+ - Bar (extraneous)
2323
+
2324
+ You can only specify the following properties:
2325
+ - path (string)
2326
+ - initialRouteName (string)
2327
+ - screens (object)
2328
+
2329
+ If you want to specify configuration for screens, you need to specify them under a 'screens' property.
2330
+
2331
+ See https://reactnavigation.org/docs/configuring-links for more details on how to specify a linking configuration."
2332
+ `), expect(
2333
+ () => getStateFromPath("", {
2334
+ screens: {
2335
+ Foo: "foo",
2336
+ Bar: {
2337
+ path: "bar"
2338
+ },
2339
+ Baz: {
2340
+ Qux: {
2341
+ path: "qux"
2342
+ }
2343
+ }
2344
+ }
2345
+ })
2346
+ ).toThrowErrorMatchingInlineSnapshot(`
2347
+ "Found invalid properties in the configuration:
2348
+ - Qux (extraneous)
2349
+
2350
+ You can only specify the following properties:
2351
+ - path (string)
2352
+ - initialRouteName (string)
2353
+ - screens (object)
2354
+ - alias (array)
2355
+ - exact (boolean)
2356
+ - stringify (object)
2357
+ - parse (object)
2358
+
2359
+ If you want to specify configuration for screens, you need to specify them under a 'screens' property.
2360
+
2361
+ See https://reactnavigation.org/docs/configuring-links for more details on how to specify a linking configuration."
2362
+ `), expect(
2363
+ () => getStateFromPath("", {
2364
+ path: "foo/:id"
2365
+ })
2366
+ ).toThrowErrorMatchingInlineSnapshot(
2367
+ `"Found invalid path 'foo/:id'. The 'path' in the top-level configuration cannot contain patterns for params."`
2368
+ );
2369
+ });
2370
+ test.skip("encodes special characters in params", () => {
2371
+ const paramWithValidSymbols = "User09-A_Z~!$&'()*+,;=:@__", invalidSymbols = "#?[]{}%<>||", queryString = "user#email@gmail.com=2&4", path = `users/id/${paramWithValidSymbols}${encodeURIComponent(
2372
+ invalidSymbols
2373
+ )}?query=${encodeURIComponent(queryString)}`, config = {
2374
+ path: "users",
2375
+ screens: {
2376
+ Users: {
2377
+ screens: {
2378
+ User: "id/:id"
2379
+ }
2380
+ }
2381
+ }
2382
+ }, state = {
2383
+ routes: [
2384
+ {
2385
+ name: "Users",
2386
+ state: {
2387
+ routes: [
2388
+ {
2389
+ name: "User",
2390
+ params: {
2391
+ id: `${paramWithValidSymbols}${invalidSymbols}`,
2392
+ query: queryString
2393
+ }
2394
+ }
2395
+ ]
2396
+ }
2397
+ }
2398
+ ]
2399
+ };
2400
+ expect(getPathFromState(state, config)).toBe(`/${path}`), expect(getPathFromState(getStateFromPath(path, config), config)).toBe(
2401
+ `/${path}`
2402
+ );
2403
+ });
2404
+ test.skip("resolves nested path params with same name to correct screen", () => {
2405
+ const path = "/foo/42/bar/43", config = {
2406
+ initialRouteName: "Foo",
2407
+ screens: {
2408
+ Foo: {
2409
+ path: "foo/:id",
2410
+ screens: {
2411
+ Bar: {
2412
+ path: "bar/:id"
2413
+ }
2414
+ }
2415
+ }
2416
+ }
2417
+ }, state = {
2418
+ routes: [
2419
+ {
2420
+ name: "Foo",
2421
+ params: { id: "42" },
2422
+ state: {
2423
+ routes: [
2424
+ {
2425
+ name: "Bar",
2426
+ params: { id: "43" },
2427
+ path
2428
+ }
2429
+ ]
2430
+ }
2431
+ }
2432
+ ]
2433
+ };
2434
+ expect(getStateFromPath(path, config)).toEqual(state);
2435
+ });
2436
+ test("parses / same as empty string", () => {
2437
+ const config = {
2438
+ screens: {
2439
+ Foo: {
2440
+ path: "/"
2441
+ },
2442
+ Bar: {
2443
+ path: "bar"
2444
+ }
2445
+ }
2446
+ };
2447
+ expect(getStateFromPath("/", config)).toEqual(
2448
+ getStateFromPath("", config)
2449
+ );
2450
+ });
2451
+ test.skip("matches regexp patterns when provided", () => {
2452
+ const config = {
2453
+ screens: {
2454
+ Foo: {
2455
+ path: "foo/:id(\\d+)",
2456
+ parse: {
2457
+ id: Number
2458
+ }
2459
+ },
2460
+ Bar: {
2461
+ path: "foo/:id([a-z]+)"
2462
+ },
2463
+ Baz: {
2464
+ path: "foo/:id(\\d+)/:name([a-z]+)"
2465
+ },
2466
+ Qux: {
2467
+ path: "foo/:id(@[a-z]+)",
2468
+ parse: {
2469
+ id: (id) => id.slice(1)
2470
+ }
2471
+ },
2472
+ Quy: {
2473
+ path: "foo/bar/:category"
2474
+ },
2475
+ Quz: {
2476
+ path: "foo/bar/:special([a-z]+)"
2477
+ },
2478
+ Quu: {
2479
+ path: "foo/bar/baz"
2480
+ },
2481
+ NotFound: {
2482
+ path: "foo/bar/*"
2483
+ }
2484
+ }
2485
+ };
2486
+ expect(getStateFromPath("foo/42", config)).toEqual({
2487
+ routes: [
2488
+ {
2489
+ name: "Foo",
2490
+ params: { id: 42 },
2491
+ path: "foo/42"
2492
+ }
2493
+ ]
2494
+ }), expect(getStateFromPath("foo/bar", config)).toEqual({
2495
+ routes: [
2496
+ {
2497
+ name: "Bar",
2498
+ params: { id: "bar" },
2499
+ path: "foo/bar"
2500
+ }
2501
+ ]
2502
+ }), expect(getStateFromPath("foo/42/bar", config)).toEqual({
2503
+ routes: [
2504
+ {
2505
+ name: "Baz",
2506
+ params: { id: "42", name: "bar" },
2507
+ path: "foo/42/bar"
2508
+ }
2509
+ ]
2510
+ }), expect(getStateFromPath("foo/@bar", config)).toEqual({
2511
+ routes: [
2512
+ {
2513
+ name: "Qux",
2514
+ params: { id: "bar" },
2515
+ path: "foo/@bar"
2516
+ }
2517
+ ]
2518
+ }), expect(getStateFromPath("foo/@bar", config)).toEqual({
2519
+ routes: [
2520
+ {
2521
+ name: "Qux",
2522
+ params: { id: "bar" },
2523
+ path: "foo/@bar"
2524
+ }
2525
+ ]
2526
+ }), expect(getStateFromPath("foo/42a", config)).toBeUndefined(), expect(getStateFromPath("foo/bar/123", config)).toEqual({
2527
+ routes: [
2528
+ {
2529
+ name: "Quy",
2530
+ params: { category: "123" },
2531
+ path: "foo/bar/123"
2532
+ }
2533
+ ]
2534
+ }), expect(getStateFromPath("foo/bar/test", config)).toEqual({
2535
+ routes: [
2536
+ {
2537
+ name: "Quz",
2538
+ params: { special: "test" },
2539
+ path: "foo/bar/test"
2540
+ }
2541
+ ]
2542
+ }), expect(getStateFromPath("foo/bar/baz", config)).toEqual({
2543
+ routes: [
2544
+ {
2545
+ name: "Quu",
2546
+ path: "foo/bar/baz"
2547
+ }
2548
+ ]
2549
+ }), expect(getStateFromPath("foo/bar/hello/world", config)).toEqual({
2550
+ routes: [{ name: "NotFound", path: "foo/bar/hello/world" }]
2551
+ });
2552
+ });
2553
+ test("regexp pattern doesn't match slash", () => {
2554
+ const config = {
2555
+ screens: {
2556
+ Foo: {
2557
+ path: "foo/:id([a-z]+\\/)"
2558
+ }
2559
+ }
2560
+ };
2561
+ expect(getStateFromPath("foo/bar/", config)).toBeUndefined(), expect(getStateFromPath("foo/bar/baz", config)).toBeUndefined(), expect(getStateFromPath("foo/bar/baz/qux", config)).toBeUndefined();
2562
+ });
2563
+ test.skip("handles alias for paths", () => {
2564
+ const config = {
2565
+ screens: {
2566
+ Foo: {
2567
+ path: "foo",
2568
+ alias: ["first"],
2569
+ screens: {
2570
+ Baz: {
2571
+ path: "baz/:id?",
2572
+ parse: {
2573
+ id: (value) => value.replace(/@/, "")
2574
+ },
2575
+ alias: [
2576
+ {
2577
+ path: "second/:id",
2578
+ exact: !0
2579
+ },
2580
+ "third",
2581
+ {
2582
+ path: "fourth/:id",
2583
+ parse: {
2584
+ id: (value) => value.replace(/\$/, "")
2585
+ }
2586
+ }
2587
+ ]
2588
+ },
2589
+ Qux: {
2590
+ path: "qux/:id"
2591
+ }
2592
+ }
2593
+ }
2594
+ }
2595
+ };
2596
+ expect(getStateFromPath("foo", config)).toEqual({
2597
+ routes: [{ name: "Foo", path: "foo" }]
2598
+ }), expect(getPathFromState(getStateFromPath("foo", config), config)).toBe(
2599
+ "/foo"
2600
+ ), expect(getStateFromPath("first", config)).toEqual({
2601
+ routes: [{ name: "Foo", path: "first" }]
2602
+ }), expect(
2603
+ getPathFromState(getStateFromPath("first", config), config)
2604
+ ).toBe("/foo"), expect(getStateFromPath("foo/baz/@$test", config)).toEqual({
2605
+ routes: [
2606
+ {
2607
+ name: "Foo",
2608
+ state: {
2609
+ routes: [
2610
+ {
2611
+ name: "Baz",
2612
+ params: { id: "$test" },
2613
+ path: "foo/baz/@$test"
2614
+ }
2615
+ ]
2616
+ }
2617
+ }
2618
+ ]
2619
+ }), expect(
2620
+ getPathFromState(getStateFromPath("foo/baz/@$test", config), config)
2621
+ ).toBe("/foo/baz/$test"), expect(getStateFromPath("second/42", config)).toEqual({
2622
+ routes: [
2623
+ {
2624
+ name: "Foo",
2625
+ state: {
2626
+ routes: [
2627
+ {
2628
+ name: "Baz",
2629
+ params: { id: "42" },
2630
+ path: "second/42"
2631
+ }
2632
+ ]
2633
+ }
2634
+ }
2635
+ ]
2636
+ }), expect(
2637
+ getPathFromState(getStateFromPath("second/42", config), config)
2638
+ ).toBe("/foo/baz/42"), expect(getStateFromPath("foo/third", config)).toEqual({
2639
+ routes: [
2640
+ {
2641
+ name: "Foo",
2642
+ state: {
2643
+ routes: [
2644
+ {
2645
+ name: "Baz",
2646
+ path: "foo/third"
2647
+ }
2648
+ ]
2649
+ }
2650
+ }
2651
+ ]
2652
+ }), expect(
2653
+ getPathFromState(getStateFromPath("foo/third", config), config)
2654
+ ).toBe("/foo/baz"), expect(getStateFromPath("foo/fourth/@$test", config)).toEqual({
2655
+ routes: [
2656
+ {
2657
+ name: "Foo",
2658
+ state: {
2659
+ routes: [
2660
+ {
2661
+ name: "Baz",
2662
+ params: { id: "@test" },
2663
+ path: "foo/fourth/@$test"
2664
+ }
2665
+ ]
2666
+ }
2667
+ }
2668
+ ]
2669
+ }), expect(
2670
+ getPathFromState(
2671
+ getStateFromPath("foo/fourth/@$test", config),
2672
+ config
2673
+ )
2674
+ ).toBe("/foo/baz/@test"), expect(getStateFromPath("foo/qux/42", config)).toEqual({
2675
+ routes: [
2676
+ {
2677
+ name: "Foo",
2678
+ state: {
2679
+ routes: [
2680
+ {
2681
+ name: "Qux",
2682
+ params: { id: "42" },
2683
+ path: "foo/qux/42"
2684
+ }
2685
+ ]
2686
+ }
2687
+ }
2688
+ ]
2689
+ }), expect(
2690
+ getPathFromState(getStateFromPath("foo/qux/42", config), config)
2691
+ ).toBe("/foo/qux/42");
2692
+ });
2693
+ test.skip("throws if screen has alias but no path", () => {
2694
+ expect(
2695
+ () => getStateFromPath("", {
2696
+ screens: {
2697
+ Foo: {
2698
+ alias: ["bar"]
2699
+ }
2700
+ }
2701
+ })
2702
+ ).toThrow(
2703
+ "Screen 'Foo' doesn't specify a 'path'. A 'path' needs to be specified in order to use 'alias'."
2704
+ );
2705
+ });
2706
+ //# sourceMappingURL=getStateFromPath.test.js.map