deno.land / x / opine@2.3.4 / test / units / app.router.test.ts
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264import { opine, Router } from "../../mod.ts";import { expect, superdeno } from "../deps.ts";import { after, describe, it } from "../utils.ts";import { methods } from "../../src/methods.ts";import type { NextFunction, OpineRequest, OpineResponse,} from "../../src/types.ts";
describe("app.router", function () { it("should restore req.params after leaving router", function (done) { const app = opine(); const router = Router();
function handler1( req: OpineRequest, res: OpineResponse, next: NextFunction, ) { res.set("x-user-id", String(req.params.id)); next(); }
function handler2(req: OpineRequest, res: OpineResponse) { res.send(req.params.id); }
router.use( function (req: OpineRequest, res: OpineResponse, next: NextFunction) { res.set("x-router", String(req.params.id)); next(); }, );
app.get("/user/:id", handler1, router, handler2);
superdeno(app) .get("/user/1") .expect("x-router", "undefined") .expect("x-user-id", "1") .expect(200, "1", done); });
describe("methods", function () { methods.forEach(function (method) { if (method === "connect") return;
it("should include " + method.toUpperCase(), function (done) { const app = opine();
(app as any)[method]( "/foo", function (req: OpineRequest, res: OpineResponse) { res.send(method); }, );
(superdeno(app) as any)[method]("/foo") .expect(200, done); });
it("should reject numbers for app." + method, function () { const app = opine(); expect((app as any)[method].bind(app, "/", 3)).toThrow(/Number/); }); });
it("should re-route when method is altered", function (done) { const app = opine(); const cb = after(3, done);
app.use( function (req: OpineRequest, res: OpineResponse, next: NextFunction) { if (req.method !== "POST") return next(); req.method = "DELETE"; res.set("X-Method-Altered", "1"); next(); }, );
app.delete("/", function (req: OpineRequest, res: OpineResponse) { res.end("deleted everything"); });
superdeno(app) .get("/") .expect(404, cb);
superdeno(app) .delete("/") .expect(200, "deleted everything", cb);
superdeno(app) .post("/") .expect("X-Method-Altered", "1") .expect(200, "deleted everything", cb); }); });
describe("decode params", function () { it("should decode correct params", function (done) { const app = opine();
app.get( "/:name", function (req: OpineRequest, res: OpineResponse, next: NextFunction) { res.send(req.params.name); }, );
superdeno(app) .get("/foo%2Fbar") .expect("foo/bar", done); });
it("should not accept params in malformed paths", function (done) { const app = opine();
app.get( "/:name", function (req: OpineRequest, res: OpineResponse, next: NextFunction) { res.send(req.params.name); }, );
superdeno(app) .get("/%foobar") .expect(400, done); });
it("should not decode spaces", function (done) { const app = opine();
app.get( "/:name", function (req: OpineRequest, res: OpineResponse, next: NextFunction) { res.send(req.params.name); }, );
superdeno(app) .get("/foo+bar") .expect("foo+bar", done); });
it("should work with unicode", function (done) { const app = opine();
app.get( "/:name", function (req: OpineRequest, res: OpineResponse, next: NextFunction) { res.send(req.params.name); }, );
superdeno(app) .get("/%ce%b1") .expect("\u03b1", done); }); });
it("should be .use()able", function (done) { const app = opine(); let calls: any[] = [];
app.use( function (req: OpineRequest, res: OpineResponse, next: NextFunction) { calls.push("before"); next(); }, );
app.get( "/", function (req: OpineRequest, res: OpineResponse, next: NextFunction) { calls.push("GET /"); next(); }, );
app.use( function (req: OpineRequest, res: OpineResponse, next: NextFunction) { calls.push("after"); res.json(calls); }, );
superdeno(app) .get("/") .expect(200, ["before", "GET /", "after"], done); });
describe("when given a regexp", function () { it("should match the pathname only", function (done) { const app = opine();
app.get( /^\/user\/[0-9]+$/, function (req: OpineRequest, res: OpineResponse) { res.end("user"); }, );
superdeno(app) .get("/user/12?foo=bar") .expect("user", done); });
it("should populate req.params with the captures", function (done) { const app = opine();
app.get( /^\/user\/([0-9]+)\/(view|edit)?$/, function (req: OpineRequest, res: OpineResponse) { const id = req.params[0], op = req.params[1]; res.end(op + "ing user " + id); }, );
superdeno(app) .get("/user/10/edit") .expect("editing user 10", done); }); });
describe("case sensitivity", function () { it("should be disabled by default", function (done) { const app = opine();
app.get("/user", function (req: OpineRequest, res: OpineResponse) { res.end("deno"); });
superdeno(app) .get("/USER") .expect("deno", done); });
describe('when "case sensitive routing" is enabled', function () { it("should match identical casing", function (done) { const app = opine();
app.enable("case sensitive routing");
app.get("/uSer", function (req: OpineRequest, res: OpineResponse) { res.end("deno"); });
superdeno(app) .get("/uSer") .expect("deno", done); });
it("should not match otherwise", function (done) { const app = opine();
app.enable("case sensitive routing");
app.get("/uSer", function (req: OpineRequest, res: OpineResponse) { res.end("deno"); });
superdeno(app) .get("/user") .expect(404, done); }); }); });
describe("params", function () { it("should overwrite existing req.params by default", function (done) { const app = opine(); const router = Router();
router.get("/:action", function (req: OpineRequest, res: OpineResponse) { res.send(req.params); });
app.use("/user/:user", router);
superdeno(app) .get("/user/1/get") .expect(200, '{"action":"get"}', done); });
it("should allow merging existing req.params", function (done) { const app = opine(); const router = new Router({ mergeParams: true });
router.get("/:action", function (req: OpineRequest, res: OpineResponse) { const keys = Object.keys(req.params).sort(); res.send(keys.map(function (k) { return [k, req.params[k]]; })); });
app.use("/user/:user", router);
superdeno(app) .get("/user/deno/get") .expect(200, '[["action","get"],["user","deno"]]', done); });
it("should use params from router", function (done) { const app = opine(); const router = new Router({ mergeParams: true });
router.get("/:thing", function (req: OpineRequest, res: OpineResponse) { const keys = Object.keys(req.params).sort(); res.send(keys.map(function (k) { return [k, req.params[k]]; })); });
app.use("/user/:thing", router);
superdeno(app) .get("/user/deno/get") .expect(200, '[["thing","get"]]', done); });
it("should merge numeric indices req.params", function (done) { const app = opine(); const router = new Router({ mergeParams: true });
router.get("/*.*", function (req: OpineRequest, res: OpineResponse) { const keys = Object.keys(req.params).sort(); res.send(keys.map(function (k) { return [k, req.params[k]]; })); });
app.use("/user/id:(\\d+)", router);
superdeno(app) .get("/user/id:10/profile.json") .expect(200, '[["0","10"],["1","profile"],["2","json"]]', done); });
it("should merge numeric indices req.params when more in parent", function ( done, ) { const app = opine(); const router = new Router({ mergeParams: true });
router.get("/*", function (req: OpineRequest, res: OpineResponse) { const keys = Object.keys(req.params).sort(); res.send(keys.map(function (k) { return [k, req.params[k]]; })); });
app.use("/user/id:(\\d+)/name:(\\w+)", router);
superdeno(app) .get("/user/id:10/name:deno/profile") .expect(200, '[["0","10"],["1","deno"],["2","profile"]]', done); });
it( "should merge numeric indices req.params when parent has same number", function ( done, ) { const app = opine(); const router = new Router({ mergeParams: true });
router.get( "/name:(\\w+)", function (req: OpineRequest, res: OpineResponse) { const keys = Object.keys(req.params).sort(); res.send(keys.map(function (k) { return [k, req.params[k]]; })); }, );
app.use("/user/id:(\\d+)", router);
superdeno(app) .get("/user/id:10/name:deno") .expect(200, '[["0","10"],["1","deno"]]', done); }, );
it("should ignore invalid incoming req.params", function (done) { const app = opine(); const router = new Router({ mergeParams: true });
router.get("/:name", function (req: OpineRequest, res: OpineResponse) { const keys = Object.keys(req.params).sort(); res.send(keys.map(function (k) { return [k, req.params[k]]; })); });
app.use( "/user/", function (req: OpineRequest, res: OpineResponse, next: NextFunction) { (req as any).params = 3; // wat? router(req, res, next); }, );
superdeno(app) .get("/user/deno") .expect(200, '[["name","deno"]]', done); });
it("should restore req.params", function (done) { const app = opine(); const router = new Router({ mergeParams: true });
router.get( "/user:(\\w+)/*", function (req: OpineRequest, res: OpineResponse, next: NextFunction) { next(); }, );
app.use( "/user/id:(\\d+)", function (req: OpineRequest, res: OpineResponse, next: NextFunction) { router(req, res, function (err: any) { const keys = Object.keys(req.params).sort(); res.send(keys.map(function (k) { return [k, req.params[k]]; })); }); }, );
superdeno(app) .get("/user/id:42/user:deno/profile") .expect(200, '[["0","42"]]', done); }); });
describe("trailing slashes", function () { it("should be optional by default", function (done) { const app = opine();
app.get("/user", function (req: OpineRequest, res: OpineResponse) { res.end("deno"); });
superdeno(app) .get("/user/") .expect("deno", done); });
describe('when "strict routing" is enabled', function () { it("should match trailing slashes", function (done) { const app = opine();
app.enable("strict routing");
app.get("/user/", function (req: OpineRequest, res: OpineResponse) { res.end("deno"); });
superdeno(app) .get("/user/") .expect("deno", done); });
it("should pass-though middleware", function (done) { const app = opine();
app.enable("strict routing");
app.use( function (req: OpineRequest, res: OpineResponse, next: NextFunction) { res.set("x-middleware", "true"); next(); }, );
app.get("/user/", function (req: OpineRequest, res: OpineResponse) { res.end("deno"); });
superdeno(app) .get("/user/") .expect("x-middleware", "true") .expect(200, "deno", done); });
it("should pass-though mounted middleware", function (done) { const app = opine();
app.enable("strict routing");
app.use( "/user/", function (req: OpineRequest, res: OpineResponse, next: NextFunction) { res.set("x-middleware", "true"); next(); }, );
app.get( "/user/test/", function (req: OpineRequest, res: OpineResponse) { res.end("deno"); }, );
superdeno(app) .get("/user/test/") .expect("x-middleware", "true") .expect(200, "deno", done); });
it("should match no slashes", function (done) { const app = opine();
app.enable("strict routing");
app.get("/user", function (req: OpineRequest, res: OpineResponse) { res.end("deno"); });
superdeno(app) .get("/user") .expect("deno", done); });
it("should match middleware when omitting the trailing slash", function ( done, ) { const app = opine();
app.enable("strict routing");
app.use("/user/", function (req: OpineRequest, res: OpineResponse) { res.end("deno"); });
superdeno(app) .get("/user") .expect(200, "deno", done); });
it("should match middleware", function (done) { const app = opine();
app.enable("strict routing");
app.use("/user", function (req: OpineRequest, res: OpineResponse) { res.end("deno"); });
superdeno(app) .get("/user") .expect(200, "deno", done); });
it("should match middleware when adding the trailing slash", function ( done, ) { const app = opine();
app.enable("strict routing");
app.use("/user", function (req: OpineRequest, res: OpineResponse) { res.end("deno"); });
superdeno(app) .get("/user/") .expect(200, "deno", done); });
it("should fail when omitting the trailing slash", function (done) { const app = opine();
app.enable("strict routing");
app.get("/user/", function (req: OpineRequest, res: OpineResponse) { res.end("deno"); });
superdeno(app) .get("/user") .expect(404, done); });
it("should fail when adding the trailing slash", function (done) { const app = opine();
app.enable("strict routing");
app.get("/user", function (req: OpineRequest, res: OpineResponse) { res.end("deno"); });
superdeno(app) .get("/user/") .expect(404, done); }); }); });
it("should allow escaped regexp", function (done) { const app = opine();
app.get("/user/\\d+", function (req: OpineRequest, res: OpineResponse) { res.end("woot"); });
superdeno(app) .get("/user/10") .expect(200, function (err: any) { if (err) return done(err); superdeno(app) .get("/user/deno") .expect(404, done); }); });
it('should allow literal "."', function (done) { const app = opine();
app.get( "/api/users/:from..:to", function (req: OpineRequest, res: OpineResponse) { const from = req.params.from; const to = req.params.to;
res.end("users from " + from + " to " + to); }, );
superdeno(app) .get("/api/users/1..50") .expect("users from 1 to 50", done); });
describe("*", function () { it("should capture everything", function (done) { const app = opine();
app.get("*", function (req: OpineRequest, res: OpineResponse) { res.end(req.params[0]); });
superdeno(app) .get("/user/deno.json") .expect("/user/deno.json", done); });
it("should decode the capture", function (done) { const app = opine();
app.get("*", function (req: OpineRequest, res: OpineResponse) { res.end(req.params[0]); });
superdeno(app) .get("/user/deno%20and%20superdeno.json") .expect("/user/deno and superdeno.json", done); });
it("should denote a greedy capture group", function (done) { const app = opine();
app.get("/user/*.json", function (req: OpineRequest, res: OpineResponse) { res.end(req.params[0]); });
superdeno(app) .get("/user/deno.json") .expect("deno", done); });
it("should work with several", function (done) { const app = opine();
app.get("/api/*.*", function (req: OpineRequest, res: OpineResponse) { const resource = req.params[0]; const format = req.params[1]; res.end(resource + " as " + format); });
superdeno(app) .get("/api/users/foo.bar.json") .expect("users/foo.bar as json", done); });
it("should work cross-segment", function (done) { const app = opine();
app.get("/api*", function (req: OpineRequest, res: OpineResponse) { res.send(req.params[0]); });
superdeno(app) .get("/api") .expect("", function () { superdeno(app) .get("/api/hey") .expect("/hey", done); }); });
it("should allow naming", function (done) { const app = opine();
app.get( "/api/:resource(*)", function (req: OpineRequest, res: OpineResponse) { const resource = req.params.resource; res.end(resource); }, );
superdeno(app) .get("/api/users/0.json") .expect("users/0.json", done); });
it("should not be greedy immediately after param", function (done) { const app = opine();
app.get("/user/:user*", function (req: OpineRequest, res: OpineResponse) { res.end(req.params.user); });
superdeno(app) .get("/user/122") .expect("122", done); });
it("should eat everything after /", function (done) { const app = opine();
app.get("/user/:user*", function (req: OpineRequest, res: OpineResponse) { res.end(req.params.user); });
superdeno(app) .get("/user/122/aaa") .expect("122", done); });
it("should span multiple segments", function (done) { const app = opine();
app.get("/file/*", function (req: OpineRequest, res: OpineResponse) { res.end(req.params[0]); });
superdeno(app) .get("/file/javascripts/jquery.js") .expect("javascripts/jquery.js", done); });
it("should be optional", function (done) { const app = opine();
app.get("/file/*", function (req: OpineRequest, res: OpineResponse) { res.end(req.params[0]); });
superdeno(app) .get("/file/") .expect("", done); });
it("should require a preceding /", function (done) { const app = opine();
app.get("/file/*", function (req: OpineRequest, res: OpineResponse) { res.end(req.params[0]); });
superdeno(app) .get("/file") .expect(404, done); });
it("should keep correct parameter indexes", function (done) { const app = opine();
app.get("/*/user/:id", function (req: OpineRequest, res: OpineResponse) { res.send(req.params); });
superdeno(app) .get("/1/user/2") .expect(200, '{"0":"1","id":"2"}', done); });
it("should work within arrays", function (done) { const app = opine();
app.get( ["/user/:id", "/foo/*", "/:bar"], function (req: OpineRequest, res: OpineResponse) { res.send(req.params.bar); }, );
superdeno(app) .get("/test") .expect(200, "test", done); }); });
describe(":name", function () { it("should denote a capture group", function (done) { const app = opine();
app.get("/user/:user", function (req: OpineRequest, res: OpineResponse) { res.end(req.params.user); });
superdeno(app) .get("/user/deno") .expect("deno", done); });
it("should match a single segment only", function (done) { const app = opine();
app.get("/user/:user", function (req: OpineRequest, res: OpineResponse) { res.end(req.params.user); });
superdeno(app) .get("/user/deno/edit") .expect(404, done); });
it("should allow several capture groups", function (done) { const app = opine();
app.get( "/user/:user/:op", function (req: OpineRequest, res: OpineResponse) { res.end(req.params.op + "ing " + req.params.user); }, );
superdeno(app) .get("/user/deno/edit") .expect("editing deno", done); });
it("should work following a partial capture group", function (done) { const app = opine(); const cb = after(2, done);
app.get( "/user(s)?/:user/:op", function (req: OpineRequest, res: OpineResponse) { res.end( req.params.op + "ing " + req.params.user + (req.params[0] ? " (old)" : ""), ); }, );
superdeno(app) .get("/user/deno/edit") .expect("editing deno", cb);
superdeno(app) .get("/users/deno/edit") .expect("editing deno (old)", cb); });
it("should work inside literal parenthesis", function (done) { const app = opine();
app.get( "/:user\\(:op\\)", function (req: OpineRequest, res: OpineResponse) { res.end(req.params.op + "ing " + req.params.user); }, );
superdeno(app) .get("/deno(edit)") .expect("editing deno", done); });
it("should work in array of paths", function (done) { const app = opine(); const cb = after(2, done);
app.get( ["/user/:user/poke", "/user/:user/pokes"], function (req: OpineRequest, res: OpineResponse) { res.end("poking " + req.params.user); }, );
superdeno(app) .get("/user/deno/poke") .expect("poking deno", cb);
superdeno(app) .get("/user/deno/pokes") .expect("poking deno", cb); }); });
describe(":name?", function () { it("should denote an optional capture group", function (done) { const app = opine();
app.get( "/user/:user/:op?", function (req: OpineRequest, res: OpineResponse) { const op = req.params.op || "view"; res.end(op + "ing " + req.params.user); }, );
superdeno(app) .get("/user/deno") .expect("viewing deno", done); });
it("should populate the capture group", function (done) { const app = opine();
app.get( "/user/:user/:op?", function (req: OpineRequest, res: OpineResponse) { const op = req.params.op || "view"; res.end(op + "ing " + req.params.user); }, );
superdeno(app) .get("/user/deno/edit") .expect("editing deno", done); }); });
describe(".:name", function () { it("should denote a format", function (done) { const app = opine();
app.get( "/:name.:format", function (req: OpineRequest, res: OpineResponse) { res.end(req.params.name + " as " + req.params.format); }, );
superdeno(app) .get("/foo.json") .expect("foo as json", function () { superdeno(app) .get("/foo") .expect(404, done); }); }); });
describe(".:name?", function () { it("should denote an optional format", function (done) { const app = opine();
app.get( "/:name.:format?", function (req: OpineRequest, res: OpineResponse) { res.end(req.params.name + " as " + (req.params.format || "html")); }, );
superdeno(app) .get("/foo") .expect("foo as html", function () { superdeno(app) .get("/foo.json") .expect("foo as json", done); }); }); });
describe("when next() is called", function () { it("should continue lookup", function (done) { const app = opine(); const calls: any[] = [];
app.get( "/foo/:bar?", function (req: OpineRequest, res: OpineResponse, next: NextFunction) { calls.push("/foo/:bar?"); next(); }, );
app.get("/bar", function (req: OpineRequest, res: OpineResponse) { throw new Error("should not be called"); });
app.get( "/foo", function (req: OpineRequest, res: OpineResponse, next: NextFunction) { calls.push("/foo"); next(); }, );
app.get( "/foo", function (req: OpineRequest, res: OpineResponse, next: NextFunction) { calls.push("/foo 2"); res.json(calls); }, );
superdeno(app) .get("/foo") .expect(200, ["/foo/:bar?", "/foo", "/foo 2"], done); }); });
describe('when next("route") is called', function () { it("should jump to next route", function (done) { const app = opine();
function fn(req: OpineRequest, res: OpineResponse, next: NextFunction) { res.set("X-Hit", "1"); next("route"); }
app.get( "/foo", fn, function (req: OpineRequest, res: OpineResponse, next: NextFunction) { res.end("failure"); }, );
app.get("/foo", function (req: OpineRequest, res: OpineResponse) { res.end("success"); });
superdeno(app) .get("/foo") .expect("X-Hit", "1") .expect(200, "success", done); }); });
describe('when next("router") is called', function () { it("should jump out of router", function (done) { const app = opine(); const router = Router();
function fn(req: OpineRequest, res: OpineResponse, next: NextFunction) { res.set("X-Hit", "1"); next("router"); }
router.get( "/foo", fn, function (req: OpineRequest, res: OpineResponse, next: NextFunction) { res.end("failure"); }, );
router.get( "/foo", function (req: OpineRequest, res: OpineResponse, next: NextFunction) { res.end("failure"); }, );
app.use(router);
app.get("/foo", function (req: OpineRequest, res: OpineResponse) { res.end("success"); });
superdeno(app) .get("/foo") .expect("X-Hit", "1") .expect(200, "success", done); }); });
describe("when next(err) is called", function () { it("should break out of app.router", function (done) { const app = opine(); const calls: any[] = [];
app.get( "/foo/:bar?", function (req: OpineRequest, res: OpineResponse, next: NextFunction) { calls.push("/foo/:bar?"); next(); }, );
app.get("/bar", function (req: OpineRequest, res: OpineResponse) { throw new Error("should not be called"); });
app.get( "/foo", function (req: OpineRequest, res: OpineResponse, next: NextFunction) { calls.push("/foo"); next(new Error("fail")); }, );
app.get( "/foo", function (req: OpineRequest, res: OpineResponse, next: NextFunction) { throw new Error("should not be called"); }, );
app.use( function ( err: any, req: OpineRequest, res: OpineResponse, next: NextFunction, ) { res.json({ calls: calls, error: err.message, }); }, );
superdeno(app) .get("/foo") .expect(200, { calls: ["/foo/:bar?", "/foo"], error: "fail" }, done); });
it("should call handler in same route, if exists", function (done) { const app = opine();
function fn1(req: OpineRequest, res: OpineResponse, next: NextFunction) { next(new Error("boom!")); }
function fn2(req: OpineRequest, res: OpineResponse, next: NextFunction) { res.send("foo here"); }
function fn3( err: any, req: OpineRequest, res: OpineResponse, next: NextFunction, ) { res.send("route go " + err.message); }
app.get("/foo", fn1, fn2, fn3);
app.use( function ( err: any, req: OpineRequest, res: OpineResponse, next: NextFunction, ) { res.end("error!"); }, );
superdeno(app) .get("/foo") .expect("route go boom!", done); }); });
it("should allow rewriting of the url", function (done) { const app = opine();
app.get( "/account/edit", function (req: OpineRequest, res: OpineResponse, next: NextFunction) { (req as any).user = { id: 12 }; // faux authenticated user req.url = "/user/" + (req as any).user.id + "/edit"; next(); }, );
app.get("/user/:id/edit", function (req: OpineRequest, res: OpineResponse) { res.send("editing user " + req.params.id); });
superdeno(app) .get("/account/edit") .expect("editing user 12", done); });
it("should run in order added", function (done) { const app = opine(); const path: any[] = [];
app.get( "*", function (req: OpineRequest, res: OpineResponse, next: NextFunction) { path.push(0); next(); }, );
app.get( "/user/:id", function (req: OpineRequest, res: OpineResponse, next: NextFunction) { path.push(1); next(); }, );
app.use( function (req: OpineRequest, res: OpineResponse, next: NextFunction) { path.push(2); next(); }, );
app.all( "/user/:id", function (req: OpineRequest, res: OpineResponse, next: NextFunction) { path.push(3); next(); }, );
app.get( "*", function (req: OpineRequest, res: OpineResponse, next: NextFunction) { path.push(4); next(); }, );
app.use( function (req: OpineRequest, res: OpineResponse, next: NextFunction) { path.push(5); res.end(path.join(",")); }, );
superdeno(app) .get("/user/1") .expect(200, "0,1,2,3,4,5", done); });
it("should be chainable", function () { const app = opine(); expect(app.get("/", function () {})).toEqual(app); });});
Version Info