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