Skip to content

Latest commit

 

History

History
139 lines (109 loc) · 3.51 KB

File metadata and controls

139 lines (109 loc) · 3.51 KB
description
Add a global app wrapper to provide common meta tags or context for application routes.

To ensure that your application works as expected we can write tests. Any aspect of Fresh can be tested as a whole together or in isolation. We use Deno's built-in test runner to write tests.

Testing middlewares

To test middlewares we're going to create a dummy app and return the relevant info we want to check in a custom / handler.

import { expect } from "@std/expect";
import { App } from "fresh";

const middleware = define.middleware((ctx) => {
  ctx.state.text = "middleware text";
  return await ctx.next();
});

Deno.test("My middleware - sets ctx.state.text", async () => {
  const handler = new App()
    .use(middleware)
    .get("/", (ctx) => new Response(ctx.state.text))
    .handler();

  const res = await handler(new Request("http://localhost"));
  const text = await res.text();

  expect(text).toEqual("middleware text");
});

You can extend this pattern for other middlewares. When you have a middleware that adds a header to the returned response, you can assert against that too.

Testing app wrapper or layouts

Both the app wrapper component and layouts can be tested in the same way.

import { expect } from "@std/expect";
import { App } from "fresh";

function AppWrapper({ Component }) {
  return (
    <html lang="en">
      <head>
        <meta charset="utf-8" />
        <title>My App</title>
      </head>
      <body>
        <Component />
      </body>
    </html>
  );
}

Deno.test("App Wrapper - renders title and content", async () => {
  const handler = new App()
    .appWrapper(AppWrapper)
    .get("/", (ctx) => ctx.render(<h1>hello</h1>))
    .handler();

  const res = await handler(new Request("http://localhost"));
  const text = await res.text();

  expect(text).toContain("My App");
  expect(text).toContain("Hello");
});

Same can be done for layouts.

import { expect } from "@std/expect";
import { App } from "fresh";

function MyLayout({ Component }) {
  return (
    <div>
      <h1>My Layout</h1>
      <Component />
    </div>
  );
}

Deno.test("MyLayout - renders heading and content", async () => {
  const handler = new App()
    .layout("*", MyLayout)
    .get("/", (ctx) => ctx.render(<h1>hello</h1>))
    .handler();

  const res = await handler(new Request("http://localhost"));
  const text = await res.text();

  expect(text).toContain("My Layout");
  expect(text).toContain("Hello");
});

Testing with file routes and islands

File routes are collected by the Builder class and not just by App alone. We can generate a snapshot and re-use it for many app instances in our test suite.

// Best to do this once instead of for every test case for
// performance reasons.
const builder = new Builder();
const applySnapshot = await builder.build({ snapshot: "memory" });

function testApp() {
  const app = new App()
    .get("/", () => new Response("hello"))
    .fsRoutes();

  // Applies build snapshot to this app instance.
  applySnapshot(app);
}

Deno.test("My Test", () => {
  const handler = testApp().handler();

  const response = await handler(new Request("http://localhost"));
  const text = await response.text();

  if (text !== "hello") {
    throw new Error("fail");
  }
});