chore: init
This commit is contained in:
commit
acbf714fc4
15 changed files with 8734 additions and 0 deletions
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# Dependencies
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# ESLint cache
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Build directories
|
||||||
|
/dist/
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
*.swa-p
|
2
.husky/commit-msg
Executable file
2
.husky/commit-msg
Executable file
|
@ -0,0 +1,2 @@
|
||||||
|
#!/bin/sh
|
||||||
|
npx --no -- commitlint --edit "$1"
|
2
.husky/pre-commit
Executable file
2
.husky/pre-commit
Executable file
|
@ -0,0 +1,2 @@
|
||||||
|
#!/bin/sh
|
||||||
|
npx lint-staged
|
14
.swcrc
Normal file
14
.swcrc
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"jsc": {
|
||||||
|
"parser": {
|
||||||
|
"syntax": "ecmascript",
|
||||||
|
"dynamicImport": true
|
||||||
|
},
|
||||||
|
"loose": true,
|
||||||
|
"target": "es2017"
|
||||||
|
},
|
||||||
|
"minify": false,
|
||||||
|
"module": {
|
||||||
|
"type": "commonjs"
|
||||||
|
}
|
||||||
|
}
|
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2025 SVR.JS
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
100
README.md
Normal file
100
README.md
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
# SVRouter
|
||||||
|
|
||||||
|
SVRouter is a router library built for use in building web applications as SVR.JS 4.x mods.
|
||||||
|
|
||||||
|
Example SVR.JS mod that uses SVRouter (you will need to install the `svrouter` npm package either in the SVR.JS installation root or globally):
|
||||||
|
|
||||||
|
```js
|
||||||
|
const svrouter = require("svrouter");
|
||||||
|
const router = svrouter();
|
||||||
|
|
||||||
|
// eslint-disable-next-line no-unused-vars
|
||||||
|
router.get("/hello", (req, res, logFacilities, config, next) => {
|
||||||
|
res.writeHead(200, "OK", {
|
||||||
|
"Content-Type": "text/plain"
|
||||||
|
});
|
||||||
|
res.write("Hello World!");
|
||||||
|
res.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
|
|
||||||
|
module.exports.modInfo = {
|
||||||
|
name: "Example mod with SVRouter",
|
||||||
|
version: "0.0.0"
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Methods (exported by the `svrouter` package)
|
||||||
|
|
||||||
|
### _svrouter()_
|
||||||
|
|
||||||
|
Returns: the SVRouter router, which is a SVR.JS mod function with additional functions for adding routes and middleware.
|
||||||
|
|
||||||
|
## Methods (provided by the SVRouter router)
|
||||||
|
|
||||||
|
### _router(req, res, logFacilities, config, next)_
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
- _req_ - the SVR.JS request object
|
||||||
|
- _res_ - the SVR.JS response object
|
||||||
|
- _logFacilities_ - the SVR.JS log facilities object
|
||||||
|
- _config_ - the SVR.JS configuration object
|
||||||
|
- _next_ - the callback which passes the execution to SVR.JS mods and SVR.JS internal handlers.
|
||||||
|
|
||||||
|
The function is a SVR.JS mod callback. You can read more about the SVR.JS mod callbacks in the [SVR.JS mod API documentation](https://svrjs.org/docs/api/svrjs-api).
|
||||||
|
|
||||||
|
### _router.route(method, path, callback)_
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
- _method_ - the HTTP method, for which the route applies (_String_)
|
||||||
|
- _path_ - the route path, for which the route applies. The route paths are process via the [`path-to-regexp` library](https://www.npmjs.com/package/path-to-regexp) (_String_)
|
||||||
|
- _callback_ - the SVR.JS mod callback applied for the route (_Function_)
|
||||||
|
|
||||||
|
The function adds a route to the SVRouter router.
|
||||||
|
|
||||||
|
The _callback_ parameter has these arguments of the SVR.JS mod callback:
|
||||||
|
- _req_ - the SVR.JS request object
|
||||||
|
- _res_ - the SVR.JS response object
|
||||||
|
- _logFacilities_ - the SVR.JS log facilities object
|
||||||
|
- _config_ - the SVR.JS configuration object
|
||||||
|
- _next_ - the callback which passes the execution to other routes, SVR.JS mods and SVR.JS internal handlers.
|
||||||
|
|
||||||
|
The _req_ object has an additional _params_ parameter, which contains request parameters, for example if the request URL is `/api/task/1`, and the route path is `/api/task/:id`, then the _req.params_ object is a `null` prototype object with the `id` property set to `"1"`.
|
||||||
|
|
||||||
|
You can read more about the SVR.JS mod callbacks in the [SVR.JS mod API documentation](https://svrjs.org/docs/api/svrjs-api).
|
||||||
|
|
||||||
|
### _router.pass([path, ]callback)_
|
||||||
|
|
||||||
|
Parameters:
|
||||||
|
- _path_ - the path, for which the route applies. (optional, _String_)
|
||||||
|
- _callback_ - the SVR.JS mod callback, which the SVRouter router will pass to (_Function_)
|
||||||
|
|
||||||
|
The function adds middleware to the SVRouter router. The middleware can be an another SVRouter router (the absolute request URLs need to be provided for the _router.route_ function in the SVRouter router).
|
||||||
|
|
||||||
|
The _callback_ parameter has these arguments of the SVR.JS mod callback:
|
||||||
|
- _req_ - the SVR.JS request object
|
||||||
|
- _res_ - the SVR.JS response object
|
||||||
|
- _logFacilities_ - the SVR.JS log facilities object
|
||||||
|
- _config_ - the SVR.JS configuration object
|
||||||
|
- _next_ - the callback which passes the execution to other routes, SVR.JS mods and SVR.JS internal handlers.
|
||||||
|
|
||||||
|
You can read more about the SVR.JS mod callbacks in the [SVR.JS mod API documentation](https://svrjs.org/docs/api/svrjs-api).
|
||||||
|
|
||||||
|
### _router.get(path, callback)_
|
||||||
|
An alias to the _router.route("GET", path, callback)_ function
|
||||||
|
|
||||||
|
### _router.post(path, callback)_
|
||||||
|
An alias to the _router.route("POST", path, callback)_ function
|
||||||
|
|
||||||
|
### _router.put(path, callback)_
|
||||||
|
An alias to the _router.route("PUT", path, callback)_ function
|
||||||
|
|
||||||
|
### _router.patch(path, callback)_
|
||||||
|
An alias to the _router.route("PATCH", path, callback)_ function
|
||||||
|
|
||||||
|
### _router.delete(path, callback)_
|
||||||
|
An alias to the _router.route("DELETE", path, callback)_ function
|
||||||
|
|
||||||
|
### _router.head(path, callback)_
|
||||||
|
An alias to the _router.route("HEAD", path, callback)_ function
|
3
commitlint.config.js
Normal file
3
commitlint.config.js
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
module.exports = {
|
||||||
|
extends: ["@commitlint/config-conventional"]
|
||||||
|
};
|
30
eslint.config.js
Normal file
30
eslint.config.js
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
const globals = require("globals");
|
||||||
|
const pluginJs = require("@eslint/js");
|
||||||
|
const eslintPluginPrettierRecommended = require("eslint-plugin-prettier/recommended");
|
||||||
|
const jest = require("eslint-plugin-jest");
|
||||||
|
|
||||||
|
module.exports = [
|
||||||
|
{
|
||||||
|
files: ["**/*.js"],
|
||||||
|
languageOptions: {
|
||||||
|
sourceType: "commonjs"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ["tests/*.test.js", "tests/**/*.test.js"],
|
||||||
|
...jest.configs['flat/recommended'],
|
||||||
|
rules: {
|
||||||
|
...jest.configs['flat/recommended'].rules,
|
||||||
|
'jest/prefer-expect-assertions': 'off',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
...globals.node
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
pluginJs.configs.recommended,
|
||||||
|
eslintPluginPrettierRecommended
|
||||||
|
];
|
5
jest.config.js
Normal file
5
jest.config.js
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
module.exports = {
|
||||||
|
testEnvironment: 'node',
|
||||||
|
testMatch: ['**/tests/**/*.test.js'],
|
||||||
|
verbose: true,
|
||||||
|
};
|
6
lint-staged.config.js
Normal file
6
lint-staged.config.js
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
module.exports = {
|
||||||
|
"tests/**/*.js": "eslint --cache --fix",
|
||||||
|
"src/**/*.js": "eslint --cache --fix",
|
||||||
|
"src/**/*.d.ts": "eslint --cache --fix",
|
||||||
|
"utils/**/*.js": "eslint --cache --fix"
|
||||||
|
};
|
8196
package-lock.json
generated
Normal file
8196
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
56
package.json
Normal file
56
package.json
Normal file
|
@ -0,0 +1,56 @@
|
||||||
|
{
|
||||||
|
"name": "svrouter",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"description": "A router library for SVR.JS 4.x mods",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"scripts": {
|
||||||
|
"build": "rimraf dist/* && swc -d dist src --strip-leading-paths",
|
||||||
|
"cz": "cz",
|
||||||
|
"lint": "eslint --no-error-on-unmatched-pattern src/**/*.js src/*.js tests/**/*.test.js tests/**/*.js",
|
||||||
|
"lint:fix": "npm run lint -- --fix",
|
||||||
|
"prepare": "husky",
|
||||||
|
"test": "jest",
|
||||||
|
"test:coverage": "jest --coverage"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.svrjs.org/svrjs/svrouter"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"routing",
|
||||||
|
"router",
|
||||||
|
"svrjs",
|
||||||
|
"http"
|
||||||
|
],
|
||||||
|
"license": "MIT",
|
||||||
|
"devDependencies": {
|
||||||
|
"@commitlint/cli": "^19.6.1",
|
||||||
|
"@commitlint/config-conventional": "^19.6.0",
|
||||||
|
"@eslint/js": "^9.17.0",
|
||||||
|
"@swc/cli": "^0.5.2",
|
||||||
|
"commitizen": "^4.3.1",
|
||||||
|
"cz-conventional-changelog": "^3.3.0",
|
||||||
|
"eslint": "^9.17.0",
|
||||||
|
"eslint-config-prettier": "^9.1.0",
|
||||||
|
"eslint-plugin-jest": "^28.10.0",
|
||||||
|
"eslint-plugin-prettier": "^5.2.1",
|
||||||
|
"husky": "^9.1.7",
|
||||||
|
"jest": "^29.7.0",
|
||||||
|
"lint-staged": "^15.3.0",
|
||||||
|
"prettier": "^3.4.2",
|
||||||
|
"rimraf": "^5.0.10"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"README.md",
|
||||||
|
"LICENSE",
|
||||||
|
"dist/"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"path-to-regexp": "^8.2.0"
|
||||||
|
},
|
||||||
|
"config": {
|
||||||
|
"commitizen": {
|
||||||
|
"path": "./node_modules/cz-conventional-changelog"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
15
prettier.config.js
Normal file
15
prettier.config.js
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// prettier.config.js, .prettierrc.js, prettier.config.cjs, or .prettierrc.cjs
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see https://prettier.io/docs/en/configuration.html
|
||||||
|
* @type {import("prettier").Config}
|
||||||
|
*/
|
||||||
|
const config = {
|
||||||
|
trailingComma: "none",
|
||||||
|
tabWidth: 2,
|
||||||
|
semi: true,
|
||||||
|
singleQuote: false,
|
||||||
|
endOfLine: "lf"
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = config;
|
105
src/index.js
Normal file
105
src/index.js
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
const { match } = require("path-to-regexp");
|
||||||
|
const http = require("http");
|
||||||
|
|
||||||
|
function svrouter() {
|
||||||
|
const routes = [];
|
||||||
|
|
||||||
|
const addRoute = (method, path, callback) => {
|
||||||
|
if (typeof method !== "string") {
|
||||||
|
throw new Error("The HTTP method must be a string.");
|
||||||
|
} else if (typeof path !== "string") {
|
||||||
|
throw new Error("The route path must be a string.");
|
||||||
|
} else if (typeof callback !== "function") {
|
||||||
|
throw new Error("The route callback must be a function.");
|
||||||
|
}
|
||||||
|
|
||||||
|
routes.push({
|
||||||
|
method: method.toUpperCase(),
|
||||||
|
pathFunction: match(path),
|
||||||
|
callback: callback
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const passRoute = (path, callback) => {
|
||||||
|
const realCallback = callback ? callback : path;
|
||||||
|
if (typeof realCallback !== "function") {
|
||||||
|
throw new Error("The passed callback must be a function.");
|
||||||
|
} else if (callback && typeof path !== "string") {
|
||||||
|
throw new Error("The path must be a function");
|
||||||
|
}
|
||||||
|
|
||||||
|
routes.push({
|
||||||
|
method: null,
|
||||||
|
pathFunction: callback
|
||||||
|
? (checkedPath) =>
|
||||||
|
checkedPath == path ||
|
||||||
|
checkedPath.substring(0, path.length + 1) == path + "/"
|
||||||
|
? {
|
||||||
|
path: checkedPath,
|
||||||
|
params: null
|
||||||
|
}
|
||||||
|
: false
|
||||||
|
: () => true,
|
||||||
|
callback: realCallback
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const router = (req, res, logFacilities, config, next) => {
|
||||||
|
let index = 0;
|
||||||
|
let previousReqParams = req.params;
|
||||||
|
let paramsPresent = false;
|
||||||
|
|
||||||
|
const nextRoute = () => {
|
||||||
|
if (paramsPresent) req.params = previousReqParams;
|
||||||
|
let currentRoute = routes[index++];
|
||||||
|
let currentMatch =
|
||||||
|
currentRoute && currentRoute.pathFunction
|
||||||
|
? currentRoute.pathFunction(req.parsedURL.pathname)
|
||||||
|
: false;
|
||||||
|
while (
|
||||||
|
currentRoute &&
|
||||||
|
((currentRoute.method && req.method != currentRoute.method) ||
|
||||||
|
!currentMatch)
|
||||||
|
) {
|
||||||
|
currentRoute = routes[index++];
|
||||||
|
currentMatch =
|
||||||
|
currentRoute && currentRoute.pathFunction
|
||||||
|
? currentRoute.pathFunction(req.parsedURL.pathname)
|
||||||
|
: false;
|
||||||
|
}
|
||||||
|
if (currentRoute && currentRoute.callback) {
|
||||||
|
try {
|
||||||
|
paramsPresent = Boolean(currentMatch.params);
|
||||||
|
if (paramsPresent)
|
||||||
|
req.params =
|
||||||
|
currentMatch && currentMatch.params
|
||||||
|
? currentMatch.params
|
||||||
|
: Object.create(null);
|
||||||
|
currentRoute.callback(req, res, logFacilities, config, nextRoute);
|
||||||
|
} catch (err) {
|
||||||
|
res.error(500, err);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
nextRoute();
|
||||||
|
};
|
||||||
|
|
||||||
|
const methods = http.METHODS
|
||||||
|
? http.METHODS
|
||||||
|
: ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD"];
|
||||||
|
|
||||||
|
methods.forEach((method) => {
|
||||||
|
router[method.toLowerCase()] = (path, callback) =>
|
||||||
|
addRoute(method, path, callback);
|
||||||
|
});
|
||||||
|
|
||||||
|
router.route = addRoute;
|
||||||
|
router.pass = passRoute;
|
||||||
|
|
||||||
|
return router;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = svrouter;
|
168
tests/index.test.js
Normal file
168
tests/index.test.js
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
const svrouter = require("../src/index.js");
|
||||||
|
|
||||||
|
describe("SVRouter", () => {
|
||||||
|
let router;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
router = svrouter();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should add and handle a GET route", () => {
|
||||||
|
const req = {
|
||||||
|
method: "GET",
|
||||||
|
parsedURL: { pathname: "/test" },
|
||||||
|
params: null
|
||||||
|
};
|
||||||
|
const res = {
|
||||||
|
end: jest.fn()
|
||||||
|
};
|
||||||
|
|
||||||
|
router.get("/test", (req, res) => {
|
||||||
|
res.end("GET route matched");
|
||||||
|
});
|
||||||
|
|
||||||
|
router(req, res, null, null, () => {
|
||||||
|
res.end("No route matched");
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.end).toHaveBeenCalledWith("GET route matched");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should add and handle a POST route", () => {
|
||||||
|
const req = {
|
||||||
|
method: "POST",
|
||||||
|
parsedURL: { pathname: "/submit" },
|
||||||
|
params: null
|
||||||
|
};
|
||||||
|
const res = {
|
||||||
|
end: jest.fn()
|
||||||
|
};
|
||||||
|
|
||||||
|
router.post("/submit", (req, res) => {
|
||||||
|
res.end("POST route matched");
|
||||||
|
});
|
||||||
|
|
||||||
|
router(req, res, null, null, () => {
|
||||||
|
res.end("No route matched");
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.end).toHaveBeenCalledWith("POST route matched");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should correctly parse parameters in the route", () => {
|
||||||
|
const req = {
|
||||||
|
method: "GET",
|
||||||
|
parsedURL: { pathname: "/user/42" },
|
||||||
|
params: null
|
||||||
|
};
|
||||||
|
const res = {
|
||||||
|
end: jest.fn()
|
||||||
|
};
|
||||||
|
|
||||||
|
router.get("/user/:id", (req, res) => {
|
||||||
|
res.end(`User ID is ${req.params.id}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
router(req, res, null, null, () => {
|
||||||
|
res.end("No route matched");
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.end).toHaveBeenCalledWith("User ID is 42");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should pass to next middleware when no route matches", () => {
|
||||||
|
const req = {
|
||||||
|
method: "GET",
|
||||||
|
parsedURL: { pathname: "/nonexistent" },
|
||||||
|
params: null
|
||||||
|
};
|
||||||
|
const res = {
|
||||||
|
end: jest.fn()
|
||||||
|
};
|
||||||
|
|
||||||
|
const next = jest.fn();
|
||||||
|
|
||||||
|
router(req, res, null, null, next);
|
||||||
|
|
||||||
|
expect(next).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should add a route using router.route", () => {
|
||||||
|
const req = {
|
||||||
|
method: "PUT",
|
||||||
|
parsedURL: { pathname: "/update" },
|
||||||
|
params: null
|
||||||
|
};
|
||||||
|
const res = {
|
||||||
|
end: jest.fn()
|
||||||
|
};
|
||||||
|
|
||||||
|
router.route("PUT", "/update", (req, res) => {
|
||||||
|
res.end("PUT route matched");
|
||||||
|
});
|
||||||
|
|
||||||
|
router(req, res, null, null, () => {
|
||||||
|
res.end("No route matched");
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.end).toHaveBeenCalledWith("PUT route matched");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should add a pass-through route with router.pass", () => {
|
||||||
|
const req = {
|
||||||
|
method: "DELETE",
|
||||||
|
parsedURL: { pathname: "/anything" },
|
||||||
|
params: null
|
||||||
|
};
|
||||||
|
const res = {
|
||||||
|
end: jest.fn()
|
||||||
|
};
|
||||||
|
|
||||||
|
router.pass((req, res) => {
|
||||||
|
res.end("Pass-through matched");
|
||||||
|
});
|
||||||
|
|
||||||
|
router(req, res, null, null, () => {
|
||||||
|
res.end("No route matched");
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(res.end).toHaveBeenCalledWith("Pass-through matched");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should throw an error if method is not a string in route", () => {
|
||||||
|
expect(() => {
|
||||||
|
router.route(123, "/path", () => {});
|
||||||
|
}).toThrow("The HTTP method must be a string.");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should throw an error if callback is not a function in route", () => {
|
||||||
|
expect(() => {
|
||||||
|
router.route("GET", "/path", "not a function");
|
||||||
|
}).toThrow("The route callback must be a function.");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should throw an error if path is not a string in passRoute", () => {
|
||||||
|
expect(() => {
|
||||||
|
router.pass(123, () => {});
|
||||||
|
}).toThrow("The path must be a function");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("should handle errors thrown in route callbacks gracefully", () => {
|
||||||
|
const req = {
|
||||||
|
method: "GET",
|
||||||
|
parsedURL: { pathname: "/error" },
|
||||||
|
params: null
|
||||||
|
};
|
||||||
|
const res = {
|
||||||
|
error: jest.fn()
|
||||||
|
};
|
||||||
|
|
||||||
|
router.get("/error", () => {
|
||||||
|
throw new Error("Test error");
|
||||||
|
});
|
||||||
|
|
||||||
|
router(req, res, null, null, () => {});
|
||||||
|
|
||||||
|
expect(res.error).toHaveBeenCalledWith(500, expect.any(Error));
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in a new issue