superoak

HTTP assertions for Deno's Oak web framework made easy via SuperDeno.

GitHub tag Test deno doc PRs Welcome GitHub issues GitHub stars GitHub forks superoak License Maintenance HitCount

About

This module aims to provide a high-level abstraction for testing HTTP in Deno's Oak web framework. This is a wrapper compatibility layer around SuperDeno to reduce some of the boilerplate needed to setup Oak integration + functional tests.

Installation

This is a Deno module available to import direct from this repo and via the Deno Registry.

Before importing, download and install Deno.

You can then import SuperOak straight into your project:

import { superoak } from "https://deno.land/x/superoak@master/mod.ts";

If you want to use a specific version of SuperOak, just modify the import url to contain the version:

import { superoak } from "https://deno.land/x/superoak@0.3.0/mod.ts";

Or if you want to use a specific commit of SuperOak, just modify the import url to contain the commit hash:

import { superoak } from "https://deno.land/x/superoak@c21f8d6/mod.ts";

Example

You may pass a url string (for an already running Oak server), or an Oak Application object to superoak() - when passing an Oak Application, SuperOak will automatically handle the creation of a server, binding to a free ephemeral port and closing of the server on a call to .end().

SuperOak works with any Deno test framework. Here's an example with Deno's built-in test framework, note how you can pass done straight to any of the .expect() calls:

import { superoak } from "https://deno.land/x/superoak@master/mod.ts";
import { Application, Router } from "https://deno.land/x/oak@master/mod.ts";

Deno.test("it should support the Oak framework", (done) => {
  const router = new Router();
  router.get("/", (ctx) => {
    ctx.response.body = "Hello Deno!";
  });

  const app = new Application();
  app.use(router.routes());
  app.use(router.allowedMethods());

  const request = await superoak(app);
  request.get("/").expect("Hello Deno!", done);
});

For further examples, see the tests or the SuperDeno examples for inspiration.

Docs

API

Please refer to the SuperDeno API.

Notes

  • Unlike SuperDeno, superoak() returns a promise which will need to be awaited before you can call a method such as .get("/").

  • Unlike SuperDeno, you cannot re-use a SuperOak instance once the chained .end() method has been called. This is because SuperOak will automatically close the server once the chained .end() method is called. For example the following example will fail due to this limitation:

    Deno.test(
      "it will throw a `Request has been terminated` error when trying to use an ended SuperOak object",
      async (done) => {
        const router = new Router();
        const app = new Application();
    
        router.get("/", async (ctx: RouterContext) => {
          ctx.response.body = "Hello Deno!";
        });
    
        app.use(router.routes());
        app.use(router.allowedMethods());
    
        const request = await superoak(app);
    
        request.get("/").end(() => {
          request.get("/").end((err, res) => {
            /**
             * This will have the following error:
             *
             * Error: Request has been terminated
             * Possible causes: the network is offline, Origin is not allowed by Access-Control-Allow-Origin, the page is being unloaded, etc.
             * ...
             */
            expect(err).toBeNull();
            done();
          });
        });
      }
    );

    Instead you should make all of your assertions on the one SuperOak instance, or create a new SuperOak instance like below:

    Deno.test(
      "it will allow your to re-use the Application for another SuperOak instance",
      async (done) => {
        const router = new Router();
        const app = new Application();
    
        router.get("/", async (ctx: RouterContext) => {
          ctx.response.body = "Hello Deno!";
        });
    
        app.use(router.routes());
        app.use(router.allowedMethods());
    
        let request = await superoak(app);
    
        request.get("/").end(async () => {
          request = await superoak(app);
    
          request.get("/").end((err, res) => {
            expect(err).toBeNull();
            done();
        });
      }
    );

Contributing

Contributing guide


License

SuperOak is licensed under the MIT License.