Folo/packages/internal/utils/src/path-parser.test.ts

304 lines
7.8 KiB
TypeScript

import { compile, pathToRegexp } from "path-to-regexp"
import { describe, expect, test } from "vitest"
import {
MissingOptionalParamError,
MissingRequiredParamError,
parseFullPathParams,
parseRegexpPathParams,
regexpPathToPath,
transformUriPath,
} from "./path-parser"
describe("test `transformUriPath()`", () => {
test("normal path", () => {
expect(transformUriPath("/issues/all")).toMatchInlineSnapshot(`"/issues/all"`)
})
test("has tailing optional params", () => {
const path = transformUriPath("/issues/:id?")
expect(path).toMatchInlineSnapshot(`"/issues{/:id}"`)
expect(compile(path)({})).toMatchInlineSnapshot(`"/issues"`)
const regexp = pathToRegexp(path)
expect(regexp.keys).toMatchInlineSnapshot(`
[
{
"name": "id",
"type": "param",
},
]
`)
})
test("has tailing optional params and with value", () => {
const path = transformUriPath("/issues/:id?")
expect(
compile(path)({
id: "1111111",
}),
).toMatchInlineSnapshot(`"/issues/1111111"`)
const regexp = pathToRegexp(path)
expect(regexp.keys).toMatchInlineSnapshot(`
[
{
"name": "id",
"type": "param",
},
]
`)
})
test("catch all path", () => {
const path = transformUriPath("/:path{.+}?")
expect(path).toMatchInlineSnapshot(`"{/*path}"`)
expect(
compile(path)({
path: ["a", "b", "c"],
}),
).toMatchInlineSnapshot(`"/a/b/c"`)
})
test("catch all path with leading route", () => {
const path = transformUriPath("/issues/:path{.+}?")
expect(path).toMatchInlineSnapshot(`"/issues{/*path}"`)
expect(
compile(path)({
path: ["a", "b", "c"],
}),
).toMatchInlineSnapshot(`"/issues/a/b/c"`)
})
test("catch all path but value is query search string", () => {
const path = transformUriPath("/issues/:path{.+}?")
expect(path).toMatchInlineSnapshot(`"/issues{/*path}"`)
expect(
compile(path)({
path: ["a=1&b=2"],
}),
).toMatchInlineSnapshot(`"/issues/a%3D1%26b%3D2"`)
})
test("catch all route via `*`", () => {
expect(transformUriPath("/issues/*")).toMatchInlineSnapshot(`"/issues{/:__catchAll__}"`)
expect(transformUriPath("*")).toMatchInlineSnapshot(`"{/:__catchAll__}"`)
})
})
describe("test `regexpPathToPath()`", () => {
test("normal path", () => {
expect(regexpPathToPath("/issues/all", {})).toMatchInlineSnapshot(`"/issues/all"`)
})
test("path with optional params", () => {
expect(regexpPathToPath("/issues/:id?", {})).toMatchInlineSnapshot(`"/issues"`)
expect(regexpPathToPath("/issues/:id?", { id: "1" })).toMatchInlineSnapshot(`"/issues/1"`)
})
test("path with many optional params", () => {
expect(
regexpPathToPath("/issue/:user/:repo/:state?/:labels?", {
user: "rssnext",
repo: "follow",
}),
).toMatchInlineSnapshot(`"/issue/rssnext/follow"`)
})
test("path with many optional params, but when using the optional parameter(s) after the optional parameter(s), the previous optional parameter(s) is/are not filled in.", () => {
expect(() =>
regexpPathToPath("/issue/:user/:repo/:state?/:labels?", {
user: "rssnext",
repo: "follow",
labels: "rss",
}),
).toThrowError(MissingOptionalParamError)
})
test("path with many optional params, but when using the optional parameter(s) after the optional parameter(s), the previous optional parameter(s) is/are not filled in.", () => {
expect(() =>
regexpPathToPath("/ranking/:rid?/:day?/:arc_type?/:disableEmbed?", {
day: "1",
}),
).toThrowError(MissingOptionalParamError)
})
test("missing required param", () => {
expect(() => regexpPathToPath("/issue/:user/:repo/:state?/:labels?", {})).toThrow(
MissingRequiredParamError,
)
})
test("path with many optional params and all inputted", () => {
expect(
regexpPathToPath("/issue/:user/:repo/:state?/:labels?", {
user: "rssnext",
repo: "follow",
state: "open",
labels: "rss",
}),
).toMatchInlineSnapshot(`"/issue/rssnext/follow/open/rss"`)
})
test("omit empty string and nil value", () => {
expect(
regexpPathToPath(
"/issue/:user/:repo/:state?/:labels?",
{
user: "rssnext",
repo: "follow",
state: "open",
labels: "",
},
{
omitNilAndEmptyString: true,
},
),
).toMatchInlineSnapshot(`"/issue/rssnext/follow/open"`)
})
test("omit empty string and nil value will throw", () => {
expect(() =>
regexpPathToPath(
"/issue/:user/:repo/:state?/:labels?",
{
user: "rssnext",
repo: "follow",
state: "",
labels: "l",
},
{
omitNilAndEmptyString: true,
},
),
).toThrow(MissingOptionalParamError)
})
test("omit empty string and nil value will throw (default behavior)", () => {
expect(() =>
regexpPathToPath("/issue/:user/:repo/:state?/:labels?", {
user: "rssnext",
repo: "follow",
state: "",
labels: "l",
}),
).toThrow(MissingOptionalParamError)
})
test("empty string will pass", () => {
expect(
regexpPathToPath(
"/issue/:user/:repo/:state?/:labels?",
{
user: "rssnext",
repo: "follow",
state: "",
labels: "l",
},
{ omitNilAndEmptyString: false },
),
).toMatchInlineSnapshot(`"/issue/rssnext/follow//l"`)
})
})
describe("test `parseRegexpPathParams()`", () => {
test("normal path", () => {
expect(parseRegexpPathParams("/issues/all")).toMatchInlineSnapshot(`
[]
`)
})
test("path with optional params", () => {
expect(parseRegexpPathParams("/issues/:id?")).toMatchInlineSnapshot(`
[
{
"isCatchAll": false,
"name": "id",
"optional": true,
},
]
`)
})
test("path with many optional params", () => {
expect(parseRegexpPathParams("/issue/:user/:repo/:state?/:labels?")).toMatchInlineSnapshot(`
[
{
"isCatchAll": false,
"name": "user",
"optional": false,
},
{
"isCatchAll": false,
"name": "repo",
"optional": false,
},
{
"isCatchAll": false,
"name": "state",
"optional": true,
},
{
"isCatchAll": false,
"name": "labels",
"optional": true,
},
]
`)
})
test("catch all path", () => {
expect(parseRegexpPathParams("/:path{.+}?")).toMatchInlineSnapshot(`
[
{
"isCatchAll": true,
"name": "path",
"optional": true,
},
]
`)
})
test("with excludeNames", () => {
expect(
parseRegexpPathParams("/issue/:user/:repo/:state?/:labels?/:routeParams?", {
excludeNames: ["state", "routeParams"],
}),
).toMatchInlineSnapshot(`
[
{
"isCatchAll": false,
"name": "user",
"optional": false,
},
{
"isCatchAll": false,
"name": "repo",
"optional": false,
},
{
"isCatchAll": false,
"name": "labels",
"optional": true,
},
]
`)
})
})
describe("test `parseFullPathParams()`", () => {
test("case 1", () => {
expect(parseFullPathParams("/user/123344", "/user/:id")).toMatchInlineSnapshot(`
{
"id": "123344",
}
`)
})
test("case 2", () => {
expect(parseFullPathParams("/build/wangqiru/ttrss", "/build/:user/:name"))
.toMatchInlineSnapshot(`
{
"name": "ttrss",
"user": "wangqiru",
}
`)
})
})