diff --git a/package.json b/package.json index c7bed8f1f..d817dbb22 100644 --- a/package.json +++ b/package.json @@ -180,6 +180,7 @@ "undici": "^5.20.0", "url-loader": "^4.1.1", "vitest": "^0.34.6", + "vitest-environment-miniflare": "^2.14.1", "webpack": "^5.68.0", "webpack-dev-server": "^3.11.2", "webpack-http-server": "^0.5.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3e9a1628e..9b68636de 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -72,6 +72,7 @@ specifiers: undici: ^5.20.0 url-loader: ^4.1.1 vitest: ^0.34.6 + vitest-environment-miniflare: ^2.14.1 webpack: ^5.68.0 webpack-dev-server: ^3.11.2 webpack-http-server: ^0.5.0 @@ -149,6 +150,7 @@ devDependencies: undici: 5.23.0 url-loader: 4.1.1_webpack@5.75.0 vitest: 0.34.6_jsdom@22.1.0 + vitest-environment-miniflare: 2.14.1_vitest@0.34.6 webpack: 5.75.0_mtsvlg4x4u5udzh2pohivgt4x4 webpack-dev-server: 3.11.3_webpack@5.75.0 webpack-http-server: 0.5.0_mtsvlg4x4u5udzh2pohivgt4x4 @@ -1340,6 +1342,10 @@ packages: statuses: 2.0.1 dev: false + /@cloudflare/workers-types/4.20231025.0: + resolution: {integrity: sha512-TkcZkntUTOcvJ4vgmwpNfLTclpMbmbClZCe62B25/VTukmyv91joRa4eKzSjzCZUXTbFHNmVdOpmGaaJU2U3+A==} + dev: true + /@commitlint/cli/16.3.0_@swc+core@1.3.35: resolution: {integrity: sha512-P+kvONlfsuTMnxSwWE1H+ZcPMY3STFaHb2kAacsqoIkNx66O0T7sTpBxpxkMrFPyhkJiLJnJWMhk4bbvYD3BMA==} engines: {node: '>=v12'} @@ -2193,6 +2199,10 @@ packages: resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} dev: true + /@iarna/toml/2.2.5: + resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==} + dev: true + /@jest/schemas/29.6.3: resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -2256,6 +2266,166 @@ packages: '@jridgewell/sourcemap-codec': 1.4.14 dev: true + /@miniflare/cache/2.14.1: + resolution: {integrity: sha512-f/o6UBV6UX+MlhjcEch73/wjQvvNo37dgYmP6Pn2ax1/mEHhJ7allNAqenmonT4djNeyB3eEYV3zUl54wCEwrg==} + engines: {node: '>=16.13'} + dependencies: + '@miniflare/core': 2.14.1 + '@miniflare/shared': 2.14.1 + http-cache-semantics: 4.1.1 + undici: 5.20.0 + dev: true + + /@miniflare/core/2.14.1: + resolution: {integrity: sha512-d+SGAda/VoXq+SKz04oq8ATUwQw5755L87fgPR8pTdR2YbWkxdbmEm1z2olOpDiUjcR86aN6NtCjY6tUC7fqaw==} + engines: {node: '>=16.13'} + dependencies: + '@iarna/toml': 2.2.5 + '@miniflare/queues': 2.14.1 + '@miniflare/shared': 2.14.1 + '@miniflare/watcher': 2.14.1 + busboy: 1.6.0 + dotenv: 10.0.0 + kleur: 4.1.5 + set-cookie-parser: 2.6.0 + undici: 5.20.0 + urlpattern-polyfill: 4.0.3 + dev: true + + /@miniflare/d1/2.14.1: + resolution: {integrity: sha512-MulDDBsDD8o5DwiqdMeJZy2vLoMji+NWnLcuibSag2mayA0LJcp0eHezseZNkW+knciWR1gMP8Xpa4Q1KwkbKA==} + engines: {node: '>=16.7'} + dependencies: + '@miniflare/core': 2.14.1 + '@miniflare/shared': 2.14.1 + dev: true + + /@miniflare/durable-objects/2.14.1: + resolution: {integrity: sha512-T+oHGw5GcEIilkzrf0xDES7jzLVqcXJzSGsEIWqnBFLtdlKmrZF679ulRLBbyMVgvpQz6FRONh9jTH1XIiuObQ==} + engines: {node: '>=16.13'} + dependencies: + '@miniflare/core': 2.14.1 + '@miniflare/shared': 2.14.1 + '@miniflare/storage-memory': 2.14.1 + undici: 5.20.0 + dev: true + + /@miniflare/html-rewriter/2.14.1: + resolution: {integrity: sha512-vp4uZXuEKhtIaxoXa7jgDAPItlzjbfoUqYWp+fwDKv4J4mfQnzzs/5hwjbE7+Ihm/KNI0zNi8P0sSWjIRFl6ng==} + engines: {node: '>=16.13'} + dependencies: + '@miniflare/core': 2.14.1 + '@miniflare/shared': 2.14.1 + html-rewriter-wasm: 0.4.1 + undici: 5.20.0 + dev: true + + /@miniflare/kv/2.14.1: + resolution: {integrity: sha512-Gp07Wcszle7ptsoO8mCtKQRs0AbQnYo1rgnxUcsTL3xJJaHXEA/B9EKSADS2XzJMeY4PgUOHU6Rf08OOF2yWag==} + engines: {node: '>=16.13'} + dependencies: + '@miniflare/shared': 2.14.1 + dev: true + + /@miniflare/queues/2.14.1: + resolution: {integrity: sha512-uBzrbBkIgtNoztDpmMMISg/brYtxLHRE7oTaN8OVnq3bG+3nF9kQC42HUz+Vg+sf65UlvhSaqkjllgx+fNtOxQ==} + engines: {node: '>=16.7'} + dependencies: + '@miniflare/shared': 2.14.1 + dev: true + + /@miniflare/r2/2.14.1: + resolution: {integrity: sha512-grOMnGf2XSicbgxMYMBfWE37k/e7l5NnwXZIViQ+N06uksp+MLA8E6yKQNtvrWQS66TM8gBvMnWo96OFmYjb6Q==} + engines: {node: '>=16.13'} + dependencies: + '@miniflare/core': 2.14.1 + '@miniflare/shared': 2.14.1 + undici: 5.20.0 + dev: true + + /@miniflare/runner-vm/2.14.1: + resolution: {integrity: sha512-UobsGM0ICVPDlJD54VPDSx0EXrIY3nJMXBy2zIFuuUOz4hQKXvMQ6jtAlJ8UNKer+XXI3Mb/9R/gfU8r6kxIMA==} + engines: {node: '>=16.13'} + dependencies: + '@miniflare/shared': 2.14.1 + dev: true + + /@miniflare/shared-test-environment/2.14.1: + resolution: {integrity: sha512-hfactEWiHuHOmE29XFG8oLNCF6+HqjD6Mb80CzidcVmLlBTEtSC3PEF+DXPyvNdLXpBolZMKOuC/yzzloWvACA==} + engines: {node: '>=16.13'} + dependencies: + '@cloudflare/workers-types': 4.20231025.0 + '@miniflare/cache': 2.14.1 + '@miniflare/core': 2.14.1 + '@miniflare/d1': 2.14.1 + '@miniflare/durable-objects': 2.14.1 + '@miniflare/html-rewriter': 2.14.1 + '@miniflare/kv': 2.14.1 + '@miniflare/queues': 2.14.1 + '@miniflare/r2': 2.14.1 + '@miniflare/shared': 2.14.1 + '@miniflare/sites': 2.14.1 + '@miniflare/storage-memory': 2.14.1 + '@miniflare/web-sockets': 2.14.1 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + + /@miniflare/shared/2.14.1: + resolution: {integrity: sha512-73GnLtWn5iP936ctE6ZJrMqGu134KOoIIveq5Yd/B+NnbFfzpuzjCpkLrnqjkDdsxDbruXSb5eTR/SmAdpJxZQ==} + engines: {node: '>=16.13'} + dependencies: + '@types/better-sqlite3': 7.6.7 + kleur: 4.1.5 + npx-import: 1.1.4 + picomatch: 2.3.1 + dev: true + + /@miniflare/sites/2.14.1: + resolution: {integrity: sha512-AbbIcU6VBeaNqVgMiLMWN2a09eX3jZmjaEi0uKqufVDqW/QIz47/30aC0O9qTe+XYpi3jjph/Ux7uEY8Z+enMw==} + engines: {node: '>=16.13'} + dependencies: + '@miniflare/kv': 2.14.1 + '@miniflare/shared': 2.14.1 + '@miniflare/storage-file': 2.14.1 + dev: true + + /@miniflare/storage-file/2.14.1: + resolution: {integrity: sha512-faZu9tRSW6c/looVFI/ZhkdGsIc9NfNCbSl3jJRmm7xgyZ+/S+dQ5JtGVbVsUIX8YGWDyE2j3oWCGCjxGLEpkg==} + engines: {node: '>=16.13'} + dependencies: + '@miniflare/shared': 2.14.1 + '@miniflare/storage-memory': 2.14.1 + dev: true + + /@miniflare/storage-memory/2.14.1: + resolution: {integrity: sha512-lfQbQwopVWd4W5XzrYdp0rhk3dJpvSmv1Wwn9RhNO20WrcuoxpdSzbmpBahsgYVg+OheVaEbS6RpFqdmwwLTog==} + engines: {node: '>=16.13'} + dependencies: + '@miniflare/shared': 2.14.1 + dev: true + + /@miniflare/watcher/2.14.1: + resolution: {integrity: sha512-dkFvetm5wk6pwunlYb/UkI0yFNb3otLpRm5RDywMUzqObEf+rCiNNAbJe3HUspr2ncZVAaRWcEaDh82vYK5cmw==} + engines: {node: '>=16.13'} + dependencies: + '@miniflare/shared': 2.14.1 + dev: true + + /@miniflare/web-sockets/2.14.1: + resolution: {integrity: sha512-3N//L5EjF7+xXd7qCLR2ylUwm8t2MKyGPGWEtRBrQ2xqYYWhewKTjlquHCOPU5Irnnd/4BhTmFA55MNrq7m4Nw==} + engines: {node: '>=16.13'} + dependencies: + '@miniflare/core': 2.14.1 + '@miniflare/shared': 2.14.1 + undici: 5.20.0 + ws: 8.14.2 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + /@mswjs/cookies/1.1.0: resolution: {integrity: sha512-0ZcCVQxifZmhwNBoQIrystCb+2sWBY2Zw8lpfJBPCHGCA/HWqehITeCRVIv4VMy8MPlaHo2w2pTHFV2pFfqKPw==} engines: {node: '>=18'} @@ -2531,6 +2701,12 @@ packages: '@types/node': 18.17.14 dev: true + /@types/better-sqlite3/7.6.7: + resolution: {integrity: sha512-+c2YGPWY5831v3uj2/X0HRTK94u1GXU3sCnLqu7AKlxlSfawswnAiJR//TFzSL5azWsLQkG/uS+YnnqHtuZxPw==} + dependencies: + '@types/node': 18.17.14 + dev: true + /@types/body-parser/1.19.2: resolution: {integrity: sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==} dependencies: @@ -3919,6 +4095,12 @@ packages: engines: {node: '>=6'} dev: true + /builtins/5.0.1: + resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} + dependencies: + semver: 7.5.4 + dev: true + /bundle-require/4.0.1_esbuild@0.17.19: resolution: {integrity: sha512-9NQkRHlNdNpDBGmLpngF3EFDcwodhMUuLz9PaWYciVcQF9SE4LFjM2DB/xV1Li5JiuDMv7ZUWuC3rGbqR0MAXQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -4867,6 +5049,11 @@ packages: is-obj: 2.0.0 dev: true + /dotenv/10.0.0: + resolution: {integrity: sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==} + engines: {node: '>=10'} + dev: true + /duplexer2/0.1.4: resolution: {integrity: sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==} dependencies: @@ -6175,6 +6362,10 @@ packages: resolution: {integrity: sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==} dev: true + /html-rewriter-wasm/0.4.1: + resolution: {integrity: sha512-lNovG8CMCCmcVB1Q7xggMSf7tqPCijZXaH4gL6iE8BFghdQCbaY5Met9i1x2Ex8m/cZHDUtXK9H6/znKamRP8Q==} + dev: true + /http-assert/1.5.0: resolution: {integrity: sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==} engines: {node: '>= 0.8'} @@ -6183,6 +6374,10 @@ packages: http-errors: 1.8.1 dev: true + /http-cache-semantics/4.1.1: + resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} + dev: true + /http-deceiver/1.2.7: resolution: {integrity: sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==} dev: true @@ -6947,6 +7142,11 @@ packages: engines: {node: '>=0.10.0'} dev: true + /kleur/4.1.5: + resolution: {integrity: sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==} + engines: {node: '>=6'} + dev: true + /koa-compose/4.1.0: resolution: {integrity: sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw==} dev: true @@ -7649,6 +7849,15 @@ packages: path-key: 4.0.0 dev: true + /npx-import/1.1.4: + resolution: {integrity: sha512-3ShymTWOgqGyNlh5lMJAejLuIv3W1K3fbI5Ewc6YErZU3Sp0PqsNs8UIU1O8z5+KVl/Du5ag56Gza9vdorGEoA==} + dependencies: + execa: 6.1.0 + parse-package-name: 1.0.0 + semver: 7.5.4 + validate-npm-package-name: 4.0.0 + dev: true + /nwsapi/2.2.7: resolution: {integrity: sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==} dev: true @@ -7923,6 +8132,10 @@ packages: lines-and-columns: 1.2.4 dev: true + /parse-package-name/1.0.0: + resolution: {integrity: sha512-kBeTUtcj+SkyfaW4+KBe0HtsloBJ/mKTPoxpVdA57GZiPerREsUWJOhVj9anXweFiJkm5y8FG1sxFZkZ0SN6wg==} + dev: true + /parse-passwd/1.0.0: resolution: {integrity: sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==} engines: {node: '>=0.10.0'} @@ -8825,6 +9038,10 @@ packages: resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} dev: true + /set-cookie-parser/2.6.0: + resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==} + dev: true + /set-value/2.0.1: resolution: {integrity: sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==} engines: {node: '>=0.10.0'} @@ -9827,6 +10044,13 @@ packages: which-boxed-primitive: 1.0.2 dev: true + /undici/5.20.0: + resolution: {integrity: sha512-J3j60dYzuo6Eevbawwp1sdg16k5Tf768bxYK4TUJRH7cBM4kFCbf3mOnM/0E3vQYXvpxITbbWmBafaDbxLDz3g==} + engines: {node: '>=12.18'} + dependencies: + busboy: 1.6.0 + dev: true + /undici/5.23.0: resolution: {integrity: sha512-1D7w+fvRsqlQ9GscLBwcAJinqcZGHUKjbOmXdlE/v8BvEGXjeWAax+341q44EuTcHXXnfyKNbKRq4Lg7OzhMmg==} engines: {node: '>=14.0'} @@ -9942,6 +10166,10 @@ packages: querystring: 0.2.0 dev: true + /urlpattern-polyfill/4.0.3: + resolution: {integrity: sha512-DOE84vZT2fEcl9gqCUTcnAw5ZY5Id55ikUcziSUntuEFL3pRvavg5kwDmTEUJkeCHInTlV/HexFomgYnzO5kdQ==} + dev: true + /use/3.1.1: resolution: {integrity: sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==} engines: {node: '>=0.10.0'} @@ -9991,6 +10219,13 @@ packages: spdx-expression-parse: 3.0.1 dev: true + /validate-npm-package-name/4.0.0: + resolution: {integrity: sha512-mzR0L8ZDktZjpX4OB46KT+56MAhl4EIazWP/+G/HPGuvfdaqg4YsCdtOm6U9+LOFyYDoh4dpnpxZRB9MQQns5Q==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + builtins: 5.0.1 + dev: true + /vary/1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} @@ -10054,6 +10289,23 @@ packages: fsevents: 2.3.2 dev: true + /vitest-environment-miniflare/2.14.1_vitest@0.34.6: + resolution: {integrity: sha512-efMpx9XnpjHeIN1lnEMO+4Ky9xSFM0VeG8Ilf+5Uyh8U8lNuJ+qTTfr76LQ6MQcNzkLMo4byh0YxaZo8QfIYrw==} + engines: {node: '>=16.13'} + peerDependencies: + vitest: '>=0.23.0' + dependencies: + '@miniflare/queues': 2.14.1 + '@miniflare/runner-vm': 2.14.1 + '@miniflare/shared': 2.14.1 + '@miniflare/shared-test-environment': 2.14.1 + undici: 5.20.0 + vitest: 0.34.6_jsdom@22.1.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: true + /vitest/0.34.6_jsdom@22.1.0: resolution: {integrity: sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==} engines: {node: '>=v14.18.0'} diff --git a/test/node/regressions/miniflare.node.test.ts b/test/node/regressions/miniflare.node.test.ts new file mode 100644 index 000000000..eb5f6b5db --- /dev/null +++ b/test/node/regressions/miniflare.node.test.ts @@ -0,0 +1,75 @@ +/** + * @vitest-environment miniflare + */ +import nodeHttp from 'http' +import { HttpServer } from '@open-draft/test-server/http' +import { http, HttpResponse } from 'msw' +import { setupServer } from 'msw/node' +import { waitForClientRequest } from '../../support/utils' + +const httpServer = new HttpServer((app) => { + app.get('/resource', (_, res) => { + return res.status(500).send('original-response') + }) +}) + +const server = setupServer() + +beforeAll(async () => { + await httpServer.listen() + server.listen() +}) + +beforeEach(() => { + server.use( + http.get(httpServer.http.url('/resource'), () => { + return HttpResponse.json( + { firstName: 'John' }, + { + status: 401, + headers: { + 'x-header': 'yes', + }, + }, + ) + }), + ) +}) + +afterEach(() => { + server.resetHandlers() +}) + +afterAll(async () => { + server.close() + await httpServer.close() +}) + +it('returns a mocked response to an "http.get" request', async () => { + const request = nodeHttp.get(httpServer.http.url('/resource')) + const { response, responseText } = await waitForClientRequest(request) + + expect(response.statusCode).toBe(401) + expect(response.headers).toEqual( + expect.objectContaining({ + 'content-type': 'application/json', + 'x-header': 'yes', + }), + ) + expect(responseText).toBe('{"firstName":"John"}') +}) + +it('returns a mocked response to an "http.request" request', async () => { + const request = nodeHttp.request(httpServer.http.url('/resource')) + request.end() + const { response, responseText } = await waitForClientRequest(request) + + expect(response.statusCode).toBe(401) + expect(response.headers).toEqual( + expect.objectContaining({ + 'content-type': 'application/json', + 'x-header': 'yes', + }), + ) + expect(responseText).toBe('{"firstName":"John"}') +})