Skip to content

Commit

Permalink
feat(server): createMiddlewareHandlerContext (#17)
Browse files Browse the repository at this point in the history
  • Loading branch information
uki00a authored Aug 24, 2023
1 parent adc3430 commit 6c3fc7a
Show file tree
Hide file tree
Showing 10 changed files with 413 additions and 70 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@
.env.test.local
.env.production.local
.env.local

.vscode
33 changes: 33 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,39 @@ describe("islands/Counter.tsx", () => {
});
```

### Testing fresh middlewares

You can test fresh middlewares using `createMiddlewareHandlerContext` API:

```ts
import { createMiddlewareHandlerContext } from "$fresh-testing-library";
import { assert, assertEquals } from "$std/testing/asserts.ts";
import { describe, it } from "$std/testing/bdd.ts";

import { createLoggerMiddleware } from "./demo/routes/(_middlewares)/logger.ts";
import manifest from "./demo/fresh.gen.ts";

describe("createLoggerMiddleware", () => {
it("returns a middleware which logs the information about each request", async () => {
const messages: Array<string> = [];
const testingLogger = {
info(...args: Array<unknown>) {
messages.push(args.map(String).join(""));
},
};
const middleware = createLoggerMiddleware(testingLogger);
const path = `/api/users/123`;
const req = new Request(`http://localhost:3000${path}`);
const ctx = createMiddlewareHandlerContext(req, { manifest });
await middleware(req, ctx);
assertEquals(messages, [
`<-- GET ${path}`,
`--> GET ${path} 200`,
]);
});
});
```

### Testing fresh handlers

You can test fresh handlers using `createHandlerContext` API:
Expand Down
20 changes: 19 additions & 1 deletion _util.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { assertEquals } from "$std/assert/assert_equals.ts";
import { describe, it } from "$std/testing/bdd.ts";

import { freshPathToURLPattern } from "./_util.ts";
import {
determineRouteDestinationKind,
freshPathToURLPattern,
} from "./_util.ts";

describe("$fresh-testing-library/_util", () => {
describe("freshPathToURLPattern", () => {
Expand Down Expand Up @@ -33,4 +36,19 @@ describe("$fresh-testing-library/_util", () => {
}
});
});

describe("determineRouteDestinationKind", () => {
for (
const [given, expected] of [
["/_frsh/refresh.js", "internal"],
["/api/users/1234", "route"],
["/api/users/1234/foo", "notFound"],
]
) {
it(`should return "${expected}" for "${given}"`, async () => {
const { default: manifest } = await import("./demo/fresh.gen.ts");
assertEquals(determineRouteDestinationKind(given, manifest), expected);
});
}
});
});
28 changes: 28 additions & 0 deletions _util.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { extname } from "node:path";
import type { Manifest } from "$fresh/server.ts";

const routeExtnames = [".tsx", ".jsx", ".mts", ".ts", ".js", ".mjs"];

Expand Down Expand Up @@ -45,3 +46,30 @@ function removeSuffix(s: string, suffix: string): string {
? s.slice(0, -suffix.length)
: s;
}

const kDestinationKindInternal = "internal" as const;
const kDesitinationKindRoute = "route" as const;
const kDesitinationKindNotFound = "notFound" as const;
// TODO: Add support for `"static"`.
// const kDesitinationKindStatic = "static" as const;
export function determineRouteDestinationKind(
path: string,
manifest?: Manifest,
) {
if (path.startsWith("/_frsh")) {
return kDestinationKindInternal;
}

if (manifest == null) {
return kDesitinationKindNotFound;
}

for (const freshPath of Object.keys(manifest.routes)) {
const pattern = freshPathToURLPattern(freshPath);
if (pattern.test({ pathname: path })) {
return kDesitinationKindRoute;
}
}

return kDesitinationKindNotFound;
}
10 changes: 6 additions & 4 deletions demo/fresh.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@

import * as $0 from "./routes/[name].tsx";
import * as $1 from "./routes/_app.tsx";
import * as $2 from "./routes/api/users/[id].ts";
import * as $3 from "./routes/index.tsx";
import * as $2 from "./routes/_middleware.ts";
import * as $3 from "./routes/api/users/[id].ts";
import * as $4 from "./routes/index.tsx";
import * as $$0 from "./islands/Counter.tsx";

const manifest = {
routes: {
"./routes/[name].tsx": $0,
"./routes/_app.tsx": $1,
"./routes/api/users/[id].ts": $2,
"./routes/index.tsx": $3,
"./routes/_middleware.ts": $2,
"./routes/api/users/[id].ts": $3,
"./routes/index.tsx": $4,
},
islands: {
"./islands/Counter.tsx": $$0,
Expand Down
15 changes: 15 additions & 0 deletions demo/routes/(_middlewares)/logger.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { MiddlewareHandler } from "$fresh/server.ts";

interface Logger {
info(...args: Array<unknown>): void;
}

export function createLoggerMiddleware(logger: Logger): MiddlewareHandler {
return async (req, ctx) => {
// Output logs in [koa-logger](https://github.com/koajs/logger) like format
logger.info(`<-- ${req.method} ${new URL(req.url).pathname}`);
const res = await ctx.next();
logger.info(`--> ${req.method} ${new URL(req.url).pathname} ${res.status}`);
return res;
};
}
3 changes: 3 additions & 0 deletions demo/routes/_middleware.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { createLoggerMiddleware } from "./(_middlewares)/logger.ts";

export const handler = createLoggerMiddleware(console);
5 changes: 4 additions & 1 deletion mod.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
export * from "./components.ts";
export { createHandlerContext } from "./server.ts";
export {
createHandlerContext,
createMiddlewareHandlerContext,
} from "./server.ts";
Loading

0 comments on commit 6c3fc7a

Please sign in to comment.