UNPKG

one

Version:

One is a new React Framework that makes Vite serve both native and web.

2,262 lines (2,261 loc) 60.1 kB
import { produce } from "immer"; import { expect, test } from "vitest"; import { findFocusedRoute } from "../findFocusedRoute.mjs"; import { getPathFromState } from "../getPathFromState.mjs"; import { getStateFromPath } from "../getStateFromPath.mjs"; const changePath = (state, path) => produce(state, draftState => { const route = findFocusedRoute(draftState); route.path = path; }); test("returns undefined for invalid path", () => { expect(getStateFromPath("//")).toBeUndefined(); }); test.skip("converts path string to initial state", () => { const path = "foo/bar/baz%20qux?author=jane%20%26%20co&valid=true"; const state = { routes: [{ name: "foo", state: { routes: [{ name: "bar", state: { routes: [{ name: "baz qux", params: { author: "jane & co", valid: "true" }, path }] } }] } }] }; expect(getStateFromPath(path)).toEqual(state); expect(getStateFromPath(getPathFromState(state))).toEqual(changePath(state, "/foo/bar/baz%20qux?author=jane%20%26%20co&valid=true")); }); test.skip("decodes encoded params in path", () => { const path = "/foo/bar/bar_%23_foo"; const config = { screens: { Foo: { path: "foo", screens: { Bar: { path: "/bar/:id" } } } } }; const state = { routes: [{ name: "Foo", state: { routes: [{ name: "Bar", params: { id: "bar_#_foo" }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getPathFromState(getStateFromPath(path, config), config)).toEqual(path); }); test.skip("decodes encoded params in path that have encoded /", () => { const path = "/foo/bar/bar_%2F_foo"; const config = { screens: { Foo: { path: "foo", screens: { Bar: { path: "/bar/:id" } } } } }; const state = { routes: [{ name: "Foo", state: { routes: [{ name: "Bar", params: { id: "bar_/_foo" }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getPathFromState(getStateFromPath(path, config), config)).toEqual(path); }); test.skip("converts path string to initial state with config", () => { const path = "/foo/bar/sweet/apple/baz/jane?count=10&answer=42&valid=true"; const config = { screens: { Foo: { path: "foo", screens: { Bar: { path: "bar/:type/:fruit", screens: { Baz: { path: "baz/:author", parse: { author: author => author.replace(/^\w/, c => c.toUpperCase()), count: Number, valid: Boolean }, stringify: { author: author => author.toLowerCase() } } } } } } } }; const state = { routes: [{ name: "Foo", state: { routes: [{ name: "Bar", params: { fruit: "apple", type: "sweet" }, state: { routes: [{ name: "Baz", params: { author: "Jane", count: 10, answer: "42", valid: true }, path }] } }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test("handles leading slash when converting", () => { const path = "/foo/bar/?count=42"; expect(getStateFromPath(path)).toEqual({ routes: [{ name: "foo", key: "foo-0", state: { routes: [{ name: "bar", key: "bar-1", params: { count: "42" }, path }] } }] }); }); test("handles ending slash when converting", () => { const path = "foo/bar/?count=42"; expect(getStateFromPath(path)).toEqual({ routes: [{ name: "foo", key: "foo-0", state: { routes: [{ name: "bar", key: "bar-1", params: { count: "42" }, path }] } }] }); }); test("handles route without param", () => { const path = "foo/bar"; const state = { routes: [{ name: "foo", key: "foo-0", state: { routes: [{ name: "bar", key: "bar-1", path }] } }] }; expect(getStateFromPath(path)).toEqual(state); expect(getStateFromPath(getPathFromState(state))).toEqual(changePath(state, "/foo/bar")); }); test.skip("converts path string to initial state with config with nested screens", () => { const path = "/foe/bar/sweet/apple/baz/jane?count=10&answer=42&valid=true"; const config = { screens: { Foo: { path: "foo", screens: { Foe: { path: "foe", exact: true, screens: { Bar: { path: "bar/:type/:fruit", screens: { Baz: { path: "baz/:author", parse: { author: author => author.replace(/^\w/, c => c.toUpperCase()), count: Number, valid: Boolean }, stringify: { author: author => author.toLowerCase() } } } } } } } } } }; const state = { routes: [{ name: "Foo", state: { routes: [{ name: "Foe", state: { routes: [{ name: "Bar", params: { fruit: "apple", type: "sweet" }, state: { routes: [{ name: "Baz", params: { author: "Jane", count: 10, answer: "42", valid: true }, path }] } }] } }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test.skip("converts path string to initial state with config with nested screens and unused parse functions", () => { const path = "/foe/baz/jane?count=10&answer=42&valid=true"; const config = { screens: { Foo: { path: "foo", screens: { Foe: { path: "foe", exact: true, screens: { Baz: { path: "baz/:author", parse: { author: author => author.replace(/^\w/, c => c.toUpperCase()), count: Number, valid: Boolean, id: Boolean } } } } } } } }; const state = { routes: [{ name: "Foo", state: { routes: [{ name: "Foe", state: { routes: [{ name: "Baz", params: { author: "Jane", count: 10, answer: "42", valid: true }, path }] } }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(changePath(state, "/foe/baz/Jane?count=10&answer=42&valid=true")); }); test.skip("handles nested object with unused configs and with parse in it", () => { const path = "/bar/sweet/apple/foe/bis/jane?count=10&answer=42&valid=true"; const config = { screens: { Bar: { path: "bar/:type/:fruit", screens: { Foo: { screens: { Foe: { path: "foe", screens: { Baz: { screens: { Bos: { path: "bos", exact: true }, Bis: { path: "bis/:author", stringify: { author: author => author.replace(/^\w/, c => c.toLowerCase()) }, parse: { author: author => author.replace(/^\w/, c => c.toUpperCase()), count: Number, valid: Boolean } } } } } } } } } } } }; const state = { routes: [{ name: "Bar", params: { fruit: "apple", type: "sweet" }, state: { routes: [{ name: "Foo", state: { routes: [{ name: "Foe", state: { routes: [{ name: "Baz", state: { routes: [{ name: "Bis", params: { author: "Jane", count: 10, answer: "42", valid: true }, path }] } }] } }] } }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test("handles parse in nested object for second route depth", () => { const path = "/baz"; const config = { screens: { Foo: { path: "foo", screens: { Foe: { path: "foe", exact: true }, Bar: { path: "bar", exact: true, screens: { Baz: { path: "baz", exact: true } } } } } } }; const state = { routes: [{ name: "Foo", key: "Foo-0", state: { routes: [{ name: "Bar", key: "Bar-1", state: { routes: [{ name: "Baz", key: "Baz-2", path }] } }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test("handles parse in nested object for second route depth and and path and parse in roots", () => { const path = "/baz"; const config = { screens: { Foo: { path: "foo/:id", parse: { id: Number }, stringify: { id: id => `id=${id}` }, screens: { Foe: "foe", Bar: { screens: { Baz: { path: "baz", exact: true } } } } } } }; const state = { routes: [{ name: "Foo", key: "Foo-0", state: { routes: [{ name: "Bar", key: "Bar-1", state: { routes: [{ name: "Baz", key: "Baz-2", path }] } }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test.skip("handles path at top level", () => { const path = "/foo/fruits/apple"; const config = { path: "foo", screens: { Foo: { screens: { Fruits: "fruits/:fruit" } } } }; const state = { routes: [{ name: "Foo", state: { routes: [{ name: "Fruits", params: { fruit: "apple" }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test("handles initialRouteName at top level", () => { const path = "/baz"; const config = { initialRouteName: "Boo", screens: { Foo: { screens: { Foe: "foe", Bar: { screens: { Baz: "baz" } } } } } }; const state = { index: 1, routes: [{ name: "Boo", key: "Boo-0" }, { name: "Foo", key: "Foo-1", state: { routes: [{ name: "Bar", key: "Bar-2", state: { routes: [{ name: "Baz", key: "Baz-3", path }] } }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test("handles initialRouteName inside a screen", () => { const path = "/baz"; const config = { screens: { Foo: { initialRouteName: "Foe", screens: { Foe: "foe", Bar: { screens: { Baz: "baz" } } } } } }; const state = { routes: [{ name: "Foo", key: "Foo-0", state: { index: 1, routes: [{ name: "Foe", key: "Foe-1" }, { name: "Bar", key: "Bar-2", state: { routes: [{ name: "Baz", key: "Baz-3", path }] } }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test("handles initialRouteName included in path", () => { const path = "/baz"; const config = { screens: { Foo: { initialRouteName: "Foe", screens: { Foe: { screens: { Baz: "baz" } }, Bar: "bar" } } } }; const state = { routes: [{ name: "Foo", key: "Foo-0", state: { routes: [{ name: "Foe", key: "Foe-1", state: { routes: [{ name: "Baz", key: "Baz-2", path }] } }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test.skip("handles two initialRouteNames", () => { const path = "/bar/sweet/apple/foe/bis/jane?answer=42&count=10&valid=true"; const config = { screens: { Bar: { path: "bar/:type/:fruit", screens: { Foo: { screens: { Foe: { path: "foe", screens: { Baz: { initialRouteName: "Bos", screens: { Bos: { path: "bos", exact: true }, Bis: { path: "bis/:author", stringify: { author: author => author.replace(/^\w/, c => c.toLowerCase()) }, parse: { author: author => author.replace(/^\w/, c => c.toUpperCase()), count: Number, valid: Boolean } } } } } } } } } } } }; const state = { routes: [{ name: "Bar", params: { fruit: "apple", type: "sweet" }, state: { routes: [{ name: "Foo", state: { routes: [{ name: "Foe", state: { routes: [{ name: "Baz", state: { index: 1, routes: [{ name: "Bos" }, { name: "Bis", params: { answer: "42", author: "Jane", count: 10, valid: true }, path }] } }] } }] } }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test.skip("accepts initialRouteName without config for it", () => { const path = "/bar/sweet/apple/foe/bis/jane?answer=42&count=10&valid=true"; const config = { screens: { Bar: { path: "bar/:type/:fruit", screens: { Foo: { screens: { Foe: { path: "foe", screens: { Baz: { initialRouteName: "Bas", screens: { Bos: { path: "bos", exact: true }, Bis: { path: "bis/:author", stringify: { author: author => author.replace(/^\w/, c => c.toLowerCase()) }, parse: { author: author => author.replace(/^\w/, c => c.toUpperCase()), count: Number, valid: Boolean } } } } } } } } } } } }; const state = { routes: [{ name: "Bar", params: { fruit: "apple", type: "sweet" }, state: { routes: [{ name: "Foo", state: { routes: [{ name: "Foe", state: { routes: [{ name: "Baz", state: { index: 1, routes: [{ name: "Bas" }, { name: "Bis", params: { answer: "42", author: "Jane", count: 10, valid: true }, path }] } }] } }] } }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test("returns undefined if no matching screen is present (top level path)", () => { const path = "/foo/bar"; const config = { path: "qux", screens: { Foo: { screens: { Foe: "foo", Bar: { screens: { Baz: "bar" } } } } } }; expect(getStateFromPath(path, config)).toBeUndefined(); }); test("returns undefined if no matching screen is present", () => { const path = "/baz"; const config = { screens: { Foo: { path: "foo", screens: { Foe: "foe", Bar: { screens: { Baz: "baz" } } } } } }; expect(getStateFromPath(path, config)).toBeUndefined(); }); test("returns undefined if path is empty and no matching screen is present", () => { const path = ""; const config = { screens: { Foo: { screens: { Foe: "foe", Bar: { screens: { Baz: "baz" } } } } } }; expect(getStateFromPath(path, config)).toBeUndefined(); }); test.skip("returns matching screen if path is empty", () => { const path = ""; const config = { screens: { Foo: { screens: { Foe: "foe", Bar: { screens: { Qux: "", Baz: "baz" } } } } } }; const state = { routes: [{ name: "Foo", state: { routes: [{ name: "Bar", state: { routes: [{ name: "Qux", path }] } }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(changePath(state, "")); }); test.skip("returns matching screen if path is only slash", () => { const path = "/"; const config = { screens: { Foo: { screens: { Foe: "foe", Bar: { screens: { Qux: "", Baz: "baz" } } } } } }; const state = { routes: [{ name: "Foo", state: { routes: [{ name: "Bar", state: { routes: [{ name: "Qux", path: "" }] } }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(changePath(state, "")); }); test("returns matching screen with params if path is empty", () => { const path = "?foo=42"; const config = { screens: { Foo: { screens: { Foe: "foe", Bar: { screens: { Qux: { path: "", parse: { foo: Number } }, Baz: "baz" } } } } } }; const state = { routes: [{ name: "Foo", key: "Foo-0", state: { routes: [{ name: "Bar", key: "Bar-1", state: { routes: [{ name: "Qux", key: "Qux-2", params: { foo: 42 }, path }] } }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(changePath(state, "/?foo=42")); }); test("doesn't match nested screen if path is empty", () => { const config = { screens: { Foo: { screens: { Foe: "foe", Bar: { path: "bar", screens: { Qux: { path: "", parse: { foo: Number } } } } } } } }; const path = ""; expect(getStateFromPath(path, config)).toBeUndefined(); }); test.skip("chooses more exhaustive pattern", () => { const path = "/foo/5"; const config = { screens: { Foe: { path: "/", initialRouteName: "Foo", screens: { Foo: "foo", Bis: { path: "foo/:id", parse: { id: Number } } } } } }; const state = { routes: [{ name: "Foe", state: { index: 1, routes: [{ name: "Foo" }, { name: "Bis", params: { id: 5 }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test("handles same paths beginnings", () => { const path = "/foos"; const config = { screens: { Foe: { path: "/", initialRouteName: "Foo", screens: { Foo: "foo", Bis: { path: "foos" } } } } }; const state = { routes: [{ name: "Foe", key: "Foe-0", state: { index: 1, routes: [{ name: "Foo", key: "Foo-1" }, { name: "Bis", key: "Bis-2", path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test.skip("handles same paths beginnings with params", () => { const path = "/foos/5"; const config = { screens: { Foe: { path: "/", initialRouteName: "Foo", screens: { Foo: "foo", Bis: { path: "foos/:id", parse: { id: Number } } } } } }; const state = { routes: [{ name: "Foe", state: { index: 1, routes: [{ name: "Foo" }, { name: "Bis", params: { id: 5 }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test.skip("handles not taking path with too many segments", () => { const path = "/foos/5"; const config = { screens: { Foe: { path: "/", initialRouteName: "Foo", screens: { Foo: "foo", Bis: { path: "foos/:id", parse: { id: Number } }, Bas: { path: "foos/:id/:nip", parse: { id: Number, pwd: Number } } } } } }; const state = { routes: [{ name: "Foe", state: { index: 1, routes: [{ name: "Foo" }, { name: "Bis", params: { id: 5 }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test.skip("handles differently ordered params v1", () => { const path = "/foos/5/res/20"; const config = { screens: { Foe: { path: "/", initialRouteName: "Foo", screens: { Foo: "foo", Bis: { path: "foos/:id", parse: { id: Number } }, Bas: { path: "foos/:id/res/:pwd", parse: { id: Number, pwd: Number } } } } } }; const state = { routes: [{ name: "Foe", state: { index: 1, routes: [{ name: "Foo" }, { name: "Bas", params: { id: 5, pwd: 20 }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test.skip("handles differently ordered params v2", () => { const path = "/5/20/foos/res"; const config = { screens: { Foe: { path: "/", initialRouteName: "Foo", screens: { Foo: "foo", Bis: { path: "foos/:id", parse: { id: Number } }, Bas: { path: ":id/:pwd/foos/res", parse: { id: Number, pwd: Number } } } } } }; const state = { routes: [{ name: "Foe", state: { index: 1, routes: [{ name: "Foo" }, { name: "Bas", params: { id: 5, pwd: 20 }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test.skip("handles differently ordered params v3", () => { const path = "/foos/5/20/res"; const config = { screens: { Foe: { path: "/", initialRouteName: "Foo", screens: { Foo: "foo", Bis: { path: "foos/:id", parse: { id: Number } }, Bas: { path: "foos/:id/:pwd/res", parse: { id: Number, pwd: Number } } } } } }; const state = { routes: [{ name: "Foe", state: { index: 1, routes: [{ name: "Foo" }, { name: "Bas", params: { id: 5, pwd: 20 }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test.skip("handles differently ordered params v4", () => { const path = "5/foos/res/20"; const config = { screens: { Foe: { path: "/", initialRouteName: "Foo", screens: { Foo: "foo", Bis: { path: "foos/:id", parse: { id: Number } }, Bas: { path: ":id/foos/res/:pwd", parse: { id: Number, pwd: Number } } } } } }; const state = { routes: [{ name: "Foe", state: { index: 1, routes: [{ name: "Foo" }, { name: "Bas", params: { id: 5, pwd: 20 }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(changePath(state, "/5/foos/res/20")); }); test.skip("handles simple optional params", () => { const path = "/foos/5"; const config = { screens: { Foe: { path: "/", initialRouteName: "Foo", screens: { Foo: "foo", Bis: { path: "foo/:id", parse: { id: Number } }, Bas: { path: "foos/:id/:nip?", parse: { id: Number, nip: Number } } } } } }; const state = { routes: [{ name: "Foe", state: { index: 1, routes: [{ name: "Foo" }, { name: "Bas", params: { id: 5 }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test.skip("handle 2 optional params at the end v1", () => { const path = "/foos/5"; const config = { screens: { Foe: { path: "/", initialRouteName: "Foo", screens: { Foo: "foo", Bis: { path: "foo/:id", parse: { id: Number } }, Bas: { path: "foos/:id/:nip?/:pwd?", parse: { id: Number, nip: Number } } } } } }; const state = { routes: [{ name: "Foe", state: { index: 1, routes: [{ name: "Foo" }, { name: "Bas", params: { id: 5 }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test.skip("handle 2 optional params at the end v2", () => { const path = "/foos/5/10"; const config = { screens: { Foe: { path: "/", initialRouteName: "Foo", screens: { Foo: "foo", Bis: { path: "foo/:id", parse: { id: Number } }, Bas: { path: "foos/:id/:nip?/:pwd?", parse: { id: Number, nip: Number } } } } } }; const state = { routes: [{ name: "Foe", state: { index: 1, routes: [{ name: "Foo" }, { name: "Bas", params: { id: 5, nip: 10 }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test.skip("handle 2 optional params at the end v3", () => { const path = "/foos/5/10/15"; const config = { screens: { Foe: { path: "/", initialRouteName: "Foo", screens: { Foo: "foo", Bis: { path: "foo/:id", parse: { id: Number } }, Bas: { path: "foos/:id/:nip?/:pwd?", parse: { id: Number, nip: Number, pwd: Number } } } } } }; const state = { routes: [{ name: "Foe", state: { index: 1, routes: [{ name: "Foo" }, { name: "Bas", params: { id: 5, nip: 10, pwd: 15 }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test.skip("handle optional params in the middle v1", () => { const path = "/foos/5/10"; const config = { screens: { Foe: { path: "/", initialRouteName: "Foo", screens: { Foo: "foo", Bis: { path: "foo/:id", parse: { id: Number } }, Bas: { path: "foos/:id/:nip?/:pwd", parse: { id: Number, nip: Number, pwd: Number } } } } } }; const state = { routes: [{ name: "Foe", state: { index: 1, routes: [{ name: "Foo" }, { name: "Bas", params: { id: 5, pwd: 10 }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test.skip("handle optional params in the middle v2", () => { const path = "/foos/5/10/15"; const config = { screens: { Foe: { path: "/", initialRouteName: "Foo", screens: { Foo: "foo", Bis: { path: "foo/:id", parse: { id: Number } }, Bas: { path: "foos/:id/:nip?/:pwd", parse: { id: Number, nip: Number, pwd: Number } } } } } }; const state = { routes: [{ name: "Foe", state: { index: 1, routes: [{ name: "Foo" }, { name: "Bas", params: { id: 5, nip: 10, pwd: 15 }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test.skip("handle optional params in the middle v3", () => { const path = "/foos/5/10/15"; const config = { screens: { Foe: { path: "/", initialRouteName: "Foo", screens: { Foo: "foo", Bis: { path: "foo/:id", parse: { id: Number } }, Bas: { path: "foos/:id/:nip?/:pwd/:smh", parse: { id: Number, nip: Number, pwd: Number, smh: Number } } } } } }; const state = { routes: [{ name: "Foe", state: { index: 1, routes: [{ name: "Foo" }, { name: "Bas", params: { id: 5, pwd: 10, smh: 15 }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test.skip("handle optional params in the middle v4", () => { const path = "/foos/5/10"; const config = { screens: { Foe: { path: "/", initialRouteName: "Foo", screens: { Foo: "foo", Bis: { path: "foo/:id", parse: { id: Number } }, Bas: { path: "foos/:nip?/:pwd/:smh?/:id", parse: { id: Number, nip: Number, pwd: Number, smh: Number } } } } } }; const state = { routes: [{ name: "Foe", state: { index: 1, routes: [{ name: "Foo" }, { name: "Bas", params: { pwd: 5, id: 10 }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test.skip("handle optional params in the middle v5", () => { const path = "/foos/5/10/15"; const config = { screens: { Foe: { path: "/", initialRouteName: "Foo", screens: { Foo: "foo", Bis: { path: "foo/:id", parse: { id: Number } }, Bas: { path: "foos/:nip?/:pwd/:smh?/:id", parse: { id: Number, nip: Number, pwd: Number, smh: Number } } } } } }; const state = { routes: [{ name: "Foe", state: { index: 1, routes: [{ name: "Foo" }, { name: "Bas", params: { nip: 5, pwd: 10, id: 15 }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test.skip("handle optional params in the beginning v1", () => { const path = "5/10/foos/15"; const config = { screens: { Foe: { path: "/", initialRouteName: "Foo", screens: { Foo: "foo", Bis: { path: "foo/:id", parse: { id: Number } }, Bas: { path: ":nip?/:pwd/foos/:smh?/:id", parse: { id: Number, nip: Number, pwd: Number, smh: Number } } } } } }; const state = { routes: [{ name: "Foe", state: { index: 1, routes: [{ name: "Foo" }, { name: "Bas", params: { nip: 5, pwd: 10, id: 15 }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(changePath(state, "/5/10/foos/15")); }); test.skip("handle optional params in the beginning v2", () => { const path = "5/10/foos/15"; const config = { screens: { Foe: { path: "/", initialRouteName: "Foo", screens: { Foo: "foo", Bis: { path: "foo/:id", parse: { id: Number } }, Bas: { path: ":nip?/:smh?/:pwd/foos/:id", parse: { id: Number, nip: Number, pwd: Number, smh: Number } } } } } }; const state = { routes: [{ name: "Foe", state: { index: 1, routes: [{ name: "Foo" }, { name: "Bas", params: { nip: 5, pwd: 10, id: 15 }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(changePath(state, "/5/10/foos/15")); }); test.skip("merges parent patterns if needed", () => { const path = "foo/42/baz/babel"; const config = { screens: { Foo: { path: "foo/:bar", parse: { bar: Number }, screens: { Baz: "baz/:qux" } } } }; const state = { routes: [{ name: "Foo", params: { bar: 42 }, state: { routes: [{ name: "Baz", params: { qux: "babel" }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(changePath(state, "/foo/42/baz/babel")); }); test.skip("ignores extra slashes in the pattern", () => { const path = "/bar/42"; const config = { screens: { Foo: { screens: { Bar: { path: "/bar//:id/" } } } } }; const state = { routes: [{ name: "Foo", state: { routes: [{ name: "Bar", params: { id: "42" }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test.skip("matches wildcard patterns at root", () => { const path = "/test/bar/42/whatever"; const config = { screens: { 404: "*", Foo: { screens: { Bar: { path: "/bar/:id/" } } } } }; const state = { routes: [{ name: "404", path }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(changePath(state, "/404")); }); test.skip("matches wildcard patterns at nested level", () => { const path = "/bar/42/whatever/baz/initt"; const config = { screens: { Foo: { screens: { Bar: { path: "/bar/:id/", screens: { 404: "*" } } } } } }; const state = { routes: [{ name: "Foo", state: { routes: [{ name: "Bar", params: { id: "42" }, state: { routes: [{ name: "404", path }] } }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(changePath(state, "/bar/42/404")); }); test.skip("matches wildcard patterns at nested level with exact", () => { const path = "/whatever"; const config = { screens: { Foo: { screens: { Bar: { path: "/bar/:id/", screens: { 404: { path: "*", exact: true } } }, Baz: {} } } } }; const state = { routes: [{ name: "Foo", state: { routes: [{ name: "Bar", state: { routes: [{ name: "404", path }] } }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(changePath(state, "/404")); }); test.skip("tries to match wildcard patterns at the end", () => { const path = "/bar/42/test"; const config = { screens: { Foo: { screens: { Bar: { path: "/bar/:id/", screens: { 404: "*", UserProfile: ":userSlug", Test: "test" } } } } } }; const state = { routes: [{ name: "Foo", state: { routes: [{ name: "Bar", params: { id: "42" }, state: { routes: [{ name: "Test", path }] } }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test.skip("uses nearest parent wildcard match for unmatched paths", () => { const path = "/bar/42/baz/test"; const config = { screens: { Foo: { screens: { Bar: { path: "/bar/:id/", screens: { Baz: "baz" } }, 404: "*" } } } }; const state = { routes: [{ name: "Foo", state: { routes: [{ name: "404", path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(changePath(state, "/404")); }); test.skip("matches screen with overlapping initial path and wildcard", () => { const path = "/bar/42/baz/test/whatever"; const config = { screens: { Foo: { screens: { Bar: { path: "/bar/:id/", screens: { Baz: "baz" } }, Baz: "/bar/:id/*" } } } }; const state = { routes: [{ name: "Foo", state: { routes: [{ name: "Baz", params: { id: "42" }, path }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(changePath(state, "/bar/42/Baz")); }); test("throws if two screens map to the same pattern", () => { const path = "/bar/42/baz/test"; expect(() => getStateFromPath(path, { screens: { Foo: { screens: { Bar: { path: "/bar/:id/", screens: { Baz: "baz" } }, Bax: "/bar/:id/baz" } } } })).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, { screens: { Foo: { screens: { Bar: { path: "/bar/:id/", screens: { Baz: "" } } } } } })).not.toThrow(); }); test("correctly applies initialRouteName for config with similar route names", () => { const path = "/weekly-earnings"; const config = { screens: { RootTabs: { screens: { HomeTab: { screens: { Home: "", WeeklyEarnings: "weekly-earnings", EventDetails: "event-details/:eventId" } }, EarningsTab: { initialRouteName: "Earnings", path: "earnings", screens: { Earnings: "", WeeklyEarnings: "weekly-earnings" } } } } } }; const state = { routes: [{ name: "RootTabs", key: "RootTabs-0", state: { routes: [{ name: "HomeTab", key: "HomeTab-1", state: { routes: [{ name: "WeeklyEarnings", key: "WeeklyEarnings-2", path }] } }] } }] }; expect(getStateFromPath(path, config)).toEqual(state); expect(getStateFromPath(getPathFromState(state, config), config)).toEqual(state); }); test("correctly applies initialRouteName for config with similar route names v2", () => { const path = "/earnings/weekly-earnings"; const config = { screens: { RootTabs: { screens: { HomeTab: { initialRouteName: "Home", screens: { Home: "", WeeklyEarnings: "weekly-earnings"