{"id":13736348,"url":"https://github.com/cmorten/superdeno","last_synced_at":"2025-08-20T04:32:22.999Z","repository":{"id":41403872,"uuid":"267800663","full_name":"cmorten/superdeno","owner":"cmorten","description":"Super-agent driven library for testing Deno HTTP servers.","archived":false,"fork":false,"pushed_at":"2024-01-28T13:17:45.000Z","size":1416,"stargazers_count":122,"open_issues_count":1,"forks_count":5,"subscribers_count":3,"default_branch":"main","last_synced_at":"2024-10-01T08:33:02.588Z","etag":null,"topics":["assertions","deno","deno-doc","http-testing","oak","opine","superagent","superdeno","supertest","testing","typescript"],"latest_commit_sha":null,"homepage":"https://cmorten.github.io/superdeno/","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":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["cmorten"]}},"created_at":"2020-05-29T08:00:22.000Z","updated_at":"2024-05-19T10:07:54.000Z","dependencies_parsed_at":"2024-08-03T03:06:07.081Z","dependency_job_id":"300019b2-f91d-443d-b4ef-8c4479e6b71b","html_url":"https://github.com/cmorten/superdeno","commit_stats":{"total_commits":135,"total_committers":8,"mean_commits":16.875,"dds":0.6518518518518519,"last_synced_commit":"1182476a625d4b43af286e8bef3df6b6aa7bfb7c"},"previous_names":["asos-craigmorten/superdeno"],"tags_count":43,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmorten%2Fsuperdeno","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmorten%2Fsuperdeno/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmorten%2Fsuperdeno/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cmorten%2Fsuperdeno/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cmorten","download_url":"https://codeload.github.com/cmorten/superdeno/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230394228,"owners_count":18218707,"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-testing","oak","opine","superagent","superdeno","supertest","testing","typescript"],"created_at":"2024-08-03T03:01:20.232Z","updated_at":"2025-08-20T04:32:22.993Z","avatar_url":"https://github.com/cmorten.png","language":"TypeScript","funding_links":["https://github.com/sponsors/cmorten"],"categories":["基础设施","Modules"],"sub_categories":["Deno 源","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/superdeno/raw/main/.github/superdeno.png\" alt=\"Super Deno standing in the rain at night – stoically facing the dark battle that is software engineering\"\u003e\u003c/a\u003e\n  \u003ch1 align=\"center\"\u003eSuperDeno\u003c/h1\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\nHTTP assertions for Deno made easy via \u003ca href=\"https://github.com/visionmedia/superagent\"\u003esuperagent\u003c/a\u003e.\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n   \u003ca href=\"https://github.com/cmorten/superdeno/tags/\"\u003e\u003cimg src=\"https://img.shields.io/github/tag/cmorten/superdeno\" alt=\"Current version\" /\u003e\u003c/a\u003e\n   \u003cimg src=\"https://github.com/cmorten/superdeno/workflows/Test/badge.svg\" alt=\"Current test status\" /\u003e\n   \u003ca href=\"https://doc.deno.land/https/deno.land/x/superdeno/mod.ts\"\u003e\u003cimg src=\"https://doc.deno.land/badge.svg\" alt=\"SuperDeno 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/superdeno/issues/\"\u003e\u003cimg src=\"https://img.shields.io/github/issues/cmorten/superdeno\" alt=\"SuperDeno issues\" /\u003e\u003c/a\u003e\n   \u003cimg src=\"https://img.shields.io/github/stars/cmorten/superdeno\" alt=\"SuperDeno stars\" /\u003e\n   \u003cimg src=\"https://img.shields.io/github/forks/cmorten/superdeno\" alt=\"SuperDeno forks\" /\u003e\n   \u003cimg src=\"https://img.shields.io/github/license/cmorten/superdeno\" alt=\"SuperDeno license\" /\u003e\n   \u003ca href=\"https://GitHub.com/cmorten/superdeno/graphs/commit-activity\"\u003e\u003cimg src=\"https://img.shields.io/badge/Maintained%3F-no-green.svg\" alt=\"SuperDeno is unmaintained\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n   \u003ca href=\"https://deno.land/x/superdeno\"\u003e\u003cimg src=\"https://img.shields.io/endpoint?url=https%3A%2F%2Fdeno-visualizer.danopia.net%2Fshields%2Flatest-version%2Fx%2Fsuperdeno%2Fmod.ts\" alt=\"SuperDeno 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/superdeno/mod.ts\"\u003e\u003cimg src=\"https://img.shields.io/endpoint?url=https%3A%2F%2Fdeno-visualizer.danopia.net%2Fshields%2Fdep-count%2Fx%2Fsuperdeno%2Fmod.ts\" alt=\"SuperDeno dependency count\" /\u003e\u003c/a\u003e\n   \u003ca href=\"https://deno-visualizer.danopia.net/dependencies-of/https/deno.land/x/superdeno/mod.ts\"\u003e\u003cimg src=\"https://img.shields.io/endpoint?url=https%3A%2F%2Fdeno-visualizer.danopia.net%2Fshields%2Fupdates%2Fx%2Fsuperdeno%2Fmod.ts\" alt=\"SuperDeno dependency outdatedness\" /\u003e\u003c/a\u003e\n   \u003ca href=\"https://deno-visualizer.danopia.net/dependencies-of/https/deno.land/x/superdeno/mod.ts\"\u003e\u003cimg src=\"https://img.shields.io/endpoint?url=https%3A%2F%2Fdeno-visualizer.danopia.net%2Fshields%2Fcache-size%2Fx%2Fsuperdeno%2Fmod.ts\" alt=\"SuperDeno cached size\" /\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n_**Now in maintenance mode:** [Deno has introduced Node and NPM compatability](https://docs.deno.com/runtime/fundamentals/node/), consider using [SuperTest](https://www.npmjs.com/package/supertest) itself in\nDeno!_\n\n```ts\nimport supertest from \"npm:supertest\";\n```\n\nSuperTest not working for you? [Raise an issue on Deno](https://github.com/denoland/deno/issues) and keep reading for SuperDeno usage :tada:\n\n---\n\n## Table of Contents\n\n- [Getting Started](#getting-started)\n- [About](#about)\n- [Installation](#installation)\n- [Examples](#examples)\n- [Documentation](#documentation)\n- [API](#api)\n- [Notes](#notes)\n- [Contributing](#contributing)\n- [License](#license)\n\n## Getting Started\n\n```ts\nimport { superdeno } from \"https://deno.land/x/superdeno/mod.ts\";\n\nconst USER_ROUTE = new URLPattern({ pathname: \"/user\" });\n\nfunction handler(req: Request): Response {\n  const match = USER_ROUTE.exec(req.url);\n\n  if (match) {\n    const body = JSON.stringify({ name: \"Deno\" });\n\n    return new Response(body, {\n      status: 200,\n      headers: {\n        \"content-type\": \"application/json; charset=utf-8\",\n      },\n    });\n  }\n\n  return new Response(\"Not found\", {\n    status: 404,\n  });\n}\n\nconst server = Deno.serve(handler);\n\nsuperdeno(server)\n  .get(\"/user\")\n  .expect(\"Content-Type\", /json/)\n  .expect(\"Content-Length\", \"15\")\n  .expect(200)\n  .end((err, res) =\u003e {\n    if (err) throw err;\n  });\n```\n\nLooking to test an Oak web server? Check out\n[SuperOak](https://github.com/cmorten/superoak)!\n\n## About\n\nThe motivation of this module is to provide a high-level abstraction for testing\nHTTP in Deno, while still allowing you to drop down to the lower-level API\nprovided by [superagent](https://visionmedia.github.io/superagent/).\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 SuperDeno straight into your project:\n\n```ts\nimport { superdeno } from \"https://deno.land/x/superdeno/mod.ts\";\n```\n\nSuperDeno is also available on [nest.land](https://nest.land/package/superdeno),\na package registry for Deno on the Blockchain.\n\n\u003e Note: All 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/superdeno@5.0.1/mod.ts`.\n\n## Examples\n\nYou may pass a url string,\n[`http.Server`](https://doc.deno.land/https/deno.land/std/http/mod.ts#Server), a\nrequest handling function, or an object that implements an `app.listen()` method\n(which mirrors the\n[`http.serve`](https://doc.deno.land/https/deno.land/std/http/mod.ts#serve)\ninterface) to `superdeno()` - if SuperDeno identifies that a server is not\nalready listening for connections, then one is bound to an ephemeral port for\nyou so there is no need to keep track of ports.\n\nSuperDeno works with any Deno test framework. Here's an example with Deno's\nbuilt-in test framework, note how you can pass `done` straight to any of the\n`.expect()` calls:\n\n```ts\nDeno.test(\"GET /user responds with json\", async () =\u003e {\n  await superdeno(app)\n    .get(\"/user\")\n    .set(\"Accept\", \"application/json\")\n    .expect(\"Content-Type\", /json/)\n    .expect(200);\n});\n```\n\nHere's an example of SuperDeno working with the Express web framework:\n\n```ts\nimport { superdeno } from \"https://deno.land/x/superdeno/mod.ts\";\n// @deno-types=\"npm:@types/express@^4.17.22\"\nexport { default as express } from \"npm:express@4.21.2\";\nexport { expect } from \"https://deno.land/x/expect@v0.4.2/mod.ts\";\n\nDeno.test(\"it should support regular expressions\", async () =\u003e {\n  const app = express();\n\n  app.get(\"/\", (_req, res) =\u003e {\n    res.send(\"Hello Deno!\");\n  });\n\n  await superdeno(app)\n    .get(\"/\")\n    .expect(\"Content-Type\", /^application/)\n    .catch((err) =\u003e {\n      expect(err.message).toEqual(\n        'expected \"Content-Type\" matching /^application/, got \"text/html; charset=utf-8\"'\n      );\n    });\n});\n```\n\nSee more examples in the [Express test suite](./test/superdeno.express.test.ts).\n\nHere's an example of SuperDeno working with the Oak web framework:\n\n```ts\nimport { superdeno } from \"https://deno.land/x/superdeno/mod.ts\";\nimport { Application, Router } from \"jsr:@oak/oak@^17.1.4\";\n\nconst router = new Router();\nrouter.get(\"/\", (ctx) =\u003e {\n  ctx.response.body = \"Hello Deno!\";\n});\n\nconst app = new Application();\napp.use(router.routes());\napp.use(router.allowedMethods());\n\nDeno.test(\"it should support the Oak framework\", async () =\u003e {\n  const controller = new AbortController();\n  const { signal } = controller;\n\n  app.addEventListener(\"listen\", async ({ hostname, port, secure }) =\u003e {\n    const protocol = secure ? \"https\" : \"http\";\n    const url = `${protocol}://${hostname}:${port}`;\n\n    await superdeno(url)\n      .get(\"/\")\n      .expect(\"Hello Deno!\", () =\u003e {\n        controller.abort();\n      });\n  });\n\n  await app.listen({ port: 0, signal });\n});\n```\n\nSee more examples in the [Oak test suite](./test/superdeno.oak.test.ts).\n\nIf you are using the [Oak](https://github.com/oakserver/oak/) web framework then\nit is recommended that you use the specialized\n[SuperOak](https://github.com/cmorten/superoak) assertions library for\nreduced bootstrapping.\n\nIf you don't need to test the server setup side of your Oak application, or you\nare making use of the `app.handle()` method (for example for serverless apps)\nthen you can write slightly less verbose tests for Oak:\n\n```ts\nimport { superdeno } from \"https://deno.land/x/superdeno/mod.ts\";\nimport { Application, Router } from \"jsr:@oak/oak@^17.1.4\";\n\nconst router = new Router();\n\nrouter.get(\"/\", (ctx) =\u003e {\n  ctx.response.body = \"Hello Deno!\";\n});\n\nconst app = new Application();\napp.use(router.routes());\napp.use(router.allowedMethods());\n\nDeno.test(\n  \"it should support the Oak framework `app.handle` method\",\n  async () =\u003e {\n    /**\n     * Note that we have to bind `app` to the function otherwise `app.handle`\n     * doesn't preserve the `this` context from `app`.\n     */\n    await superdeno(app.handle.bind(app)).get(\"/\").expect(\"Hello Deno!\");\n  }\n);\n```\n\nIn this case, SuperDeno handles the setup and closing of the server for you, so\nyou can focus on just testing your middleware.\n\nFor further examples, see the [tests](./test) or the\n[supertest examples](https://github.com/visionmedia/supertest#example) for\ninspiration.\n\n## Documentation\n\n- [SuperDeno Deno Docs](https://doc.deno.land/https/deno.land/x/superdeno/mod.ts)\n- [SuperDeno Type Docs](https://cmorten.github.io/superdeno/)\n- [License](https://github.com/cmorten/superdeno/blob/main/LICENSE.md)\n- [Changelog](https://github.com/cmorten/superdeno/blob/main/.github/CHANGELOG.md)\n\n## API\n\nYou may use any [superagent](http://github.com/visionmedia/superagent) client\n(browser) methods and perform assertions in the `.end()` callback for\nlower-level needs.\n\n### .expect(status[, fn])\n\nAssert response `status` code.\n\n### .expect(status, body[, fn])\n\nAssert response `status` code and `body`.\n\n### .expect(body[, fn])\n\nAssert response `body` text with a string, regular expression, or parsed body\nobject.\n\n### .expect(field, value[, fn])\n\nAssert header `field` `value` with a string or regular expression.\n\n### .expect(function(res) {})\n\nPass a custom assertion function. It'll be given the response object to check.\nIf the check fails, throw an error.\n\n```ts\nfunction hasPreviousAndNextKeys(res) {\n  if (!(\"next\" in res.parsedBody)) throw new Error(\"missing next key\");\n  if (!(\"prev\" in res.parsedBody)) throw new Error(\"missing prev key\");\n}\n\nawait superdeno(app).get(\"/\").expect(hasPreviousAndNextKeys);\n```\n\n### .end(fn)\n\nPerform the request and invoke `fn(err, res)`.\n\n## Notes\n\nThis is a port of [supertest](https://github.com/visionmedia/supertest) to\nTypeScript + Deno, which fulfills this motivation currently for Node. This\nmodule also includes a XHR sham so\n[superagent](https://visionmedia.github.io/superagent/) client mode can be used\ndirectly.\n\n## Contributing\n\n[Contributing guide](https://github.com/cmorten/superdeno/blob/main/.github/CONTRIBUTING.md)\n\n---\n\n## License\n\nThis library is a port of [supertest](https://github.com/visionmedia/supertest)\nwhose license and copyrights are available at\n[SUPERTEST_LICENSE](./SUPERTEST_LICENSE.md) in the root of this repository, and\ncovers all files within the [source](./src) directory which detail that the file\nis a port.\n\nSuperDeno 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%2Fsuperdeno","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcmorten%2Fsuperdeno","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcmorten%2Fsuperdeno/lists"}