diff --git a/.browserslistrc b/.browserslistrc index 50d2bc60..5f163ced 100644 --- a/.browserslistrc +++ b/.browserslistrc @@ -17,7 +17,7 @@ # Generated data. # -# Last generated Mar 15, 2024 8:58 AM UTC. +# Last generated Mar 16, 2024 2:55 AM UTC. [production] node >= 20.9.0 diff --git a/.dockerignore b/.dockerignore index d601729e..c08d576e 100644 --- a/.dockerignore +++ b/.dockerignore @@ -17,7 +17,7 @@ # Generated data. # -# Last generated Mar 15, 2024 8:58 AM UTC. +# Last generated Mar 16, 2024 2:55 AM UTC. # Locals diff --git a/.env.vault b/.env.vault index 2f6f8cae..0bf89219 100644 --- a/.env.vault +++ b/.env.vault @@ -8,12 +8,12 @@ DOTENV_VAULT_MAIN="7GW98NfL4hM4N6HbfeDXCKreVxKvcVPupFRnZ8XJ+pomaQ==" DOTENV_VAULT_MAIN_VERSION=1 # dev -DOTENV_VAULT_DEV="574ELXrHj4VNmUqsDYhwbpFmWitCsN4euV5UwniYcmb7q5lRqStjSjhVpYlKBNI/k+t0HaHFrR3s7yt0z4X/qfIGSkLe/xhmcawcy7BiAGHP6PKQFO2TEHTCIZNLDtGqzrq+x6WpteqCA8Yejy9O71b8d71ZyjPJw9zbjJB2g3pEsVX2LCcPjrY7MxhtlcyjI/NB1YdZnm8CjmVHsRz1WnBzLAcI4P6skAX7X9XX/FxSuKv8k63PmjakZWNob1/L7Q==" -DOTENV_VAULT_DEV_VERSION=457 +DOTENV_VAULT_DEV="O9VkthkxvBAdSrwf1CVueZQ1uUKqItb92QthzejUPfShQlRmnhWTKVw7ZPdUht2t6qQakgeJQq2rpPGRpJmfz5STB5wMpm4kkVcaNnyOHUGI4bgL1bg5DeI+OSMbJ2Joso+gz9GqK82O9soqvCPiIBRTJywnoyjdALdP5O1NhOQnL2Hlz+iwWzQY0vgOCuttekAaMKx0oIAy7474OEibFPJ4fwFzlS2tlo2xR49BY6dgLU52QfpYcdl+ZtICk8ZHDA==" +DOTENV_VAULT_DEV_VERSION=459 # ci -DOTENV_VAULT_CI="HpoOuFIeKrVgWepRjdY69LajPpNahcqj+02jPeyuSPkJtq9afKnaXpzNOIL+pdtPXrphcl4GCIi42tt+NU9osiNC3GKLadr3P2rRZ6RP9C6Xb7+zuM0DFFPO+40Z0o1Bhw4fwPa1dNJgHStLaVztq8IQDJkuzUXq/iW9E4Hd7g==" -DOTENV_VAULT_CI_VERSION=457 +DOTENV_VAULT_CI="RP4UxhHGgIQLX1irR/uSoRCpq2agnPvlZHBU8L3PmYpIYplqV8tMk00Z4Y6aIea84DFSaADdgbJ3YWr9mcLg645qdv++0cObwfi0XEygvyGuQe7b+jThzeZBTZ92CwFi11pSSo9u8zhOv9ildvJTNnzt3ms1kji3XRr14xBJOA==" +DOTENV_VAULT_CI_VERSION=459 # stage DOTENV_VAULT_STAGE="aRP8su2YV4jZu3w1HZ/SLaots0IwJDFw75TCpvXEFeNp7tw=" diff --git a/.gitattributes b/.gitattributes index 873e35b7..7727a618 100644 --- a/.gitattributes +++ b/.gitattributes @@ -17,7 +17,7 @@ # Generated data. # -# Last generated Mar 15, 2024 8:58 AM UTC. +# Last generated Mar 16, 2024 2:55 AM UTC. # Default diff --git a/.gitignore b/.gitignore index 05dfd97b..dd03e559 100644 --- a/.gitignore +++ b/.gitignore @@ -17,7 +17,7 @@ # Generated data. # -# Last generated Mar 15, 2024 8:58 AM UTC. +# Last generated Mar 16, 2024 2:55 AM UTC. # Locals diff --git a/.npmignore b/.npmignore index f0afa5d3..8854ed46 100644 --- a/.npmignore +++ b/.npmignore @@ -25,7 +25,7 @@ # Generated data. # -# Last generated Mar 15, 2024 8:58 AM UTC. +# Last generated Mar 16, 2024 2:55 AM UTC. # Locals diff --git a/.prettierignore b/.prettierignore index f08e24dc..ec2aaf1a 100644 --- a/.prettierignore +++ b/.prettierignore @@ -17,7 +17,7 @@ # Generated data. # -# Last generated Mar 15, 2024 8:58 AM UTC. +# Last generated Mar 16, 2024 2:55 AM UTC. # Packages diff --git a/.vscode/settings.json b/.vscode/settings.json index be7e7c28..4eaf18fa 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -7,7 +7,7 @@ * @note This entire file will be updated automatically. * @note Instead of editing here, please review `./settings.mjs`. * - * Last generated using `./settings.mjs` Mar 15, 2024 8:58 AM UTC. + * Last generated using `./settings.mjs` Mar 16, 2024 2:55 AM UTC. */ { "editor.formatOnType": false, diff --git a/.vscodeignore b/.vscodeignore index 514a2db1..75bd987e 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -17,7 +17,7 @@ # Generated data. # -# Last generated Mar 15, 2024 8:58 AM UTC. +# Last generated Mar 16, 2024 2:55 AM UTC. # Locals diff --git a/package-lock.json b/package-lock.json index 134ab5e4..90805c06 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@clevercanyon/utilities", - "version": "1.0.914", + "version": "1.0.915", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@clevercanyon/utilities", - "version": "1.0.914", + "version": "1.0.915", "cpu": [ "x64", "arm64" @@ -1026,9 +1026,9 @@ } }, "node_modules/@clevercanyon/utilities": { - "version": "1.0.914", - "resolved": "https://registry.npmjs.org/@clevercanyon/utilities/-/utilities-1.0.914.tgz", - "integrity": "sha512-ZyX+pYjbJqpKXXfyKwKcsuWnGGzOp2cnJURTw8K/O0my5rwxGE8RiINdDcDmPLRvNQOqdhh872h4ebM7ysOcxw==", + "version": "1.0.915", + "resolved": "https://registry.npmjs.org/@clevercanyon/utilities/-/utilities-1.0.915.tgz", + "integrity": "sha512-DLoo4Y3jiow6usCj9sJUyI9xkeWsYqjKgsaedseI1p7vUM6O+eNYPVHLmbE+sMgoF1RupKjgEmjMDSDMPKKZnA==", "cpu": [ "x64", "arm64" @@ -3623,9 +3623,9 @@ } }, "node_modules/@mdn/browser-compat-data": { - "version": "5.5.15", - "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.5.15.tgz", - "integrity": "sha512-BWm+TMK60HSepXOZcu39bDs/2sJZVetHO5w0mkuxhpkZvz0G5yGAoyimfaru8g5nK6LXXUIeX6Uk/SWzOfph3g==", + "version": "5.5.16", + "resolved": "https://registry.npmjs.org/@mdn/browser-compat-data/-/browser-compat-data-5.5.16.tgz", + "integrity": "sha512-za4DOflM2h73Rs2ORnhS2IU73sVRjrN4x5ZmOZ8WgLCSOVuZ1+y1K0NQKy8xqaPW52ezN+ni2N2RBUKt532ULA==", "dev": true }, "node_modules/@mdx-js/esbuild": { @@ -7488,15 +7488,6 @@ "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", "dev": true }, - "node_modules/asynciterator.prototype": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", - "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", - "dev": true, - "dependencies": { - "has-symbols": "^1.0.3" - } - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -9086,6 +9077,57 @@ "node": ">=18" } }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/dayjs": { "version": "1.11.10", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", @@ -9536,9 +9578,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.4.707", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.707.tgz", - "integrity": "sha512-qRq74Mo7ChePOU6GHdfAJ0NREXU8vQTlVlfWz3wNygFay6xrd/fY2J7oGHwrhFeU30OVctGLdTh/FcnokTWpng==", + "version": "1.4.708", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.708.tgz", + "integrity": "sha512-iWgEEvREL4GTXXHKohhh33+6Y8XkPI5eHihDmm8zUk5Zo7HICEW+wI/j5kJ2tbuNUCXJ/sNXa03ajW635DiJXA==", "dev": true }, "node_modules/emittery": { @@ -9589,15 +9631,18 @@ } }, "node_modules/es-abstract": { - "version": "1.22.5", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.5.tgz", - "integrity": "sha512-oW69R+4q2wG+Hc3KZePPZxOiisRIqfKBVo/HLx94QcJeWGU/8sZhCvc829rd1kS366vlJbzBfXf9yWwf0+Ko7w==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.0.tgz", + "integrity": "sha512-vmuE7Uoevk2xkwu5Gwa7RfJk/ebVV6xRv7KuZNbUglmJHhWPMbLL20ztreVpBbdxBZijETx3Aml3NssX4SFMvQ==", "dev": true, "dependencies": { "array-buffer-byte-length": "^1.0.1", "arraybuffer.prototype.slice": "^1.0.3", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.0", + "data-view-byte-offset": "^1.0.0", "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.0.3", @@ -9614,6 +9659,7 @@ "internal-slot": "^1.0.7", "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.3", @@ -9685,26 +9731,25 @@ } }, "node_modules/es-iterator-helpers": { - "version": "1.0.17", - "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.17.tgz", - "integrity": "sha512-lh7BsUqelv4KUbR5a/ZTaGGIMLCjPGPqJ6q+Oq24YP0RdyptX1uzm4vvaqzk7Zx3bpl/76YLTTDj9L7uYQ92oQ==", + "version": "1.0.18", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.18.tgz", + "integrity": "sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA==", "dev": true, "dependencies": { - "asynciterator.prototype": "^1.0.0", "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.22.4", + "es-abstract": "^1.23.0", "es-errors": "^1.3.0", - "es-set-tostringtag": "^2.0.2", + "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "globalthis": "^1.0.3", "has-property-descriptors": "^1.0.2", - "has-proto": "^1.0.1", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", "internal-slot": "^1.0.7", "iterator.prototype": "^1.1.2", - "safe-array-concat": "^1.1.0" + "safe-array-concat": "^1.1.2" }, "engines": { "node": ">= 0.4" @@ -14097,6 +14142,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-date-object": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", @@ -29412,9 +29472,9 @@ } }, "node_modules/ufo": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.4.0.tgz", - "integrity": "sha512-Hhy+BhRBleFjpJ2vchUNN40qgkh0366FWJGqVLYBHev0vpHTrXSA0ryT+74UiW6KWsldNurQMKGqCm1M2zBciQ==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.5.1.tgz", + "integrity": "sha512-HGyF79+/qZ4soRvM+nHERR2pJ3VXDZ/8sL1uLahdgEDf580NkgiWOxLk33FetExqOWp352JZRsgXbG/4MaGOSg==", "dev": true }, "node_modules/unbox-primitive": { diff --git a/package.json b/package.json index 1c5d8152..fa269440 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "publishConfig": { "access": "public" }, - "version": "1.0.915", + "version": "1.0.916", "license": "GPL-3.0-or-later", "name": "@clevercanyon/utilities", "description": "Utilities for JavaScript apps running in any environment.", diff --git a/src/http.ts b/src/http.ts index 30cc2687..2c899122 100644 --- a/src/http.ts +++ b/src/http.ts @@ -145,20 +145,28 @@ export const prepareRequest = async (request: $type.Request, config?: RequestCon /** * Produces a hash of a given HTTP request. * - * Properties and headers are sorted for hash consistency. + * Properties, headers, and URL query vars are sorted for consistency. We hash a canonicalized URL; i.e., without query + * vars and/or a #hash. Query vars are hashed separately and any #hash value is ignored entirely. Query vars are hashed + * as decoded entries, such that we avoid encoding discrepancies across platforms; e.g., {@see https://o5p.me/mwt0RQ}. * * @param request HTTP request. * * @returns SHA-1 hash of HTTP request. * - * @note Please {@see requestPropertyDefaults()}, which makes hashing possible. + * @see requestPropertyDefaults(), which is what makes hashing possible. */ export const requestHash = $fnꓺmemo(2, async (request: $type.Request): Promise => { - const defaults = requestPropertyDefaults(), + const url = new URL(request.url), + defaults = requestPropertyDefaults(), properties = requestProperties(request), unsortedProps = $obj.defaults(properties, defaults) as $type.StrKeyable; const sortedProps = Object.fromEntries([...Object.entries(unsortedProps)].sort((a, b) => a[0].localeCompare(b[0]))); + + sortedProps.url = { + canonical: $url.toCanonical(url), // i.e., Without ?query and/or #hash. + queryVars: [...url.searchParams.entries()].sort((a, b) => a[0].localeCompare(b[0])), + }; sortedProps.headers = [...request.headers.entries()].sort((a, b) => a[0].localeCompare(b[0])); if (sortedProps.body /* Requires request clone. */) { diff --git a/src/tests/classes/fetcher/index.cfw.ts b/src/tests/classes/fetcher/index.cfw.ts index fbe7c2ac..981d5972 100644 --- a/src/tests/classes/fetcher/index.cfw.ts +++ b/src/tests/classes/fetcher/index.cfw.ts @@ -46,8 +46,8 @@ describe('Fetcher', async () => { headers: { 'content-type': $mime.contentType('.txt') }, }, }; - expect(fetcher.global.cache['ccb3b1f7061e279e02f9d3761d0dcf90ced8e4b8']).toStrictEqual(expectedCache); - expect(fetcher.global.cache['e42f835c52038a7a9f0d37f1e570d0f573185ecd']).toStrictEqual(expectedCache); - expect(fetcher.global.cache['cca6054445f5e17c31218d204a66bbabba314234']).toStrictEqual(expectedCache); + expect(fetcher.global.cache['dea440f47ad1caee47a54e1d9caebc4ee4829de5']).toStrictEqual(expectedCache); + expect(fetcher.global.cache['6e589b81c89bc2c5c7d1a20cd59fb92c2be5b08a']).toStrictEqual(expectedCache); + expect(fetcher.global.cache['d07c269b27b019bd5dd5c22bec9795e437eca3e7']).toStrictEqual(expectedCache); }); }); diff --git a/src/tests/classes/fetcher/index.node.ts b/src/tests/classes/fetcher/index.node.ts index a99be161..aaf643e4 100644 --- a/src/tests/classes/fetcher/index.node.ts +++ b/src/tests/classes/fetcher/index.node.ts @@ -46,8 +46,8 @@ describe('Fetcher', async () => { headers: { 'content-type': $mime.contentType('.txt') }, }, }; - expect(fetcher.global.cache['ccb3b1f7061e279e02f9d3761d0dcf90ced8e4b8']).toStrictEqual(expectedCache); - expect(fetcher.global.cache['e42f835c52038a7a9f0d37f1e570d0f573185ecd']).toStrictEqual(expectedCache); - expect(fetcher.global.cache['cca6054445f5e17c31218d204a66bbabba314234']).toStrictEqual(expectedCache); + expect(fetcher.global.cache['dea440f47ad1caee47a54e1d9caebc4ee4829de5']).toStrictEqual(expectedCache); + expect(fetcher.global.cache['6e589b81c89bc2c5c7d1a20cd59fb92c2be5b08a']).toStrictEqual(expectedCache); + expect(fetcher.global.cache['d07c269b27b019bd5dd5c22bec9795e437eca3e7']).toStrictEqual(expectedCache); }); }); diff --git a/src/tests/http/index.ts b/src/tests/http/index.ts index e6d9d25b..79ee63b7 100644 --- a/src/tests/http/index.ts +++ b/src/tests/http/index.ts @@ -192,7 +192,7 @@ describe('$http', async () => { headers: { 'foo': 'foo', 'bar': 'bar' }, }), ), - ).toBe('34187aa82135e8e0f8ba3b44dc49ed77b3fd0fb1'); + ).toBe('932cedfb51a4f5fdf07be8506fb2bea06d28c58d'); expect( await $http.requestHash( @@ -201,7 +201,7 @@ describe('$http', async () => { redirect: 'manual', }), ), - ).toBe('34187aa82135e8e0f8ba3b44dc49ed77b3fd0fb1'); + ).toBe('932cedfb51a4f5fdf07be8506fb2bea06d28c58d'); expect( await $http.requestHash( @@ -216,7 +216,7 @@ describe('$http', async () => { body: 'body', }), ), - ).toBe('1d3a8d27cea851282d31c7c4e507ed04b0d94efb'); + ).toBe('408752f44d6b6106f1b76c6f28d1924b8f569fa5'); expect( await $http.requestHash( @@ -231,7 +231,7 @@ describe('$http', async () => { body: 'body', }), ), - ).toBe('1d3a8d27cea851282d31c7c4e507ed04b0d94efb'); + ).toBe('408752f44d6b6106f1b76c6f28d1924b8f569fa5'); }); test('.prepareRefererHeader()', async () => { const headers1 = new Headers({ 'referrer-policy': 'no-referrer' }); diff --git a/src/tests/http/request-hash.any.ts b/src/tests/http/request-hash.any.ts new file mode 100644 index 00000000..56a2180a --- /dev/null +++ b/src/tests/http/request-hash.any.ts @@ -0,0 +1,76 @@ +/** + * Test suite. + */ + +import { $http } from '#index.ts'; +import { describe, expect, test } from 'vitest'; + +describe('$http', async () => { + test('.requestHash()', async () => { + expect( + await $http.requestHash( + new Request('https://x.tld/'), // + ), + ).toBe('1c7c52306c62bf93a0b86476922d76ccad58c183'); + + expect( + await $http.requestHash( + new Request('https://y.tld/'), // + ), + ).toBe('4ceedadd4a1d6e0f69f549b2e9fa59280be69145'); + + // --- + + const hash932cedfb = '932cedfb51a4f5fdf07be8506fb2bea06d28c58d'; + expect( + await $http.requestHash( + new Request('https://x.tld/', { + redirect: 'manual', + headers: { 'foo': 'foo', 'bar': 'bar' }, + }), + ), + ).toBe(hash932cedfb); + + expect( + await $http.requestHash( + new Request('https://x.tld/', { + headers: { 'bar': 'bar', 'foo': 'foo' }, + redirect: 'manual', + }), + ), + ).toBe(hash932cedfb); + + // --- + + const hash86ae5ff4 = '86ae5ff4e0b389212a8b5e1675b1188d0336751d'; + expect( + await $http.requestHash( + new Request('https://x.tld/?foo=&bar=.*_+%3D%60%21%40%24%25%5E%7C%3C%3E%3F%2C%3A%3B%27%22%28%29%7B%7D%5B%5D%5C%2F', { + method: 'POST', + redirect: 'manual', + headers: { + 'foo': 'foo', + 'bar': 'bar', + 'content-type': 'text/plain; charset=utf-8', + }, + body: 'body', + }), + ), + ).toBe(hash86ae5ff4); + + expect( + await $http.requestHash( + new Request('https://x.tld/?bar=.*_+%3D%60%21%40%24%25%5E%7C%3C%3E%3F%2C%3A%3B%27%22%28%29%7B%7D%5B%5D%5C%2F&foo', { + redirect: 'manual', + method: 'POST', + headers: { + 'bar': 'bar', + 'foo': 'foo', + 'content-type': 'text/plain; charset=utf-8', + }, + body: 'body', + }), + ), + ).toBe(hash86ae5ff4); + }); +}); diff --git a/src/tests/http/request-hash.cfw.ts b/src/tests/http/request-hash.cfw.ts index e569b914..4813bf2b 100644 --- a/src/tests/http/request-hash.cfw.ts +++ b/src/tests/http/request-hash.cfw.ts @@ -2,4 +2,4 @@ * Test suite. */ -import './request-hash.web.ts'; +import './request-hash.any.ts'; diff --git a/src/tests/http/request-hash.node.ts b/src/tests/http/request-hash.node.ts index e569b914..4813bf2b 100644 --- a/src/tests/http/request-hash.node.ts +++ b/src/tests/http/request-hash.node.ts @@ -2,4 +2,4 @@ * Test suite. */ -import './request-hash.web.ts'; +import './request-hash.any.ts'; diff --git a/src/tests/http/request-hash.web.ts b/src/tests/http/request-hash.web.ts index a221b0da..4813bf2b 100644 --- a/src/tests/http/request-hash.web.ts +++ b/src/tests/http/request-hash.web.ts @@ -2,69 +2,4 @@ * Test suite. */ -import { $http } from '#index.ts'; -import { describe, expect, test } from 'vitest'; - -describe('$http', async () => { - test('.requestHash()', async () => { - expect( - await $http.requestHash( - new Request('https://x.tld/'), // - ), - ).toBe('040647e4b50c92026667047e3e6414f9bc6687a1'); - - expect( - await $http.requestHash( - new Request('https://y.tld/'), // - ), - ).toBe('d1d50afb30d73ba631e6d2840323f6fc09a29c90'); - - expect( - await $http.requestHash( - new Request('https://x.tld/', { - redirect: 'manual', - headers: { 'foo': 'foo', 'bar': 'bar' }, - }), - ), - ).toBe('34187aa82135e8e0f8ba3b44dc49ed77b3fd0fb1'); - - expect( - await $http.requestHash( - new Request('https://x.tld/', { - headers: { 'bar': 'bar', 'foo': 'foo' }, - redirect: 'manual', - }), - ), - ).toBe('34187aa82135e8e0f8ba3b44dc49ed77b3fd0fb1'); - - expect( - await $http.requestHash( - new Request('https://x.tld/', { - method: 'POST', - redirect: 'manual', - headers: { - 'foo': 'foo', - 'bar': 'bar', - 'content-type': 'text/plain; charset=utf-8', - }, - body: 'body', - }), - ), - ).toBe('1d3a8d27cea851282d31c7c4e507ed04b0d94efb'); - - expect( - await $http.requestHash( - new Request('https://x.tld/', { - redirect: 'manual', - method: 'POST', - headers: { - 'bar': 'bar', - 'foo': 'foo', - 'content-type': 'text/plain; charset=utf-8', - }, - body: 'body', - }), - ), - ).toBe('1d3a8d27cea851282d31c7c4e507ed04b0d94efb'); - }); -}); +import './request-hash.any.ts'; diff --git a/src/tests/preact/apis/iso/ex-imports/fixtures/prerender-spa-for-web.html b/src/tests/preact/apis/iso/ex-imports/fixtures/prerender-spa-for-web.html index 34032e4b..bc36a72a 100644 --- a/src/tests/preact/apis/iso/ex-imports/fixtures/prerender-spa-for-web.html +++ b/src/tests/preact/apis/iso/ex-imports/fixtures/prerender-spa-for-web.html @@ -1,2 +1,2 @@ -index \ No newline at end of file +index \ No newline at end of file diff --git a/src/tests/preact/apis/iso/prerender-spa-lazy.cfw.tsx b/src/tests/preact/apis/iso/prerender-spa-lazy.cfw.tsx index 47ba82b8..69a741ec 100644 --- a/src/tests/preact/apis/iso/prerender-spa-lazy.cfw.tsx +++ b/src/tests/preact/apis/iso/prerender-spa-lazy.cfw.tsx @@ -167,7 +167,7 @@ describe('$preact.iso.prerenderSPA() [lazy-cfw]', async () => { expect(lazyHTML).toContain('