{"id":15415851,"url":"https://github.com/davidje13/superwstest","last_synced_at":"2025-10-27T22:36:36.057Z","repository":{"id":45621706,"uuid":"177445912","full_name":"davidje13/superwstest","owner":"davidje13","description":"supertest with added WebSocket capabilities","archived":false,"fork":false,"pushed_at":"2025-07-10T14:04:31.000Z","size":383,"stargazers_count":29,"open_issues_count":2,"forks_count":7,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-10T17:48:29.330Z","etag":null,"topics":["superagent","supertest","test","testing","websocket"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/davidje13.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-03-24T17:21:14.000Z","updated_at":"2025-07-10T14:04:31.000Z","dependencies_parsed_at":"2024-10-21T15:38:56.231Z","dependency_job_id":null,"html_url":"https://github.com/davidje13/superwstest","commit_stats":{"total_commits":109,"total_committers":6,"mean_commits":"18.166666666666668","dds":0.1009174311926605,"last_synced_commit":"afaceabdfd8000dfad1ed1f0ae90785dcc39011e"},"previous_names":[],"tags_count":33,"template":false,"template_full_name":null,"purl":"pkg:github/davidje13/superwstest","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2Fsuperwstest","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2Fsuperwstest/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2Fsuperwstest/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2Fsuperwstest/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davidje13","download_url":"https://codeload.github.com/davidje13/superwstest/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidje13%2Fsuperwstest/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264885733,"owners_count":23678380,"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":["superagent","supertest","test","testing","websocket"],"created_at":"2024-10-01T17:10:01.962Z","updated_at":"2025-10-27T22:36:36.036Z","avatar_url":"https://github.com/davidje13.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SuperWSTest\n\nProvides a [supertest](https://github.com/visionmedia/supertest)-compatible API\nfor testing WebSockets.\n\nIf supertest is installed, this package also exposes supertest's API for\nconvenience when testing servers which provide both HTTP and WebSocket URLs.\n\n## Install dependency\n\n```bash\nnpm install --save-dev superwstest\n```\n\nYou can also optionally install supertest for access to `.get`, `.post`, etc.:\n\n```bash\nnpm install --save-dev superwstest supertest\n```\n\n## Usage\n\n### Example server implementation\n\n```javascript\nimport http from 'http';\nimport WebSocket from 'ws';\n\nconst server = http.createServer();\nconst wss = new WebSocket.Server({ server });\n\nwss.on('connection', (ws) =\u003e {\n  ws.on('message', (message) =\u003e { ws.send(`echo ${message}`); });\n  ws.send('hello');\n});\n\nexport default server;\n```\n\n### Tests for example server\n\n```javascript\nimport request from 'superwstest';\nimport server from './myServer';\n\ndescribe('My Server', () =\u003e {\n  beforeEach((done) =\u003e {\n    server.listen(0, 'localhost', done);\n  });\n\n  afterEach((done) =\u003e {\n    server.close(done);\n  });\n\n  it('communicates via websockets', async () =\u003e {\n    await request(server)\n      .ws('/path/ws')\n      .expectText('hello')\n      .sendText('foo')\n      .expectText('echo foo')\n      .sendText('abc')\n      .expectText('echo abc')\n      .close()\n      .expectClosed();\n  });\n});\n```\n\nAs long as you add `server.close` in an `afterEach`, all connections\nwill be closed automatically, so you do not need to close connections\nin every test.\n\n### Testing non-WebSocket endpoints\n\nIf you have installed supertest, all the HTTP checks are also available\nby proxy:\n\n```javascript\nimport request from 'superwstest';\nimport server from './myServer';\n\ndescribe('My Server', () =\u003e {\n  beforeEach((done) =\u003e server.listen(0, 'localhost', done));\n  afterEach((done) =\u003e server.close(done));\n\n  it('communicates via HTTP', async () =\u003e {\n    await request(server)\n      .get('/path')\n      .expect(200);\n  });\n});\n```\n\n### Testing a remote webserver\n\nYou can also test against a remote webserver by specifying the URL\nof the server:\n\n```javascript\nimport request from 'superwstest';\n\ndescribe('My Remote Server', () =\u003e {\n  afterEach(() =\u003e {\n    request.closeAll(); // recommended when using remote servers\n  });\n\n  it('communicates via websockets', async () =\u003e {\n    await request('https://example.com')\n      .ws('/path/ws')\n      .expectText('hello')\n      .close();\n  });\n});\n```\n\nThe server URL given should be http(s) rather than ws(s); this will\nprovide compatibility with native supertest requests such as `post`,\n`get`, etc. and will be converted automatically as needed.\n\nNote that adding `request.closeAll()` to an `afterEach` will\nensure connections are closed in all situations (including test\ntimeouts, etc.). This is not needed when testing against a local\nserver because the server will close connections when closed.\n\nIf you need to scope the `request` instance (to avoid `closeAll`\ninterfering with other tests running in parallel in the same\nprocess), you can use `.scoped()` (note that this is not\ntypically required when using Jest since parallel execution is\nperformed using separate processes):\n\n```javascript\nimport baseRequest from 'superwstest';\n\ndescribe('thing', () =\u003e {\n  const request = baseRequest.scoped();\n  afterEach(() =\u003e request.closeAll());\n  /* ... */\n});\n```\n\n## API\n\n- [request(server[, options])](#requestserver-options)\n- [request(...).ws(path[, protocols][, options])](#requestserverwspath-protocols-options)\n  - [.set(header, value)](#setheader-value)\n  - [.unset(header)](#unsetheader)\n  - [.filterMessages(test)](#filtermessagestest)\n  - [.filterText([test])](#filtertexttest)\n  - [.filterJson([test])](#filterjsontest)\n  - [.filterBinary([test])](#filterbinarytest)\n  - [.expectText([expected[, options]])](#expecttextexpected-options)\n  - [.expectJson([expected[, options]])](#expectjsonexpected-options)\n  - [.expectBinary([expected[, options]])](#expectbinaryexpected-options)\n  - [.waitForText([expected[, options]])](#waitfortextexpected-options)\n  - [.waitForJson([expected[, options]])](#waitforjsonexpected-options)\n  - [.waitForBinary([expected[, options]])](#waitforbinaryexpected-options)\n  - [.sendText(text)](#sendtexttext)\n  - [.sendJson(json)](#sendjsonjson)\n  - [.sendBinary(data)](#sendbinarydata)\n  - [.send(data[, options])](#senddata-options)\n  - [.close([code[, reason]]](#closecode-reason)\n  - [.expectClosed([expectedCode[, expectedReason]])](#expectclosedexpectedcode-expectedreason)\n  - [.expectConnectionError([expectedStatusCode])](#expectconnectionerrorexpectedstatuscode)\n  - [.expectUpgrade(test)](#expectupgradetest)\n  - [.wait(milliseconds)](#waitmilliseconds)\n  - [.exec(fn)](#execfn)\n\n### `request(server[, options])`\n\nThe beginning of a superwstest\n(or [supertest](https://www.npmjs.com/package/supertest)) test chain.\nTypically this is immediately followed by `.ws(...)` or `.get(...)` etc.\n\n`options` can contain additional configuration:\n\n- `shutdownDelay`: wait up to the given number of milliseconds for\n  connections to close by themselves before forcing a shutdown when\n  `close` is called on the server. By default this is 0 (i.e. all\n  connections are closed immediately). Has no effect when testing\n  remote servers.\n\n  ```javascript\n  request(server, { shutdownDelay: 500 }).ws(path)\n  ```\n\n- `defaultExpectOptions`: a set of options which are passed to all\n  `expect*` calls in the current chain (e.g. allows setting a timeout\n  for all expectations in the chain):\n\n  ```javascript\n  request(server, { defaultExpectOptions: { timeout: 5000 } })\n    .ws(path)\n    .expectText('hello') // implicit { timeout: 5000 }\n    .expectText('hi', { timeout: 9000 }) // overrides default\n  ```\n\n- `defaultWaitForOptions`: a set of options which are passed to all\n  `waitFor*` calls in the current chain (e.g. allows setting a timeout\n  for all waits in the chain)\n\n### `request(server).ws(path[, protocols][, options])`\n\nReturns a `Promise` (eventually returning the `WebSocket`) with\nadditional fluent API methods attached (described below).\n\nInternally, this uses [ws](https://www.npmjs.com/package/ws), and the\nprotocols and options given are passed directly to the\n[`WebSocket` constructor](https://github.com/websockets/ws/blob/HEAD/doc/ws.md#new-websocketaddress-protocols-options).\nFor example, one way to set a cookie:\n\n```javascript\nrequest(myServer)\n  .ws('/path/ws', { headers: { cookie: 'foo=bar' } })\n```\n\n(you can also use `.set('Cookie', 'foo=bar')` to set cookies)\n\n### `.set(header, value)`\n\nSets the header-value pair on the initial WebSocket connection. This can\nalso be called with an object to set multiple headers at once.\n\n```javascript\nrequest(server).ws('...')\n  .set('Cookie', 'foo=bar')\n  .set({ 'Authorization': 'bearer foo', 'X-Foo': 'bar' })\n```\n\nThis function cannot be called after the connection has been established\n(i.e. after calling `send` or `expect*`).\n\n### `.unset(header)`\n\nRemoves the header from the initial WebSocket connection.\n\n```javascript\nrequest(server).ws('...')\n  .unset('Cookie')\n```\n\nThis function cannot be called after the connection has been established\n(i.e. after calling `send` or `expect*`).\n\n### `.filterMessages(test)`\n\nFilters out any incoming messages which do not match the `test` function.\nThis can be used to ignore background messages which are not relevant to\nthe code being tested.\n\n```javascript\nrequest(server).ws('...')\n  .filterMessages(({ data, isBinary }) =\u003e {\n    if (isBinary) {\n      return true; // allow all binary messages\n    } else {\n      return String(data) !== 'ping'; // allow all text messages except \"ping\"\n    }\n  })\n```\n\nThe `data` passed to the `test` function will always be a NodeJS `Buffer`.\nIf multiple filters are specified, they are AND-ed together.\n\nThis function cannot be called after the connection has been established\n(i.e. after calling `send` or `expect*`).\n\n### `.filterText([test])`\n\nFilters out any incoming messages which do not match the `test` function.\nThis can be used to ignore background messages which are not relevant to\nthe code being tested. Implicitly excludes all binary messages.\n\n```javascript\nrequest(server).ws('...')\n  .filterText((message) =\u003e message !== 'ping')\n```\n\nIf multiple filters are specified, they are AND-ed together.\n\nThis function cannot be called after the connection has been established\n(i.e. after calling `send` or `expect*`).\n\n### `.filterJson([test])`\n\nFilters out any incoming messages which do not match the `test` function.\nThis can be used to ignore background messages which are not relevant to\nthe code being tested. Implicitly excludes all binary messages and text\nmessages which cannot be parsed as JSON.\n\n```javascript\nrequest(server).ws('...')\n  .filterJson((message) =\u003e message.type !== 'system')\n```\n\nIf multiple filters are specified, they are AND-ed together.\n\nThis function cannot be called after the connection has been established\n(i.e. after calling `send` or `expect*`).\n\n### `.filterBinary([test])`\n\nFilters out any incoming messages which do not match the `test` function.\nThis can be used to ignore background messages which are not relevant to\nthe code being tested. Implicitly excludes all text messages.\n\n```javascript\nrequest(server).ws('...')\n  .filterBinary((message) =\u003e message[0] === 1)\n```\n\nThe `message` parameter will always be a `Uint8Array`.\nIf multiple filters are specified, they are AND-ed together.\n\nThis function cannot be called after the connection has been established\n(i.e. after calling `send` or `expect*`).\n\n### `.expectText([expected[, options]])`\n\nWaits for the next message to arrive then checks that it matches the given\ntext (exact match), regular expression, or function. If no parameter is\ngiven, this only checks that the message is text (not binary).\n\n```javascript\nrequest(server).ws('...')\n  .expectText('hello')   // exact text\n  .expectText(/^hel*o$/) // RegExp matching\n  .expectText((actual) =\u003e actual.includes('lo')) // function\n  .expectText()          // just check message is text\n```\n\nWhen using a function, the check will be considered a failure if it\nreturns `false`. Any other value (including `undefined` and `null`)\nis considered a pass. This means you can use (e.g.) Jest expectations\n(returning no value):\n\n```javascript\nrequest(server).ws('...')\n  .expectText((actual) =\u003e {\n    expect(actual).toContain('foo');\n  })\n```\n\nA second parameter can be given with additional options:\n\n- `timeout`: wait up to the given number of milliseconds for a message\n  to arrive before failing the test (defaults to infinity).\n\n  ```javascript\n  request(server).ws('...')\n    .expectText('hello', { timeout: 1000 })\n    .expectText(undefined, { timeout: 1000 })\n  ```\n\n  Note that for the most reliable tests, it is recommended to stick with\n  the default (infinite) timeout. This option is provided as an escape\n  hatch when writing long flow tests where the test timeout is\n  unreasonably large for detecting an early failure.\n\nThese options can also be configured for the whole chain in the\n[request call](#requestserver-options).\n\n### `.expectJson([expected[, options]])`\n\nWaits for the next message to arrive, deserialises it using `JSON.parse`,\nthen checks that it matches the given data\n([deep equality](https://nodejs.org/api/util.html#utilisdeepstrictequalval1-val2))\nor function.\nIf no parameter is given, this only checks that the message is valid JSON.\n\n```javascript\nrequest(server).ws('...')\n  .expectJson({ foo: 'bar', zig: ['zag'] })       // exact match\n  .expectJson((actual) =\u003e (actual.foo === 'bar')) // function\n  .expectJson() // just check message is valid JSON\n```\n\nWhen using a function, the check will be considered a failure if it\nreturns `false`. Any other value (including `undefined` and `null`)\nis considered a pass. This means you can use (e.g.) Jest expectations\n(returning no value):\n\n```javascript\nrequest(server).ws('...')\n  .expectJson((actual) =\u003e {\n    expect(actual.bar).toBeGreaterThan(2);\n  })\n```\n\nA second parameter can be given with additional options:\n\n- `timeout`: wait up to the given number of milliseconds for a message\n  to arrive before failing the test (defaults to infinity).\n\n  ```javascript\n  request(server).ws('...')\n    .expectJson({ foo: 'bar' }, { timeout: 1000 })\n    .expectJson(undefined, { timeout: 1000 })\n  ```\n\n  Note that for the most reliable tests, it is recommended to stick with\n  the default (infinite) timeout. This option is provided as an escape\n  hatch when writing long flow tests where the test timeout is\n  unreasonably large for detecting an early failure.\n\nThese options can also be configured for the whole chain in the\n[request call](#requestserver-options).\n\n### `.expectBinary([expected[, options]])`\n\nWaits for the next message to arrive then checks that it matches the given\narray / buffer (exact match) or function. If no parameter is given,\nthis only checks that the message is binary (not text).\n\nWhen providing a function, the data will always be a `Uint8Array`.\n\n```javascript\nrequest(server).ws('...')\n  .expectBinary([10, 20, 30])\n  .expectBinary(new Uint8Array([10, 20, 30]))\n  .expectBinary((actual) =\u003e (actual[0] === 10)) // function\n  .expectBinary() // just check message is binary\n```\n\nWhen using a function, the check will be considered a failure if it\nreturns `false`. Any other value (including `undefined` and `null`)\nis considered a pass. This means you can use (e.g.) Jest expectations\n(returning no value):\n\n```javascript\nrequest(server).ws('...')\n  .expectBinary((actual) =\u003e {\n    expect(actual[0]).toBeGreaterThan(2);\n  })\n```\n\nA second parameter can be given with additional options:\n\n- `timeout`: wait up to the given number of milliseconds for a message\n  to arrive before failing the test (defaults to infinity).\n\n  ```javascript\n  request(server).ws('...')\n    .expectBinary([10, 20, 30], { timeout: 1000 })\n    .expectBinary(undefined, { timeout: 1000 })\n  ```\n\n  Note that for the most reliable tests, it is recommended to stick with\n  the default (infinite) timeout. This option is provided as an escape\n  hatch when writing long flow tests where the test timeout is\n  unreasonably large for detecting an early failure.\n\nThese options can also be configured for the whole chain in the\n[request call](#requestserver-options).\n\n### `.waitForText([expected[, options]])`\n\nWaits for the next message which matches the given text (exact match),\nregular expression, or function; discarding all non-matching messages.\nIf no parameter is given, this only waits for a text message (not\nbinary).\n\n```javascript\nrequest(server).ws('...')\n  .waitForText('100%')   // exact text\n  .waitForText(/^done$/) // RegExp matching\n  .waitForText((actual) =\u003e actual.includes('complete')) // function\n  .waitForText()          // just wait for text\n```\n\nFor details on using a function matcher, see\n[`expectText`](#expecttextexpected-options).\n\nThis method is intended for situations where you need to skip past\n\"progress\" messages (e.g. a file upload reporting the upload\npercentage). If you just need to check a single message, use\n[`expectText`](#expecttextexpected-options) instead. If you need to\nignore irrelevant messages, use [`filterText`](#filtertexttest)\ninstead.\n\nA second parameter can be given with additional options:\n\n- `timeout`: wait up to the given number of milliseconds before failing\n  the test (defaults to infinity).\n\n  ```javascript\n  request(server).ws('...')\n    .waitForText('hello', { timeout: 1000 })\n    .waitForText(undefined, { timeout: 1000 })\n  ```\n\nThese options can also be configured for the whole chain in the\n[request call](#requestserver-options).\n\n### `.waitForJson([expected[, options]])`\n\nWaits for the next message which can be deserialised using `JSON.parse`\nand matches the given data\n([deep equality](https://nodejs.org/api/util.html#utilisdeepstrictequalval1-val2))\nor function; discarding all non-matching messages. If no parameter is\ngiven, this only waits for a message which is valid JSON.\n\n```javascript\nrequest(server).ws('...')\n  .waitForJson({ done: true }) // exact text\n  .waitForJson((actual) =\u003e actual.done) // function\n  .waitForJson() // just wait for valid JSON\n```\n\nFor details on using a function matcher, see\n[`expectJson`](#expectjsonexpected-options).\n\nThis method is intended for situations where you need to skip past\n\"progress\" messages (e.g. a file upload reporting the upload\npercentage). If you just need to check a single message, use\n[`expectJson`](#expectjsonexpected-options) instead. If you need to\nignore irrelevant messages, use [`filterJson`](#filterjsontest)\ninstead.\n\nA second parameter can be given with additional options:\n\n- `timeout`: wait up to the given number of milliseconds before failing\n  the test (defaults to infinity).\n\n  ```javascript\n  request(server).ws('...')\n    .waitForJson({ done: true }, { timeout: 1000 })\n    .waitForJson(undefined, { timeout: 1000 })\n  ```\n\nThese options can also be configured for the whole chain in the\n[request call](#requestserver-options).\n\n### `.waitForBinary([expected[, options]])`\n\nWaits for the next message which matches the given array / buffer\n(exact match) or function; discarding all non-matching messages.\nIf no parameter is given, this only waits for a binary message (not\ntext).\n\nWhen providing a function, the data will always be a `Uint8Array`.\n\n```javascript\nrequest(server).ws('...')\n  .waitForBinary([100])\n  .waitForBinary(new Uint8Array([100]))\n  .waitForBinary((actual) =\u003e (actual[0] === 100)) // function\n  .waitForBinary() // just wait for binary\n```\n\nFor details on using a function matcher, see\n[`expectBinary`](#expectbinaryexpected-options).\n\nThis method is intended for situations where you need to skip past\n\"progress\" messages (e.g. a file upload reporting the upload\npercentage). If you just need to check a single message, use\n[`expectBinary`](#expectbinaryexpected-options) instead. If you need\nto ignore irrelevant messages, use\n[`filterBinary`](#filterbinarytest) instead.\n\nA second parameter can be given with additional options:\n\n- `timeout`: wait up to the given number of milliseconds before failing\n  the test (defaults to infinity).\n\n  ```javascript\n  request(server).ws('...')\n    .waitForBinary([100], { timeout: 1000 })\n    .waitForBinary(undefined, { timeout: 1000 })\n  ```\n\nThese options can also be configured for the whole chain in the\n[request call](#requestserver-options).\n\n### `.sendText(text)`\n\nSends the given text. Non-strings are converted using `String` before\nsending.\n\n```javascript\nrequest(server).ws('...')\n  .sendText('yo')\n```\n\n### `.sendJson(json)`\n\nSends the given JSON as text using `JSON.stringify`.\n\n```javascript\nrequest(server).ws('...')\n  .sendJson({ foo: 'bar' })\n```\n\n### `.sendBinary(data)`\n\nSends the given data as a binary message.\n\n```javascript\nrequest(server).ws('...')\n  .sendBinary([10, 20, 30])\n  .sendBinary(new Uint8Array([10, 20, 30]))\n```\n\n### `.send(data[, options])`\n\nSends a raw message (accepts any types accepted by\n[`WebSocket.send`](https://github.com/websockets/ws/blob/HEAD/doc/ws.md#websocketsenddata-options-callback),\nand `options` is passed through unchanged).\n\n```javascript\nrequest(server).ws('...')\n  .send(new Uint8Array([5, 20, 100])) // binary message\n\n  // multipart message\n  .send('this is a fragm', { fin: false })\n  .send('ented message', { fin: true })\n```\n\n### `.close([code[, reason]])`\n\nCloses the socket. Arguments are passed directly to\n[`WebSocket.close`](https://github.com/websockets/ws/blob/HEAD/doc/ws.md#websocketclosecode-reason).\n\n```javascript\nrequest(server).ws('...')\n  .close() // close with default code and reason\n\nrequest(server).ws('...')\n  .close(1001) // custom code\n\nrequest(server).ws('...')\n  .close(1001, 'getting a cup of tea') // custom code and reason\n```\n\n### `.expectClosed([expectedCode[, expectedReason]])`\n\nWaits for the socket to be closed. Optionally checks if it was closed\nwith the expected code and reason.\n\n```javascript\nrequest(server).ws('...')\n  .expectClosed()\n\nrequest(server).ws('...')\n  .expectClosed(1001) // expected code\n\nrequest(server).ws('...')\n  .expectClosed(1001, 'bye') // expected code and reason\n```\n\n### `.expectConnectionError([expectedStatusCode])`\n\nExpect the initial connection handshake to fail. Optionally checks for\na specific HTTP status code.\n\n*note: if you use this, it must be the only invocation in the chain*\n\n```javascript\nrequest(server).ws('...')\n  .expectConnectionError(); // any error\n\nrequest(server).ws('...')\n  .expectConnectionError(404); // specific error code\n\nrequest(server).ws('...')\n  .expectConnectionError('Server sent an invalid subprotocol'); // specific error message\n```\n\n### `.expectUpgrade(test)`\n\nRun a check against the Upgrade response. Useful for making arbitrary\nassertions about parts of the Upgrade response, such as headers.\n\nThe check will be considered a failure if it returns `false`. Any other\nvalue (including `undefined` and `null`) is considered a pass.\nThis means you can use (e.g.) Jest expectations (returning no value).\n\nThe parameter will be a\n[`http.IncomingMessage`](https://nodejs.org/api/http.html#http_class_http_incomingmessage).\n\n```javascript\nrequest(server).ws('...')\n  .expectUpgrade((res) =\u003e (res.headers['set-cookie'] === 'foo=bar'));\n\nrequest(server).ws('...')\n  .expectUpgrade((res) =\u003e {\n    expect(res.headers).toHaveProperty('set-cookie', 'foo=bar');\n  })\n```\n\n### `.wait(milliseconds)`\n\nAdds a delay of a number of milliseconds using `setTimeout`. This is\navailable as an escape hatch, but try to avoid using it, as it may\ncause intermittent failures in tests due to timing variations.\n\n```javascript\nrequest(server).ws('...')\n  .wait(500)\n```\n\n### `.exec(fn)`\n\nInvokes the given function. If the function returns a promise, this\nwaits for the promise to resolve (but ignores the result). The function\nwill be given the WebSocket as a parameter. This is available as an\nescape hatch if the standard functions do not meet your needs.\n\n```javascript\nrequest(server).ws('...')\n  .exec((ws) =\u003e console.log('hello debugger!'))\n```\n\n*note: this differs from `Promise.then` because you can continue to\nchain web socket actions and expectations.*\n\nSee [the FAQ](#how-can-i-perform-another-asynchronous-task-while-a-connection-is-open)\nfor examples of how `exec` can be used to perform side operations\nduring a connection.\n\n## FAQ\n\n### My server is closing the connection immediately with code 1002\n\nYour server is probably trying to indicate that you need to specify a\nparticular sub-protocol when connecting:\n\n```javascript\nrequest(myServer)\n  .ws('/path/ws', 'my-protocol-here')\n```\n\nYou will need to check the documentation for the server library you are\nusing to find out which subprotocol is needed. If multiple sub-protocols\nare needed, you can provide an array of strings.\n\n### Why do I see \"supertest dependency not found\" errors?\n\nOlder versions of this library bundled supertest by default because they\nused some functionality from it. The latest version does not require any\nfunctionality from supertest but remains API-compatible with it, and for\nthis reason supertest has become optional and not included by default\n(reducing dependencies when testing WebSocket-only servers).\n\nTo restore the ability to use `.get`, `.post`, etc. simply run:\n\n```shell\nnpm install --save-dev supertest\n```\n\nThe presence of this package will detected automatically and the supertest\nAPI will be available via superwstest as before.\n\n### Why isn't `request(app)` supported?\n\nThis project aims to be API-compatible with `supertest` wherever possible,\nbut does not support the ability to pass an `express` app directly into\n`request()` (instead, the server must be started in advance and the server\nobject passed in). The recommended approach is:\n\n```javascript\nlet server;\n\nbeforeEach((done) =\u003e {\n  server = app.listen(0, 'localhost', done);\n});\n\nafterEach((done) =\u003e {\n  server.close(done);\n});\n```\n\nThere are several reasons for not supporting this feature:\n\n- `supertest`'s implementation\n  [has a bug](https://github.com/visionmedia/supertest/issues/566) where it\n  does not wait for the server to start before making requests. This can lead\n  to flakey tests. For this reason it seems beneficial to discourage this\n  approach in general (for both WebSocket and non-WebSocket tests).\n- It is not possible for this library to reliably know when a test has ended,\n  so it is not obvious when the auto-started server should be closed.\n  `supertest`\n  [never closes these auto-started servers](https://github.com/visionmedia/supertest/issues/437)\n  (leading to\n  [a large number of servers being spawned](https://github.com/visionmedia/supertest/issues/489)\n  during a test run), but even this approach is not viable for WebSocket\n  testing (typical web requests are short-lived, but websockets are long-lived\n  and any dangling connections will prevent the test process from terminating).\n\n### How can I perform another asynchronous task while a connection is open?\n\nOften when testing websockets, you will want to perform another action and\ncheck for a reaction on the websocket. This can be achieved using `exec`:\n\n```javascript\nawait request(server).ws('here')\n  .sendText('hello')\n  .expectText('session open')\n  .exec(async () =\u003e {\n    await myOtherOperation();\n  })\n  .expectText('something happened')\n  .close();\n```\n\nThe recommended approach is to pull these out as helper functions, for example:\n\n```javascript\nconst makeThing = (name) =\u003e () =\u003e request(server)\n  .post('blah')\n  .expect(200);\n\nawait request(server).ws('here')\n  .sendText('hello')\n  .expectText('session open')\n\n  .exec(makeThing('my first thing'))\n  .expectText('made \"my first thing\"')\n\n  .exec(makeThing('my second thing'))\n  .expectText('made \"my second thing\"')\n\n  .close();\n```\n\nIf you need 2 websocket connections to interact with each other, you can use\n`Promise.all`:\n\n```javascript\nawait Promise.all([\n  request(server).ws('here')\n    .expectText('Welcome to the chat room')\n    .sendText('Hi all! I am foo')\n    .expectText('Hi foo, I am bar')\n    .close(),\n  request(server).ws('here')\n    .expectText('Welcome to the chat room')\n    .expectText('Hi all! I am foo')\n    .sendText('Hi foo, I am bar')\n    .close(),\n]);\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidje13%2Fsuperwstest","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavidje13%2Fsuperwstest","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidje13%2Fsuperwstest/lists"}