{"id":13718845,"url":"https://github.com/cmorten/superoak","last_synced_at":"2025-08-21T02:31:16.905Z","repository":{"id":45234958,"uuid":"268245288","full_name":"cmorten/superoak","owner":"cmorten","description":"HTTP assertions for Oak made easy via SuperDeno. 🐿 🦕","archived":false,"fork":false,"pushed_at":"2024-01-28T18:58:09.000Z","size":560,"stargazers_count":121,"open_issues_count":2,"forks_count":8,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-10-29T09:17:15.277Z","etag":null,"topics":["assertions","deno","deno-doc","http-assertions","http-testing","oak","superdeno","superoak","supertest","testing","typescript"],"latest_commit_sha":null,"homepage":"https://cmorten.github.io/superoak/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cmorten.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS.md","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["cmorten"]}},"created_at":"2020-05-31T09:10:20.000Z","updated_at":"2024-08-14T13:55:46.000Z","dependencies_parsed_at":"2024-08-03T01:37:37.810Z","dependency_job_id":null,"html_url":"https://github.com/cmorten/superoak","commit_stats":{"total_commits":80,"total_committers":7,"mean_commits":"11.428571428571429","dds":0.5875,"last_synced_commit":"e2179a9b08639e3366e3bac3fe3e9b7ae04bcf1a"},"previous_names":["asos-craigmorten/superoak"],"tags_count":28,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmorten%2Fsuperoak","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmorten%2Fsuperoak/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmorten%2Fsuperoak/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmorten%2Fsuperoak/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cmorten","download_url":"https://codeload.github.com/cmorten/superoak/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230479864,"owners_count":18232630,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["assertions","deno","deno-doc","http-assertions","http-testing","oak","superdeno","superoak","supertest","testing","typescript"],"created_at":"2024-08-03T01:00:38.601Z","updated_at":"2025-08-21T02:31:16.890Z","avatar_url":"https://github.com/cmorten.png","language":"TypeScript","funding_links":["https://github.com/sponsors/cmorten"],"categories":["Modules"],"sub_categories":["Testing"],"readme":"\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.linkedin.com/in/hannah-morten-b1218017a/\"\u003e\u003cimg height=\"200\" style=\"height: 200px;\" src=\"https://github.com/cmorten/superoak/raw/main/.github/icon.png\" alt=\"Super Oak standing in the rain at night – stoically facing the dark battle that is software engineering\"\u003e\u003c/a\u003e\n  \u003ch1 align=\"center\"\u003eSuperOak\u003c/h1\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n  HTTP assertions for Deno's Oak web framework made easy via \u003ca href=\"https://github.com/cmorten/superdeno\"\u003eSuperDeno\u003c/a\u003e.\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n   \u003ca href=\"https://github.com/cmorten/superoak/tags/\"\u003e\u003cimg src=\"https://img.shields.io/github/tag/cmorten/superoak\" alt=\"Current version\" /\u003e\u003c/a\u003e\n   \u003cimg src=\"https://github.com/cmorten/superoak/workflows/Test/badge.svg\" alt=\"Current test status\" /\u003e\n   \u003ca href=\"https://doc.deno.land/https/deno.land/x/superoak/mod.ts\"\u003e\u003cimg src=\"https://doc.deno.land/badge.svg\" alt=\"SuperOak docs\" /\u003e\u003c/a\u003e\n   \u003ca href=\"http://makeapullrequest.com\"\u003e\u003cimg src=\"https://img.shields.io/badge/PRs-welcome-brightgreen.svg\" alt=\"PRs are welcome\" /\u003e\u003c/a\u003e\n   \u003ca href=\"https://github.com/cmorten/superoak/issues/\"\u003e\u003cimg src=\"https://img.shields.io/github/issues/cmorten/superoak\" alt=\"SuperOak issues\" /\u003e\u003c/a\u003e\n   \u003cimg src=\"https://img.shields.io/github/stars/cmorten/superoak\" alt=\"SuperOak stars\" /\u003e\n   \u003cimg src=\"https://img.shields.io/github/forks/cmorten/superoak\" alt=\"SuperOak forks\" /\u003e\n   \u003cimg src=\"https://img.shields.io/github/license/cmorten/superoak\" alt=\"SuperOak license\" /\u003e\n   \u003ca href=\"https://GitHub.com/cmorten/superoak/graphs/commit-activity\"\u003e\u003cimg src=\"https://img.shields.io/badge/Maintained%3F-yes-green.svg\" alt=\"SuperOak is maintained\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n   \u003ca href=\"https://deno.land/x/superoak\"\u003e\u003cimg src=\"https://img.shields.io/endpoint?url=https%3A%2F%2Fdeno-visualizer.danopia.net%2Fshields%2Flatest-version%2Fx%2Fsuperoak%2Fmod.ts\" alt=\"SuperOak latest /x/ version\" /\u003e\u003c/a\u003e\n   \u003ca href=\"https://github.com/denoland/deno/blob/main/Releases.md\"\u003e\u003cimg src=\"https://img.shields.io/badge/deno-^2.3.3-brightgreen?logo=deno\" alt=\"Minimum supported Deno version\" /\u003e\u003c/a\u003e\n   \u003ca href=\"https://deno-visualizer.danopia.net/dependencies-of/https/deno.land/x/superoak/mod.ts\"\u003e\u003cimg src=\"https://img.shields.io/endpoint?url=https%3A%2F%2Fdeno-visualizer.danopia.net%2Fshields%2Fdep-count%2Fx%2Fsuperoak%2Fmod.ts\" alt=\"SuperOak dependency count\" /\u003e\u003c/a\u003e\n   \u003ca href=\"https://deno-visualizer.danopia.net/dependencies-of/https/deno.land/x/superoak/mod.ts\"\u003e\u003cimg src=\"https://img.shields.io/endpoint?url=https%3A%2F%2Fdeno-visualizer.danopia.net%2Fshields%2Fupdates%2Fx%2Fsuperoak%2Fmod.ts\" alt=\"SuperOak dependency outdatedness\" /\u003e\u003c/a\u003e\n   \u003ca href=\"https://deno-visualizer.danopia.net/dependencies-of/https/deno.land/x/superoak/mod.ts\"\u003e\u003cimg src=\"https://img.shields.io/endpoint?url=https%3A%2F%2Fdeno-visualizer.danopia.net%2Fshields%2Fcache-size%2Fx%2Fsuperoak%2Fmod.ts\" alt=\"SuperOak cached size\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n## Table of Contents\n\n- [Table of Contents](#table-of-contents)\n- [About](#about)\n- [Installation](#installation)\n- [Example](#example)\n- [Documentation](#documentation)\n- [API](#api)\n- [FAQs](#faqs)\n  - [`Property 'get' does not exist on type 'Promise\u003cSuperDeno\u003e'`\n    error](#property-get-does-not-exist-on-type-promisesuperdeno-error)\n  - [`Request has been terminated` error](#request-has-been-terminated-error)\n- [Contributing](#contributing)\n- [License](#license)\n\n## About\n\nThis module aims to provide a high-level abstraction for testing HTTP in Deno's\nOak web framework. This is a wrapper compatibility layer around\n[SuperDeno](https://github.com/cmorten/superdeno) to reduce some of the\nboilerplate needed to setup Oak integration + functional tests.\n\n## Installation\n\nThis is a [Deno](https://deno.land/) module available to import direct from this\nrepo and via the [Deno Registry](https://deno.land/x).\n\nBefore importing, [download and install Deno](https://deno.land/#installation).\n\nYou can then import SuperOak straight into your project:\n\n```ts\nimport { superoak } from \"https://deno.land/x/superoak/mod.ts\";\n```\n\nSuperOak is also available on [nest.land](https://nest.land/package/superoak), a\npackage registry for Deno on the Blockchain.\n\n\u003e Note: Some examples in this README are using the unversioned form of the import URL. In production you should always use the versioned import form such as `https://deno.land/x/superoak@5.0.0/mod.ts`.\n\n## Example\n\nYou may pass a url string (for an already running Oak server), or an Oak\n`Application` object to `superoak()` - when passing an Oak `Application`,\nSuperOak will automatically handle the creation of a server, binding to a free\nephemeral port and closing of the server on a call to `.end()`.\n\nSuperOak works with any Deno test framework. Here's an example with Deno's\nbuilt-in test framework.\n\n```ts\nimport { Application, Router } from \"jsr:@oak/oak@^17.1.4\";\nimport { superoak } from \"https://deno.land/x/superoak@5.0.0/mod.ts\";\n\nconst router = new Router();\nrouter.get(\"/\", (ctx) =\u003e {\n  ctx.response.body = \"Hello Deno!\";\n});\nrouter.post(\"/user\", (ctx) =\u003e {\n  ctx.response.body = \"Post!\";\n});\n\nconst app = new Application();\napp.use(router.routes());\napp.use(router.allowedMethods());\n\n// Send simple GET request\nDeno.test(\"it should support the Oak framework\", async () =\u003e {\n  const request = await superoak(app);\n  await request.get(\"/\").expect(\"Hello Deno!\");\n});\n\n// Custom requests can be built with the superagent API\n// https://visionmedia.github.io/superagent/#post--put-requests.\nDeno.test(\"it should allow post requests\", async () =\u003e {\n  const request = await superoak(app);\n  await request\n    .post(\"/user\")\n    .set(\"Content-Type\", \"application/json\")\n    .send('{\"name\":\"superoak\"}')\n    .expect(200);\n});\n```\n\nSave the above to a file `demo.test.ts` and test it using\n`deno test --allow-net demo.test.ts`.\n\nFor further examples, see the\n[SuperOak examples](https://github.com/cmorten/superoak/blob/main/examples/README.md),\n[tests](https://github.com/cmorten/superoak/blob/main/test/superoak.test.ts)\nor the\n[SuperDeno examples](https://github.com/cmorten/superdeno#example) for\ninspiration.\n\n## Documentation\n\n- [SuperOak Type Docs](https://cmorten.github.io/superoak/)\n- [SuperOak Deno Docs](https://doc.deno.land/https/deno.land/x/superoak/mod.ts)\n- [SuperOak Examples](https://github.com/cmorten/superoak/blob/main/examples/README.md)\n- [License](https://github.com/cmorten/superoak/blob/main/LICENSE.md)\n- [Changelog](https://github.com/cmorten/superoak/blob/main/.github/CHANGELOG.md)\n\n## API\n\nPlease refer to the\n[SuperDeno API](https://github.com/cmorten/superdeno#api) and\n[SuperAgent API](https://visionmedia.github.io/superagent/).\n\n## FAQs\n\n### `Property 'get' does not exist on type 'Promise\u003cSuperDeno\u003e'` error\n\nUnlike [SuperDeno](https://github.com/cmorten/superdeno), `superoak()`\nreturns a promise which will need to be awaited before you can call any method\nsuch as `.get(\"/\")`.\n\n```ts\n// ✅ works\nDeno.test(\"it will allow you to make assertions if you await it\", async () =\u003e {\n  const request = await superoak(app);\n  await request.get(\"/\").expect(200).expect(\"Hello Deno!\");\n});\n\n// ❌ won't work\nDeno.test(\"it will allow you to make assertions if you await it\", async () =\u003e {\n  const request = superoak(app);\n  await request.get(\"/\").expect(200).expect(\"Hello Deno!\"); // Boom 💥 `Property 'get' does not exist on type 'Promise\u003cSuperDeno\u003e'`\n});\n```\n\n### `Request has been terminated` error\n\nUnlike [SuperDeno](https://github.com/cmorten/superdeno), you cannot\nre-use SuperOak instances. If you try you will encounter an error similar to\nbelow:\n\n```console\nError: Request has been terminated\nPossible causes: the network is offline, Origin is not allowed by Access-Control-Allow-Origin, the page is being unloaded, etc.\n    at Test.Request.crossDomainError\n    at XMLHttpRequestSham.xhr.onreadystatechange\n    ...\n```\n\nThis is because SuperOak instances automatically close the underlying Oak server\nonce the assertion chain has completed.\n\nInstead you should make all of your assertions on a single SuperOak instance, or\ncreate a new SuperOak instance for subsequent assertions like below:\n\n```ts\n// ✅ works\nDeno.test(\n  \"it will allow you to make multiple assertions on one SuperOak instance\",\n  async () =\u003e {\n    const request = await superoak(app);\n    await request.get(\"/\").expect(200).expect(\"Hello Deno!\");\n  }\n);\n\n// ✅ works\nDeno.test(\n  \"it will allow you to re-use the Application for another SuperOak instance\",\n  async () =\u003e {\n    const request1 = await superoak(app);\n    await request1.get(\"/\").expect(200);\n\n    const request2 = await superoak(app);\n    await request2.get(\"/\").expect(\"Hello Deno!\");\n  }\n);\n\n// ❌ won't work\nDeno.test(\n  \"it will throw an error if try to re-use a SuperOak instance\",\n  async () =\u003e {\n    const request = await superoak(app);\n    await request.get(\"/\").expect(200);\n    await request.get(\"/\").expect(\"Hello Deno!\"); // Boom 💥 `Error: Request has been terminated`\n  }\n);\n```\n\n## Contributing\n\n[Contributing guide](https://github.com/cmorten/superoak/blob/main/.github/CONTRIBUTING.md)\n\n---\n\n## License\n\nSuperOak is licensed under the [MIT License](./LICENSE.md).\n\nIcon designed and created by\n[Hannah Morten](https://www.linkedin.com/in/hannah-morten-b1218017a/).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcmorten%2Fsuperoak","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcmorten%2Fsuperoak","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcmorten%2Fsuperoak/lists"}