{
  "type": "module",
  "source": "doc/api/best-practices-writing-tests.md",
  "modules": [
    {
      "textRaw": "Writing tests",
      "name": "writing_tests",
      "type": "module",
      "desc": "<p>Undici is tuned for a production use case and its default will keep\na socket open for a few seconds after an HTTP request is completed to\nremove the overhead of opening up a new socket. These settings that makes\nUndici shine in production are not a good fit for using Undici in automated\ntests, as it will result in longer execution times.</p>\n<p>The following are good defaults that will keep the socket open for only 10ms:</p>\n<pre><code class=\"language-js\">import { request, setGlobalDispatcher, Agent } from 'undici'\n\nconst agent = new Agent({\n  keepAliveTimeout: 10, // milliseconds\n  keepAliveMaxTimeout: 10 // milliseconds\n})\n\nsetGlobalDispatcher(agent)\n</code></pre>",
      "modules": [
        {
          "textRaw": "Guarding against unexpected disconnects",
          "name": "guarding_against_unexpected_disconnects",
          "type": "module",
          "desc": "<p>Undici's <code>Client</code> automatically reconnects after a socket error. This means\na test can silently disconnect, reconnect, and still pass. Unfortunately,\nthis could mask bugs like unexpected parser errors or protocol violations.\nTo catch these silent reconnections, add a disconnect guard after creating\na <code>Client</code>:</p>\n<pre><code class=\"language-js\">const { Client } = require('undici')\nconst { test, after } = require('node:test')\nconst { tspl } = require('@matteo.collina/tspl')\n\ntest('example with disconnect guard', async (t) => {\n  t = tspl(t, { plan: 1 })\n\n  const client = new Client('http://localhost:3000')\n  after(() => client.close())\n\n  client.on('disconnect', () => {\n    if (!client.closed &#x26;&#x26; !client.destroyed) {\n      t.fail('unexpected disconnect')\n    }\n  })\n\n  // ... test logic ...\n})\n</code></pre>\n<p><code>client.close()</code> and <code>client.destroy()</code> both emit <code>'disconnect'</code> events, but\nthose are expected. The guard only fails when a disconnect happens during the\nactive test (i.e., <code>!client.closed &#x26;&#x26; !client.destroyed</code> is true).</p>\n<p>Skip the guard for tests where a disconnect is expected behavior, such as:</p>\n<ul>\n<li>Signal aborts (<code>signal.emit('abort')</code>, <code>ac.abort()</code>)</li>\n<li>Server-side destruction (<code>res.destroy()</code>, <code>req.socket.destroy()</code>)</li>\n<li>Client-side body destruction mid-stream (<code>data.body.destroy()</code>)</li>\n<li>Timeout errors (<code>HeadersTimeoutError</code>, <code>BodyTimeoutError</code>)</li>\n<li>Successful upgrades (the socket is detached from the <code>Client</code>)</li>\n<li>Retry/reconnect tests where the disconnect triggers the retry</li>\n<li>HTTP parser errors from malformed responses (<code>HTTPParserError</code>)</li>\n</ul>",
          "displayName": "Guarding against unexpected disconnects"
        }
      ],
      "displayName": "Writing tests"
    }
  ]
}