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,1561 @@
1
+ import { expect, test } from "vitest";
2
+ import { getPathFromState } from "../getPathFromState";
3
+ import { getStateFromPath } from "../getStateFromPath";
4
+ test("converts state to path string", () => {
5
+ const state = {
6
+ routes: [
7
+ {
8
+ name: "foo",
9
+ state: {
10
+ index: 1,
11
+ routes: [
12
+ { name: "boo" },
13
+ {
14
+ name: "bar",
15
+ params: { fruit: "apple" },
16
+ state: {
17
+ routes: [
18
+ {
19
+ name: "baz qux",
20
+ params: { author: "jane", valid: !0 }
21
+ }
22
+ ]
23
+ }
24
+ }
25
+ ]
26
+ }
27
+ }
28
+ ]
29
+ }, path = "/foo/bar/baz%20qux?author=jane&valid=true";
30
+ expect(getPathFromState(state)).toBe(path), expect(getPathFromState(getStateFromPath(path))).toBe(path);
31
+ });
32
+ test("converts state to path string with config", () => {
33
+ const path = "/few/bar/sweet/apple/baz/jane?id=x10&valid=true", config = {
34
+ screens: {
35
+ Foo: {
36
+ path: "few",
37
+ screens: {
38
+ Bar: {
39
+ path: "bar/:type/:fruit",
40
+ screens: {
41
+ Baz: {
42
+ path: "baz/:author",
43
+ parse: {
44
+ author: (author) => author.replace(/^\w/, (c) => c.toUpperCase()),
45
+ id: (id) => Number(id.replace(/^x/, "")),
46
+ valid: Boolean
47
+ },
48
+ stringify: {
49
+ author: (author) => author.toLowerCase(),
50
+ id: (id) => `x${id}`
51
+ }
52
+ }
53
+ }
54
+ }
55
+ }
56
+ }
57
+ }
58
+ };
59
+ expect(getPathFromState({
60
+ routes: [
61
+ {
62
+ name: "Foo",
63
+ state: {
64
+ index: 1,
65
+ routes: [
66
+ { name: "boo" },
67
+ {
68
+ name: "Bar",
69
+ params: { fruit: "apple", type: "sweet", avaliable: !1 },
70
+ state: {
71
+ routes: [
72
+ {
73
+ name: "Baz",
74
+ params: {
75
+ author: "Jane",
76
+ id: 10,
77
+ valid: !0
78
+ }
79
+ }
80
+ ]
81
+ }
82
+ }
83
+ ]
84
+ }
85
+ }
86
+ ]
87
+ }, config)).toBe(path), expect(
88
+ getPathFromState(getStateFromPath(path, config), config)
89
+ ).toBe(path);
90
+ });
91
+ test("prepends trailing slash to path", () => {
92
+ expect(
93
+ getPathFromState({
94
+ routes: [
95
+ {
96
+ name: "foo",
97
+ state: {
98
+ routes: [{ name: "bar" }]
99
+ }
100
+ }
101
+ ]
102
+ })
103
+ ).toBe("/foo/bar"), expect(
104
+ getPathFromState({
105
+ routes: [
106
+ {
107
+ name: "foo",
108
+ state: {
109
+ routes: [{ name: "bar", path: "foo/bar" }]
110
+ }
111
+ }
112
+ ]
113
+ })
114
+ ).toBe("/foo/bar");
115
+ });
116
+ test("handles route without param", () => {
117
+ const path = "/foo/bar";
118
+ expect(getPathFromState({
119
+ routes: [
120
+ {
121
+ name: "foo",
122
+ state: {
123
+ routes: [{ name: "bar" }]
124
+ }
125
+ }
126
+ ]
127
+ })).toBe(path), expect(getPathFromState(getStateFromPath(path))).toBe(path);
128
+ });
129
+ test("doesn't add query param for empty params", () => {
130
+ const path = "/foo";
131
+ expect(getPathFromState({
132
+ routes: [
133
+ {
134
+ name: "foo",
135
+ params: {}
136
+ }
137
+ ]
138
+ })).toBe(path), expect(getPathFromState(getStateFromPath(path))).toBe(path);
139
+ });
140
+ test("handles state with config with nested screens", () => {
141
+ const path = "/foo/foe/bar/sweet/apple/baz/jane?answer=42&count=10&valid=true", config = {
142
+ screens: {
143
+ Foo: {
144
+ path: "foo",
145
+ screens: {
146
+ Foe: {
147
+ path: "foe",
148
+ screens: {
149
+ Bar: {
150
+ path: "bar/:type/:fruit",
151
+ screens: {
152
+ Baz: {
153
+ path: "baz/:author",
154
+ parse: {
155
+ author: (author) => author.replace(/^\w/, (c) => c.toUpperCase()),
156
+ count: Number,
157
+ valid: Boolean
158
+ },
159
+ stringify: {
160
+ author: (author) => author.toLowerCase(),
161
+ id: (id) => `x${id}`,
162
+ unknown: (_) => "x"
163
+ }
164
+ }
165
+ }
166
+ }
167
+ }
168
+ }
169
+ }
170
+ }
171
+ }
172
+ };
173
+ expect(getPathFromState({
174
+ routes: [
175
+ {
176
+ name: "Foo",
177
+ state: {
178
+ routes: [
179
+ {
180
+ name: "Foe",
181
+ state: {
182
+ routes: [
183
+ {
184
+ name: "Bar",
185
+ params: { fruit: "apple", type: "sweet" },
186
+ state: {
187
+ routes: [
188
+ {
189
+ name: "Baz",
190
+ params: {
191
+ answer: "42",
192
+ author: "Jane",
193
+ count: "10",
194
+ valid: !0
195
+ }
196
+ }
197
+ ]
198
+ }
199
+ }
200
+ ]
201
+ }
202
+ }
203
+ ]
204
+ }
205
+ }
206
+ ]
207
+ }, config)).toBe(path), expect(
208
+ getPathFromState(getStateFromPath(path, config), config)
209
+ ).toBe(path);
210
+ });
211
+ test("handles state with config with nested screens and exact", () => {
212
+ const path = "/foe/bar/sweet/apple/baz/jane?answer=42&count=10&valid=true", config = {
213
+ screens: {
214
+ Foo: {
215
+ path: "foo",
216
+ screens: {
217
+ Foe: {
218
+ path: "foe",
219
+ exact: !0,
220
+ screens: {
221
+ Bar: {
222
+ path: "bar/:type/:fruit",
223
+ screens: {
224
+ Baz: {
225
+ path: "baz/:author",
226
+ parse: {
227
+ author: (author) => author.replace(/^\w/, (c) => c.toUpperCase()),
228
+ count: Number,
229
+ valid: Boolean
230
+ },
231
+ stringify: {
232
+ author: (author) => author.toLowerCase(),
233
+ id: (id) => `x${id}`,
234
+ unknown: (_) => "x"
235
+ }
236
+ }
237
+ }
238
+ }
239
+ }
240
+ }
241
+ }
242
+ }
243
+ }
244
+ };
245
+ expect(getPathFromState({
246
+ routes: [
247
+ {
248
+ name: "Foo",
249
+ state: {
250
+ routes: [
251
+ {
252
+ name: "Foe",
253
+ state: {
254
+ routes: [
255
+ {
256
+ name: "Bar",
257
+ params: { fruit: "apple", type: "sweet" },
258
+ state: {
259
+ routes: [
260
+ {
261
+ name: "Baz",
262
+ params: {
263
+ answer: "42",
264
+ author: "Jane",
265
+ count: "10",
266
+ valid: !0
267
+ }
268
+ }
269
+ ]
270
+ }
271
+ }
272
+ ]
273
+ }
274
+ }
275
+ ]
276
+ }
277
+ }
278
+ ]
279
+ }, config)).toBe(path), expect(
280
+ getPathFromState(getStateFromPath(path, config), config)
281
+ ).toBe(path);
282
+ });
283
+ test("handles state with config with nested screens and unused configs", () => {
284
+ const path = "/foo/foe/baz/jane?answer=42&count=10&valid=true", config = {
285
+ screens: {
286
+ Foo: {
287
+ path: "foo",
288
+ screens: {
289
+ Foe: {
290
+ path: "foe",
291
+ screens: {
292
+ Baz: {
293
+ path: "baz/:author",
294
+ parse: {
295
+ author: (author) => author.replace(/^\w/, (c) => c.toUpperCase()),
296
+ count: Number,
297
+ valid: Boolean
298
+ },
299
+ stringify: {
300
+ author: (author) => author.replace(/^\w/, (c) => c.toLowerCase()),
301
+ unknown: (_) => "x"
302
+ }
303
+ }
304
+ }
305
+ }
306
+ }
307
+ }
308
+ }
309
+ };
310
+ expect(getPathFromState({
311
+ routes: [
312
+ {
313
+ name: "Foo",
314
+ state: {
315
+ routes: [
316
+ {
317
+ name: "Foe",
318
+ state: {
319
+ routes: [
320
+ {
321
+ name: "Baz",
322
+ params: {
323
+ answer: "42",
324
+ author: "Jane",
325
+ count: 10,
326
+ valid: !0
327
+ }
328
+ }
329
+ ]
330
+ }
331
+ }
332
+ ]
333
+ }
334
+ }
335
+ ]
336
+ }, config)).toBe(path), expect(
337
+ getPathFromState(getStateFromPath(path, config), config)
338
+ ).toBe(path);
339
+ });
340
+ test("handles state with config with nested screens and unused configs with exact", () => {
341
+ const path = "/foe/baz/jane?answer=42&count=10&valid=true", config = {
342
+ screens: {
343
+ Foo: {
344
+ path: "foo",
345
+ screens: {
346
+ Foe: {
347
+ path: "foe",
348
+ exact: !0,
349
+ screens: {
350
+ Baz: {
351
+ path: "baz/:author",
352
+ parse: {
353
+ author: (author) => author.replace(/^\w/, (c) => c.toUpperCase()),
354
+ count: Number,
355
+ valid: Boolean
356
+ },
357
+ stringify: {
358
+ author: (author) => author.replace(/^\w/, (c) => c.toLowerCase()),
359
+ unknown: (_) => "x"
360
+ }
361
+ }
362
+ }
363
+ }
364
+ }
365
+ }
366
+ }
367
+ };
368
+ expect(getPathFromState({
369
+ routes: [
370
+ {
371
+ name: "Foo",
372
+ state: {
373
+ routes: [
374
+ {
375
+ name: "Foe",
376
+ state: {
377
+ routes: [
378
+ {
379
+ name: "Baz",
380
+ params: {
381
+ answer: "42",
382
+ author: "Jane",
383
+ count: 10,
384
+ valid: !0
385
+ }
386
+ }
387
+ ]
388
+ }
389
+ }
390
+ ]
391
+ }
392
+ }
393
+ ]
394
+ }, config)).toBe(path), expect(
395
+ getPathFromState(getStateFromPath(path, config), config)
396
+ ).toBe(path);
397
+ });
398
+ test("handles nested object with stringify in it", () => {
399
+ const path = "/bar/sweet/apple/foo/bis/jane?answer=42&count=10&valid=true", config = {
400
+ screens: {
401
+ Bar: {
402
+ path: "bar/:type/:fruit",
403
+ screens: {
404
+ Foo: {
405
+ path: "foo",
406
+ screens: {
407
+ Foe: {
408
+ path: "foe"
409
+ },
410
+ Baz: {
411
+ screens: {
412
+ Bos: "bos",
413
+ Bis: {
414
+ path: "bis/:author",
415
+ stringify: {
416
+ author: (author) => author.replace(/^\w/, (c) => c.toLowerCase())
417
+ },
418
+ parse: {
419
+ author: (author) => author.replace(/^\w/, (c) => c.toUpperCase()),
420
+ count: Number,
421
+ valid: Boolean
422
+ }
423
+ }
424
+ }
425
+ }
426
+ }
427
+ }
428
+ }
429
+ }
430
+ }
431
+ };
432
+ expect(getPathFromState({
433
+ routes: [
434
+ {
435
+ name: "Bar",
436
+ params: { fruit: "apple", type: "sweet" },
437
+ state: {
438
+ routes: [
439
+ {
440
+ name: "Foo",
441
+ state: {
442
+ routes: [
443
+ {
444
+ name: "Baz",
445
+ state: {
446
+ routes: [
447
+ {
448
+ name: "Bis",
449
+ params: {
450
+ answer: "42",
451
+ author: "Jane",
452
+ count: 10,
453
+ valid: !0
454
+ }
455
+ }
456
+ ]
457
+ }
458
+ }
459
+ ]
460
+ }
461
+ }
462
+ ]
463
+ }
464
+ }
465
+ ]
466
+ }, config)).toBe(path), expect(
467
+ getPathFromState(getStateFromPath(path, config), config)
468
+ ).toBe(path);
469
+ });
470
+ test("handles nested object with stringify in it with exact", () => {
471
+ const path = "/bis/jane?answer=42&count=10&valid=true", config = {
472
+ screens: {
473
+ Bar: {
474
+ path: "bar/:type/:fruit",
475
+ screens: {
476
+ Foo: {
477
+ path: "foo",
478
+ screens: {
479
+ Foe: {
480
+ path: "foe"
481
+ },
482
+ Baz: {
483
+ path: "baz",
484
+ screens: {
485
+ Bos: "bos",
486
+ Bis: {
487
+ path: "bis/:author",
488
+ exact: !0,
489
+ stringify: {
490
+ author: (author) => author.replace(/^\w/, (c) => c.toLowerCase())
491
+ },
492
+ parse: {
493
+ author: (author) => author.replace(/^\w/, (c) => c.toUpperCase()),
494
+ count: Number,
495
+ valid: Boolean
496
+ }
497
+ }
498
+ }
499
+ }
500
+ }
501
+ }
502
+ }
503
+ }
504
+ }
505
+ };
506
+ expect(getPathFromState({
507
+ routes: [
508
+ {
509
+ name: "Bar",
510
+ params: { fruit: "apple", type: "sweet" },
511
+ state: {
512
+ routes: [
513
+ {
514
+ name: "Foo",
515
+ state: {
516
+ routes: [
517
+ {
518
+ name: "Baz",
519
+ state: {
520
+ routes: [
521
+ {
522
+ name: "Bis",
523
+ params: {
524
+ answer: "42",
525
+ author: "Jane",
526
+ count: 10,
527
+ valid: !0
528
+ }
529
+ }
530
+ ]
531
+ }
532
+ }
533
+ ]
534
+ }
535
+ }
536
+ ]
537
+ }
538
+ }
539
+ ]
540
+ }, config)).toBe(path), expect(
541
+ getPathFromState(getStateFromPath(path, config), config)
542
+ ).toBe(path);
543
+ });
544
+ test("handles nested object for second route depth", () => {
545
+ const path = "/foo/bar/baz", config = {
546
+ screens: {
547
+ Foo: {
548
+ path: "foo",
549
+ screens: {
550
+ Foe: "foe",
551
+ Bar: {
552
+ path: "bar",
553
+ screens: {
554
+ Baz: "baz"
555
+ }
556
+ }
557
+ }
558
+ }
559
+ }
560
+ };
561
+ expect(getPathFromState({
562
+ routes: [
563
+ {
564
+ name: "Foo",
565
+ state: {
566
+ routes: [
567
+ {
568
+ name: "Bar",
569
+ state: {
570
+ routes: [{ name: "Baz" }]
571
+ }
572
+ }
573
+ ]
574
+ }
575
+ }
576
+ ]
577
+ }, config)).toBe(path), expect(
578
+ getPathFromState(getStateFromPath(path, config), config)
579
+ ).toBe(path);
580
+ });
581
+ test("handles nested object for second route depth with exact", () => {
582
+ const path = "/baz", config = {
583
+ screens: {
584
+ Foo: {
585
+ path: "foo",
586
+ screens: {
587
+ Foe: "foe",
588
+ Bar: {
589
+ path: "bar",
590
+ screens: {
591
+ Baz: {
592
+ path: "baz",
593
+ exact: !0
594
+ }
595
+ }
596
+ }
597
+ }
598
+ }
599
+ }
600
+ };
601
+ expect(getPathFromState({
602
+ routes: [
603
+ {
604
+ name: "Foo",
605
+ state: {
606
+ routes: [
607
+ {
608
+ name: "Bar",
609
+ state: {
610
+ routes: [{ name: "Baz" }]
611
+ }
612
+ }
613
+ ]
614
+ }
615
+ }
616
+ ]
617
+ }, config)).toBe(path), expect(
618
+ getPathFromState(getStateFromPath(path, config), config)
619
+ ).toBe(path);
620
+ });
621
+ test("handles nested object for second route depth and path and stringify in roots", () => {
622
+ const path = "/foo/dathomir/bar/42/baz", config = {
623
+ screens: {
624
+ Foo: {
625
+ path: "foo/:planet",
626
+ stringify: {
627
+ id: (id) => `planet=${id}`
628
+ },
629
+ screens: {
630
+ Foe: "foe",
631
+ Bar: {
632
+ path: "bar/:id",
633
+ parse: {
634
+ id: Number
635
+ },
636
+ screens: {
637
+ Baz: "baz"
638
+ }
639
+ }
640
+ }
641
+ }
642
+ }
643
+ };
644
+ expect(getPathFromState({
645
+ routes: [
646
+ {
647
+ name: "Foo",
648
+ params: { planet: "dathomir" },
649
+ state: {
650
+ routes: [
651
+ {
652
+ name: "Bar",
653
+ state: {
654
+ routes: [{ name: "Baz", params: { id: 42 } }]
655
+ }
656
+ }
657
+ ]
658
+ }
659
+ }
660
+ ]
661
+ }, config)).toBe(path), expect(
662
+ getPathFromState(getStateFromPath(path, config), config)
663
+ ).toBe(path);
664
+ });
665
+ test("handles nested object for second route depth and path and stringify in roots with exact", () => {
666
+ const path = "/baz", config = {
667
+ screens: {
668
+ Foo: {
669
+ path: "foo/:id",
670
+ stringify: {
671
+ id: (id) => `id=${id}`
672
+ },
673
+ screens: {
674
+ Foe: "foe",
675
+ Bar: {
676
+ path: "bar/:id",
677
+ stringify: {
678
+ id: (id) => `id=${id}`
679
+ },
680
+ parse: {
681
+ id: Number
682
+ },
683
+ screens: {
684
+ Baz: {
685
+ path: "baz",
686
+ exact: !0
687
+ }
688
+ }
689
+ }
690
+ }
691
+ }
692
+ }
693
+ };
694
+ expect(getPathFromState({
695
+ routes: [
696
+ {
697
+ name: "Foo",
698
+ state: {
699
+ routes: [
700
+ {
701
+ name: "Bar",
702
+ state: {
703
+ routes: [{ name: "Baz" }]
704
+ }
705
+ }
706
+ ]
707
+ }
708
+ }
709
+ ]
710
+ }, config)).toBe(path), expect(
711
+ getPathFromState(getStateFromPath(path, config), config)
712
+ ).toBe(path);
713
+ });
714
+ test("ignores empty string paths", () => {
715
+ const path = "/bar", config = {
716
+ screens: {
717
+ Foo: {
718
+ path: "",
719
+ screens: {
720
+ Foe: "foe"
721
+ }
722
+ },
723
+ Bar: "bar"
724
+ }
725
+ };
726
+ expect(getPathFromState({
727
+ routes: [
728
+ {
729
+ name: "Foo",
730
+ state: {
731
+ routes: [{ name: "Bar" }]
732
+ }
733
+ }
734
+ ]
735
+ }, config)).toBe(path), expect(
736
+ getPathFromState(getStateFromPath(path, config), config)
737
+ ).toBe(path);
738
+ });
739
+ test("keeps query params if path is empty", () => {
740
+ const path = "/?foo=42", config = {
741
+ screens: {
742
+ Foo: {
743
+ screens: {
744
+ Foe: "foe",
745
+ Bar: {
746
+ screens: {
747
+ Qux: {
748
+ path: "",
749
+ parse: { foo: Number }
750
+ },
751
+ Baz: "baz"
752
+ }
753
+ }
754
+ }
755
+ }
756
+ }
757
+ };
758
+ expect(getPathFromState({
759
+ routes: [
760
+ {
761
+ name: "Foo",
762
+ state: {
763
+ routes: [
764
+ {
765
+ name: "Bar",
766
+ state: {
767
+ routes: [{ name: "Qux", params: { foo: 42 } }]
768
+ }
769
+ }
770
+ ]
771
+ }
772
+ }
773
+ ]
774
+ }, config)).toBe(path), expect(
775
+ getPathFromState(getStateFromPath(path, config), config)
776
+ ).toEqual(path);
777
+ });
778
+ test("does not use Object.prototype properties as parsing functions", () => {
779
+ const path = "/?toString=42", config = {
780
+ screens: {
781
+ Foo: {
782
+ screens: {
783
+ Foe: "foe",
784
+ Bar: {
785
+ screens: {
786
+ Qux: {
787
+ path: "",
788
+ parse: {}
789
+ },
790
+ Baz: "baz"
791
+ }
792
+ }
793
+ }
794
+ }
795
+ }
796
+ };
797
+ expect(getPathFromState({
798
+ routes: [
799
+ {
800
+ name: "Foo",
801
+ state: {
802
+ routes: [
803
+ {
804
+ name: "Bar",
805
+ state: {
806
+ routes: [{ name: "Qux", params: { toString: 42 } }]
807
+ }
808
+ }
809
+ ]
810
+ }
811
+ }
812
+ ]
813
+ }, config)).toBe(path), expect(
814
+ getPathFromState(getStateFromPath(path, config), config)
815
+ ).toEqual(path);
816
+ });
817
+ test("cuts nested configs too", () => {
818
+ const path = "/foo/baz", config = {
819
+ screens: {
820
+ Foo: {
821
+ path: "foo",
822
+ screens: {
823
+ Bar: {
824
+ path: "",
825
+ screens: {
826
+ Baz: {
827
+ path: "baz"
828
+ }
829
+ }
830
+ }
831
+ }
832
+ }
833
+ }
834
+ };
835
+ expect(getPathFromState({
836
+ routes: [
837
+ {
838
+ name: "Foo",
839
+ state: {
840
+ routes: [
841
+ {
842
+ name: "Bar",
843
+ state: {
844
+ routes: [{ name: "Baz" }]
845
+ }
846
+ }
847
+ ]
848
+ }
849
+ }
850
+ ]
851
+ }, config)).toBe(path), expect(
852
+ getPathFromState(getStateFromPath(path, config), config)
853
+ ).toBe(path);
854
+ });
855
+ test("cuts nested configs too with exact", () => {
856
+ const path = "/baz", config = {
857
+ screens: {
858
+ Foo: {
859
+ path: "foo",
860
+ screens: {
861
+ Bar: {
862
+ path: "",
863
+ exact: !0,
864
+ screens: {
865
+ Baz: {
866
+ path: "baz"
867
+ }
868
+ }
869
+ }
870
+ }
871
+ }
872
+ }
873
+ };
874
+ expect(getPathFromState({
875
+ routes: [
876
+ {
877
+ name: "Foo",
878
+ state: {
879
+ routes: [
880
+ {
881
+ name: "Bar",
882
+ state: {
883
+ routes: [{ name: "Baz" }]
884
+ }
885
+ }
886
+ ]
887
+ }
888
+ }
889
+ ]
890
+ }, config)).toBe(path), expect(
891
+ getPathFromState(getStateFromPath(path, config), config)
892
+ ).toBe(path);
893
+ });
894
+ test("handles empty path at the end", () => {
895
+ const path = "/foo/bar", config = {
896
+ screens: {
897
+ Foo: {
898
+ path: "foo",
899
+ screens: {
900
+ Bar: "bar"
901
+ }
902
+ },
903
+ Baz: { path: "" }
904
+ }
905
+ };
906
+ expect(getPathFromState({
907
+ routes: [
908
+ {
909
+ name: "Foo",
910
+ state: {
911
+ routes: [
912
+ {
913
+ name: "Bar",
914
+ state: {
915
+ routes: [{ name: "Baz" }]
916
+ }
917
+ }
918
+ ]
919
+ }
920
+ }
921
+ ]
922
+ }, config)).toBe(path), expect(
923
+ getPathFromState(getStateFromPath(path, config), config)
924
+ ).toBe(path);
925
+ });
926
+ test('returns "/" for empty path', () => {
927
+ const path = "/", config = {
928
+ screens: {
929
+ Foo: {
930
+ path: "",
931
+ screens: {
932
+ Bar: ""
933
+ }
934
+ }
935
+ }
936
+ };
937
+ expect(getPathFromState({
938
+ routes: [
939
+ {
940
+ name: "Foo",
941
+ state: {
942
+ routes: [
943
+ {
944
+ name: "Bar"
945
+ }
946
+ ]
947
+ }
948
+ }
949
+ ]
950
+ }, config)).toBe(path), expect(
951
+ getPathFromState(getStateFromPath(path, config), config)
952
+ ).toBe(path);
953
+ });
954
+ test("parses no path specified", () => {
955
+ const path = "/bar", config = {
956
+ screens: {
957
+ Foo: {
958
+ screens: {
959
+ Foe: {},
960
+ Bar: "bar"
961
+ }
962
+ }
963
+ }
964
+ };
965
+ expect(getPathFromState({
966
+ routes: [
967
+ {
968
+ name: "Foo",
969
+ state: {
970
+ routes: [{ name: "Bar" }]
971
+ }
972
+ }
973
+ ]
974
+ }, config)).toBe(path), expect(
975
+ getPathFromState(getStateFromPath(path, config), config)
976
+ ).toBe(path);
977
+ });
978
+ test("strips undefined query params", () => {
979
+ const path = "/bar/sweet/apple/foo/bis/jane?count=10&valid=true", config = {
980
+ screens: {
981
+ Bar: {
982
+ path: "bar/:type/:fruit",
983
+ screens: {
984
+ Foo: {
985
+ path: "foo",
986
+ screens: {
987
+ Foe: {
988
+ path: "foe"
989
+ },
990
+ Baz: {
991
+ screens: {
992
+ Bos: "bos",
993
+ Bis: {
994
+ path: "bis/:author",
995
+ stringify: {
996
+ author: (author) => author.replace(/^\w/, (c) => c.toLowerCase())
997
+ },
998
+ parse: {
999
+ author: (author) => author.replace(/^\w/, (c) => c.toUpperCase()),
1000
+ count: Number,
1001
+ valid: Boolean
1002
+ }
1003
+ }
1004
+ }
1005
+ }
1006
+ }
1007
+ }
1008
+ }
1009
+ }
1010
+ }
1011
+ };
1012
+ expect(getPathFromState({
1013
+ routes: [
1014
+ {
1015
+ name: "Bar",
1016
+ params: { fruit: "apple", type: "sweet" },
1017
+ state: {
1018
+ routes: [
1019
+ {
1020
+ name: "Foo",
1021
+ state: {
1022
+ routes: [
1023
+ {
1024
+ name: "Baz",
1025
+ state: {
1026
+ routes: [
1027
+ {
1028
+ name: "Bis",
1029
+ params: {
1030
+ author: "Jane",
1031
+ count: 10,
1032
+ valid: !0
1033
+ }
1034
+ }
1035
+ ]
1036
+ }
1037
+ }
1038
+ ]
1039
+ }
1040
+ }
1041
+ ]
1042
+ }
1043
+ }
1044
+ ]
1045
+ }, config)).toBe(path), expect(
1046
+ getPathFromState(getStateFromPath(path, config), config)
1047
+ ).toBe(path);
1048
+ });
1049
+ test("strips undefined query params with exact", () => {
1050
+ const path = "/bis/jane?count=10&valid=true", config = {
1051
+ screens: {
1052
+ Bar: {
1053
+ path: "bar/:type/:fruit",
1054
+ screens: {
1055
+ Foo: {
1056
+ path: "foo",
1057
+ screens: {
1058
+ Foe: {
1059
+ path: "foe"
1060
+ },
1061
+ Baz: {
1062
+ screens: {
1063
+ Bos: "bos",
1064
+ Bis: {
1065
+ path: "bis/:author",
1066
+ exact: !0,
1067
+ stringify: {
1068
+ author: (author) => author.replace(/^\w/, (c) => c.toLowerCase())
1069
+ },
1070
+ parse: {
1071
+ author: (author) => author.replace(/^\w/, (c) => c.toUpperCase()),
1072
+ count: Number,
1073
+ valid: Boolean
1074
+ }
1075
+ }
1076
+ }
1077
+ }
1078
+ }
1079
+ }
1080
+ }
1081
+ }
1082
+ }
1083
+ };
1084
+ expect(getPathFromState({
1085
+ routes: [
1086
+ {
1087
+ name: "Bar",
1088
+ params: { fruit: "apple", type: "sweet" },
1089
+ state: {
1090
+ routes: [
1091
+ {
1092
+ name: "Foo",
1093
+ state: {
1094
+ routes: [
1095
+ {
1096
+ name: "Baz",
1097
+ state: {
1098
+ routes: [
1099
+ {
1100
+ name: "Bis",
1101
+ params: {
1102
+ author: "Jane",
1103
+ count: 10,
1104
+ valid: !0
1105
+ }
1106
+ }
1107
+ ]
1108
+ }
1109
+ }
1110
+ ]
1111
+ }
1112
+ }
1113
+ ]
1114
+ }
1115
+ }
1116
+ ]
1117
+ }, config)).toBe(path), expect(
1118
+ getPathFromState(getStateFromPath(path, config), config)
1119
+ ).toBe(path);
1120
+ });
1121
+ test("handles stripping all query params", () => {
1122
+ const path = "/bar/sweet/apple/foo/bis/jane", config = {
1123
+ screens: {
1124
+ Bar: {
1125
+ path: "bar/:type/:fruit",
1126
+ screens: {
1127
+ Foo: {
1128
+ path: "foo",
1129
+ screens: {
1130
+ Foe: {
1131
+ path: "foe"
1132
+ },
1133
+ Baz: {
1134
+ screens: {
1135
+ Bos: "bos",
1136
+ Bis: {
1137
+ path: "bis/:author",
1138
+ stringify: {
1139
+ author: (author) => author.replace(/^\w/, (c) => c.toLowerCase())
1140
+ },
1141
+ parse: {
1142
+ author: (author) => author.replace(/^\w/, (c) => c.toUpperCase()),
1143
+ count: Number,
1144
+ valid: Boolean
1145
+ }
1146
+ }
1147
+ }
1148
+ }
1149
+ }
1150
+ }
1151
+ }
1152
+ }
1153
+ }
1154
+ };
1155
+ expect(getPathFromState({
1156
+ routes: [
1157
+ {
1158
+ name: "Bar",
1159
+ params: { fruit: "apple", type: "sweet" },
1160
+ state: {
1161
+ routes: [
1162
+ {
1163
+ name: "Foo",
1164
+ state: {
1165
+ routes: [
1166
+ {
1167
+ name: "Baz",
1168
+ state: {
1169
+ routes: [
1170
+ {
1171
+ name: "Bis",
1172
+ params: {
1173
+ author: "Jane"
1174
+ }
1175
+ }
1176
+ ]
1177
+ }
1178
+ }
1179
+ ]
1180
+ }
1181
+ }
1182
+ ]
1183
+ }
1184
+ }
1185
+ ]
1186
+ }, config)).toBe(path), expect(
1187
+ getPathFromState(getStateFromPath(path, config), config)
1188
+ ).toBe(path);
1189
+ });
1190
+ test("handles stripping all query params with exact", () => {
1191
+ const path = "/bis/jane", config = {
1192
+ screens: {
1193
+ Bar: {
1194
+ path: "bar/:type/:fruit",
1195
+ screens: {
1196
+ Foo: {
1197
+ path: "foo",
1198
+ screens: {
1199
+ Foe: {
1200
+ path: "foe"
1201
+ },
1202
+ Baz: {
1203
+ path: "baz",
1204
+ screens: {
1205
+ Bos: "bos",
1206
+ Bis: {
1207
+ path: "bis/:author",
1208
+ exact: !0,
1209
+ stringify: {
1210
+ author: (author) => author.replace(/^\w/, (c) => c.toLowerCase())
1211
+ },
1212
+ parse: {
1213
+ author: (author) => author.replace(/^\w/, (c) => c.toUpperCase()),
1214
+ count: Number,
1215
+ valid: Boolean
1216
+ }
1217
+ }
1218
+ }
1219
+ }
1220
+ }
1221
+ }
1222
+ }
1223
+ }
1224
+ }
1225
+ };
1226
+ expect(getPathFromState({
1227
+ routes: [
1228
+ {
1229
+ name: "Bar",
1230
+ params: { fruit: "apple", type: "sweet" },
1231
+ state: {
1232
+ routes: [
1233
+ {
1234
+ name: "Foo",
1235
+ state: {
1236
+ routes: [
1237
+ {
1238
+ name: "Baz",
1239
+ state: {
1240
+ routes: [
1241
+ {
1242
+ name: "Bis",
1243
+ params: {
1244
+ author: "Jane"
1245
+ }
1246
+ }
1247
+ ]
1248
+ }
1249
+ }
1250
+ ]
1251
+ }
1252
+ }
1253
+ ]
1254
+ }
1255
+ }
1256
+ ]
1257
+ }, config)).toBe(path), expect(
1258
+ getPathFromState(getStateFromPath(path, config), config)
1259
+ ).toBe(path);
1260
+ });
1261
+ test("replaces undefined query params", () => {
1262
+ const path = "/bar/undefined/apple", config = {
1263
+ screens: {
1264
+ Bar: "bar/:type/:fruit"
1265
+ }
1266
+ };
1267
+ expect(getPathFromState({
1268
+ routes: [
1269
+ {
1270
+ name: "Bar",
1271
+ params: { fruit: "apple" }
1272
+ }
1273
+ ]
1274
+ }, config)).toBe(path), expect(
1275
+ getPathFromState(getStateFromPath(path, config), config)
1276
+ ).toBe(path);
1277
+ });
1278
+ test.skip("matches wildcard patterns at root", () => {
1279
+ const path = "/test/bar/42/whatever", config = {
1280
+ screens: {
1281
+ 404: "*",
1282
+ Foo: {
1283
+ screens: {
1284
+ Bar: {
1285
+ path: "/bar/:id/"
1286
+ }
1287
+ }
1288
+ }
1289
+ }
1290
+ };
1291
+ expect(getPathFromState({
1292
+ routes: [{ name: "404" }]
1293
+ }, config)).toBe("/404"), expect(
1294
+ getPathFromState(getStateFromPath(path, config), config)
1295
+ ).toBe("/404");
1296
+ });
1297
+ test.skip("matches wildcard patterns at nested level", () => {
1298
+ const path = "/bar/42/whatever/baz/initt", config = {
1299
+ screens: {
1300
+ Foo: {
1301
+ screens: {
1302
+ Bar: {
1303
+ path: "/bar/:id/",
1304
+ screens: {
1305
+ 404: "*"
1306
+ }
1307
+ }
1308
+ }
1309
+ }
1310
+ }
1311
+ };
1312
+ expect(getPathFromState({
1313
+ routes: [
1314
+ {
1315
+ name: "Foo",
1316
+ state: {
1317
+ routes: [
1318
+ {
1319
+ name: "Bar",
1320
+ params: { id: "42" },
1321
+ state: {
1322
+ routes: [{ name: "404" }]
1323
+ }
1324
+ }
1325
+ ]
1326
+ }
1327
+ }
1328
+ ]
1329
+ }, config)).toBe("/bar/42/404"), expect(
1330
+ getPathFromState(getStateFromPath(path, config), config)
1331
+ ).toBe("/bar/42/404");
1332
+ });
1333
+ test.skip("matches wildcard patterns at nested level with exact", () => {
1334
+ const path = "/whatever", config = {
1335
+ screens: {
1336
+ Foo: {
1337
+ screens: {
1338
+ Bar: {
1339
+ path: "/bar/:id/",
1340
+ screens: {
1341
+ 404: {
1342
+ path: "*",
1343
+ exact: !0
1344
+ }
1345
+ }
1346
+ },
1347
+ Baz: {}
1348
+ }
1349
+ }
1350
+ }
1351
+ };
1352
+ expect(getPathFromState({
1353
+ routes: [
1354
+ {
1355
+ name: "Foo",
1356
+ state: {
1357
+ routes: [
1358
+ {
1359
+ name: "Bar",
1360
+ state: {
1361
+ routes: [{ name: "404" }]
1362
+ }
1363
+ }
1364
+ ]
1365
+ }
1366
+ }
1367
+ ]
1368
+ }, config)).toBe("/404"), expect(
1369
+ getPathFromState(getStateFromPath(path, config), config)
1370
+ ).toBe("/404");
1371
+ });
1372
+ test("tries to match wildcard patterns at the end", () => {
1373
+ const path = "/bar/42/test", config = {
1374
+ screens: {
1375
+ Foo: {
1376
+ screens: {
1377
+ Bar: {
1378
+ path: "/bar/:id/",
1379
+ screens: {
1380
+ 404: "*",
1381
+ Test: "test"
1382
+ }
1383
+ }
1384
+ }
1385
+ }
1386
+ }
1387
+ };
1388
+ expect(getPathFromState({
1389
+ routes: [
1390
+ {
1391
+ name: "Foo",
1392
+ state: {
1393
+ routes: [
1394
+ {
1395
+ name: "Bar",
1396
+ params: { id: "42" },
1397
+ state: {
1398
+ routes: [{ name: "Test" }]
1399
+ }
1400
+ }
1401
+ ]
1402
+ }
1403
+ }
1404
+ ]
1405
+ }, config)).toBe(path), expect(
1406
+ getPathFromState(getStateFromPath(path, config), config)
1407
+ ).toBe(path);
1408
+ });
1409
+ test.skip("uses nearest parent wildcard match for unmatched paths", () => {
1410
+ const path = "/bar/42/baz/test", config = {
1411
+ screens: {
1412
+ Foo: {
1413
+ screens: {
1414
+ Bar: {
1415
+ path: "/bar/:id/",
1416
+ screens: {
1417
+ Baz: "baz"
1418
+ }
1419
+ },
1420
+ 404: "*"
1421
+ }
1422
+ }
1423
+ }
1424
+ };
1425
+ expect(getPathFromState({
1426
+ routes: [
1427
+ {
1428
+ name: "Foo",
1429
+ state: {
1430
+ routes: [{ name: "404" }]
1431
+ }
1432
+ }
1433
+ ]
1434
+ }, config)).toBe("/404"), expect(
1435
+ getPathFromState(getStateFromPath(path, config), config)
1436
+ ).toBe("/404");
1437
+ });
1438
+ test.skip("handles path at top level", () => {
1439
+ const path = "foo/fruits/apple", config = {
1440
+ path: "foo",
1441
+ screens: {
1442
+ Foo: {
1443
+ screens: {
1444
+ Fruits: "fruits/:fruit"
1445
+ }
1446
+ }
1447
+ }
1448
+ };
1449
+ expect(getPathFromState({
1450
+ routes: [
1451
+ {
1452
+ name: "Foo",
1453
+ state: {
1454
+ routes: [
1455
+ {
1456
+ name: "Fruits",
1457
+ params: { fruit: "apple" }
1458
+ }
1459
+ ]
1460
+ }
1461
+ }
1462
+ ]
1463
+ }, config)).toBe(`/${path}`), expect(getPathFromState(getStateFromPath(path, config), config)).toBe(
1464
+ `/${path}`
1465
+ );
1466
+ });
1467
+ test.skip("ignores regexp patterns when provided", () => {
1468
+ const config = {
1469
+ screens: {
1470
+ Foo: {
1471
+ path: "foo/:id(\\d+)",
1472
+ parse: {
1473
+ id: Number
1474
+ }
1475
+ },
1476
+ Bar: {
1477
+ path: "foo/:id([a-z]+)"
1478
+ },
1479
+ Baz: {
1480
+ path: "foo/:id(\\d+)/:name([a-z]+)"
1481
+ },
1482
+ Qux: {
1483
+ path: "foo/:id(@[a-z]+)",
1484
+ stringify: {
1485
+ id: (id) => `@${id}`
1486
+ }
1487
+ }
1488
+ }
1489
+ };
1490
+ expect(
1491
+ getPathFromState(
1492
+ {
1493
+ routes: [
1494
+ {
1495
+ name: "Foo",
1496
+ params: { id: 42 }
1497
+ }
1498
+ ]
1499
+ },
1500
+ config
1501
+ )
1502
+ ).toBe("/foo/42"), expect(
1503
+ getPathFromState(
1504
+ {
1505
+ routes: [
1506
+ {
1507
+ name: "Bar",
1508
+ params: { id: "bar" }
1509
+ }
1510
+ ]
1511
+ },
1512
+ config
1513
+ )
1514
+ ).toBe("/foo/bar"), expect(
1515
+ getPathFromState(
1516
+ {
1517
+ routes: [
1518
+ {
1519
+ name: "Baz",
1520
+ params: { id: 42, name: "bar" }
1521
+ }
1522
+ ]
1523
+ },
1524
+ config
1525
+ )
1526
+ ).toBe("/foo/42/bar"), expect(
1527
+ getPathFromState(
1528
+ {
1529
+ routes: [
1530
+ {
1531
+ name: "Qux",
1532
+ params: { id: "bar" }
1533
+ }
1534
+ ]
1535
+ },
1536
+ config
1537
+ )
1538
+ ).toBe("/foo/@bar");
1539
+ });
1540
+ test.skip("correctly handles regex pattern with slash", () => {
1541
+ expect(
1542
+ getPathFromState(
1543
+ {
1544
+ routes: [
1545
+ {
1546
+ name: "Foo",
1547
+ params: { id: "bar" }
1548
+ }
1549
+ ]
1550
+ },
1551
+ {
1552
+ screens: {
1553
+ Foo: {
1554
+ path: "foo/:id([a-z]+\\/)"
1555
+ }
1556
+ }
1557
+ }
1558
+ )
1559
+ ).toBe("/foo/bar");
1560
+ });
1561
+ //# sourceMappingURL=getPathFromState.test.js.map