Skip to content

Commit

Permalink
fix route testing with possible conflicting dynmic params
Browse files Browse the repository at this point in the history
  • Loading branch information
mattiaz9 committed Jun 13, 2024
1 parent 3287055 commit f1cc007
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 47 deletions.
5 changes: 3 additions & 2 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"semi": false
}
"semi": false,
"printWidth": 100
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "route-fn",
"version": "1.3.0",
"version": "1.3.1",
"description": "A simple utility function for typesafe urls.",
"license": "MIT",
"type": "module",
Expand Down
37 changes: 18 additions & 19 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,8 @@ export function createRouteFn<const Routes extends string[]>(routes: Routes) {
type DynamicRouteId = ExtractDynamicRouteIds<Routes>[number]
type StaticRouteId = ExtractStaticRouteIds<Routes>[number]

function fn<Id extends DynamicRouteId>(
id: Id,
params: RouteParams<Id>
): string
function fn<Id extends StaticRouteId>(
id: Id,
params?: RouteParams<Id>
): string
function fn<Id extends DynamicRouteId>(id: Id, params: RouteParams<Id>): string
function fn<Id extends StaticRouteId>(id: Id, params?: RouteParams<Id>): string
function fn<Id extends DynamicRouteId | StaticRouteId>(
id: Id,
params?: RouteParams<Id> | SearchParams
Expand Down Expand Up @@ -70,9 +64,7 @@ export function createRouteFn<const Routes extends string[]>(routes: Routes) {
return 0
})

const patterns = sortedRoutes.map(
(route) => new URLPattern({ pathname: route })
)
const patterns = sortedRoutes.map((route) => new URLPattern({ pathname: route }))

for (const pattern of patterns) {
const patternResult = pattern.exec(input)
Expand All @@ -86,13 +78,11 @@ export function createRouteFn<const Routes extends string[]>(routes: Routes) {

fn.test = function (
url: string,
routeIds:
| StaticRouteId
| DynamicRouteId
| (StaticRouteId | DynamicRouteId)[]
routeIds: StaticRouteId | DynamicRouteId | (StaticRouteId | DynamicRouteId)[]
): boolean {
const routes = typeof routeIds === "string" ? [routeIds] : routeIds
for (const route of routes) {
const matchingRoutes = typeof routeIds === "string" ? [routeIds] : routeIds

const matchedRoutes = routes.filter((route) => {
const urlWithOrigin = new URL(url, fakeOrigin).href
const input = urlWithOrigin.split("?")[0]

Expand All @@ -101,8 +91,17 @@ export function createRouteFn<const Routes extends string[]>(routes: Routes) {
if (pattern.test(input)) {
return true
}
}
return false

return false
})

// make sure some dynamic params are not conflicting
return (
matchedRoutes.length > 0 &&
matchedRoutes.every((route) =>
matchingRoutes.includes(route as StaticRouteId | DynamicRouteId)
)
)
}

fn.list = function (): Routes {
Expand Down
43 changes: 18 additions & 25 deletions tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,23 +24,15 @@ describe("route-fn", () => {
it("should return the correct route with search params", () => {
const route = createRouteFn(["/user/:id"])

expect(route("/user/:id", { id: 1, searchParams: { page: 0 } })).toBe(
"/user/1?page=0"
)
expect(route("/user/:id", { id: 1, searchParams: { page: 2 } })).toBe(
"/user/1?page=2"
)
expect(route("/user/:id", { id: 1, searchParams: { page: 0 } })).toBe("/user/1?page=0")
expect(route("/user/:id", { id: 1, searchParams: { page: 2 } })).toBe("/user/1?page=2")
})

it("should strip null or undefined search params", () => {
const route = createRouteFn(["/user/:id"])

expect(route("/user/:id", { id: 1, searchParams: { page: null } })).toBe(
"/user/1"
)
expect(
route("/user/:id", { id: 1, searchParams: { page: undefined } })
).toBe("/user/1")
expect(route("/user/:id", { id: 1, searchParams: { page: null } })).toBe("/user/1")
expect(route("/user/:id", { id: 1, searchParams: { page: undefined } })).toBe("/user/1")
})

it("should show type error when a param is missing", () => {
Expand Down Expand Up @@ -74,13 +66,11 @@ describe("route-fn.params", () => {
})
})

describe("route-fn.match", () => {
describe("route-fn.test", () => {
it("should match the same url", () => {
const route = createRouteFn(["/user/:id/settings/:page"])

expect(
route.test("/user/1/settings/2", "/user/:id/settings/:page")
).toEqual(true)
expect(route.test("/user/1/settings/2", "/user/:id/settings/:page")).toEqual(true)
})

it("should match one of multiple test routes", () => {
Expand All @@ -96,15 +86,18 @@ describe("route-fn.match", () => {
})

it("should not match different route", () => {
const route = createRouteFn(["/user/:id/settings/:page"])
const route = createRouteFn([
"/:org",
"/:org/settings",
"/:org/settings/billing",
"/:org/:project",
"/:org/:project/posts",
"/:org/:project/settings",
])

expect(route.test("/user", "/user/:id/settings/:page")).toEqual(false)
expect(route.test("/user/1", "/user/:id/settings/:page")).toEqual(false)
expect(route.test("/user/1/settings", "/user/:id/settings/:page")).toEqual(
false
)
expect(
route.test("/user/1/settings/2/posts", "/user/:id/settings/:page")
).toEqual(false)
expect(route.test("/apple", "/:org/:project")).toEqual(false)
expect(route.test("/apple/settings", "/:org/:project")).toEqual(false)
expect(route.test("/apple/settings/billing", "/:org/:project/posts")).toEqual(false)
expect(route.test("/apple/settings/billing", "/:org/:project/settings")).toEqual(false)
})
})

0 comments on commit f1cc007

Please sign in to comment.