diff --git a/.gitignore b/.gitignore index 6f6b665..66fe243 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,7 @@ dist/ .cache .output .env -.eslintcache \ No newline at end of file +.eslintcache + +# vitest +coverage \ No newline at end of file diff --git a/package.json b/package.json index 787805c..d597d88 100644 --- a/package.json +++ b/package.json @@ -58,10 +58,12 @@ "devDependencies": { "@eslint/js": "^9.23.0", "@size-limit/preset-small-lib": "^11.2.0", + "@vitest/coverage-v8": "3.0.8", "esbuild": "^0.25.0", "eslint": "^9.22.0", "eslint-plugin-jsdoc": "^50.6.3", "globals": "^16.0.0", + "happy-dom": "^17.4.4", "husky": "^9.1.7", "netlify-cli": "^19.0.2", "prettier": "^3.5.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2bd1923..bfcf913 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ importers: '@size-limit/preset-small-lib': specifier: ^11.2.0 version: 11.2.0(size-limit@11.2.0) + '@vitest/coverage-v8': + specifier: 3.0.8 + version: 3.0.8(vitest@3.0.8(@types/node@22.13.10)(happy-dom@17.4.4)(jiti@2.4.2)(terser@5.39.0)(yaml@2.7.0)) esbuild: specifier: ^0.25.0 version: 0.25.0 @@ -26,6 +29,9 @@ importers: globals: specifier: ^16.0.0 version: 16.0.0 + happy-dom: + specifier: ^17.4.4 + version: 17.4.4 husky: specifier: ^9.1.7 version: 9.1.7 @@ -49,7 +55,7 @@ importers: version: 5.8.2 vitest: specifier: ^3.0.8 - version: 3.0.8(@types/node@22.13.10)(jiti@2.4.2)(terser@5.39.0)(yaml@2.7.0) + version: 3.0.8(@types/node@22.13.10)(happy-dom@17.4.4)(jiti@2.4.2)(terser@5.39.0)(yaml@2.7.0) site: dependencies: @@ -62,6 +68,10 @@ importers: packages: + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + '@babel/code-frame@7.26.2': resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} @@ -74,15 +84,28 @@ packages: resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} engines: {node: '>=6.9.0'} + '@babel/parser@7.26.10': + resolution: {integrity: sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/parser@7.26.9': resolution: {integrity: sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==} engines: {node: '>=6.0.0'} hasBin: true + '@babel/types@7.26.10': + resolution: {integrity: sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==} + engines: {node: '>=6.9.0'} + '@babel/types@7.26.9': resolution: {integrity: sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==} engines: {node: '>=6.9.0'} + '@bcoe/v8-coverage@1.0.2': + resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} + engines: {node: '>=18'} + '@bugsnag/browser@7.25.0': resolution: {integrity: sha512-PzzWy5d9Ly1CU1KkxTB6ZaOw/dO+CYSfVtqxVJccy832e6+7rW/dvSw5Jy7rsNhgcKSKjZq86LtNkPSvritOLA==} @@ -938,6 +961,10 @@ packages: resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} engines: {node: '>=18.0.0'} + '@istanbuljs/schema@0.1.3': + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + '@jest/types@27.5.1': resolution: {integrity: sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==} engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} @@ -1360,8 +1387,8 @@ packages: '@redocly/config@0.22.1': resolution: {integrity: sha512-1CqQfiG456v9ZgYBG9xRQHnpXjt8WoSnDwdkX6gxktuK69v2037hTAR1eh0DGIqpZ1p4k82cGH8yTNwt7/pI9g==} - '@redocly/openapi-core@1.33.0': - resolution: {integrity: sha512-MUB1jPxYX2NmgiobICcvyrkSbPSaGAb/P/MsxSW+UT9hxpQvDCX81bstGg68BcKIdeFvVRKcoyG4xiTgDOEBfQ==} + '@redocly/openapi-core@1.34.0': + resolution: {integrity: sha512-Ji00EiLQRXq0pJIz5pAjGF9MfQvQVsQehc6uIis6sqat8tG/zh25Zi64w6HVGEDgJEzUeq/CuUlD0emu3Hdaqw==} engines: {node: '>=18.17.0', npm: '>=9.5.0'} '@rollup/plugin-alias@5.1.1': @@ -1774,6 +1801,15 @@ packages: engines: {node: '>=18'} hasBin: true + '@vitest/coverage-v8@3.0.8': + resolution: {integrity: sha512-y7SAKsQirsEJ2F8bulBck4DoluhI2EEgTimHd6EEUgJBGKy9tC25cpywh1MH4FvDGoG2Unt7+asVd1kj4qOSAw==} + peerDependencies: + '@vitest/browser': 3.0.8 + vitest: 3.0.8 + peerDependenciesMeta: + '@vitest/browser': + optional: true + '@vitest/expect@3.0.8': resolution: {integrity: sha512-Xu6TTIavTvSSS6LZaA3EebWFr6tsoXPetOWNMOlc7LO88QVVBwq2oQWBoDiLCN6YTvNYsGSjqOO8CAdjom5DCQ==} @@ -3535,6 +3571,10 @@ packages: engines: {node: '>=0.4.7'} hasBin: true + happy-dom@17.4.4: + resolution: {integrity: sha512-/Pb0ctk3HTZ5xEL3BZ0hK1AqDSAUuRQitOmROPHhfUYEWpmTImwfD8vFDGADmMAX0JYgbcgxWoLFKtsWhcpuVA==} + engines: {node: '>=18.0.0'} + has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} @@ -3573,6 +3613,9 @@ packages: resolution: {integrity: sha512-tmjcyZkG/qADhcdC7UjAp8D7v7W2DOYFgaZ48fYMuayMQmVVUg8fntKmrjes/b40ef6yZ+qt1lB8kuEDfLC4zw==} engines: {node: '>=10.0.0'} + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + http-cache-semantics@4.1.1: resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} @@ -3695,6 +3738,10 @@ packages: resolution: {integrity: sha512-MWDKS3AS1bGCHLBA2VLImJz42f7bJh8wQsTGCzI3j519/CASStoDONUBVz2I/VID0MpiX3SGSnbOD2xUalbE5g==} engines: {node: '>=18'} + index-to-position@1.0.0: + resolution: {integrity: sha512-sCO7uaLVhRJ25vz1o8s9IFM3nVS4DkuQnyjMwiQPKvQuBYBDmb8H7zx8ki7nVh4HJQOdVWebyvLE0qt+clruxA==} + engines: {node: '>=18'} + inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. @@ -3935,6 +3982,22 @@ packages: resolution: {integrity: sha512-3YZcUUR2Wt1WsapF+S/WiA2WmlW0cWAoPccMqne7AxEBhCdFeTPjfv/Axb8V2gyCgY3nRw+ksZ3xSUX+R47iAg==} engines: {node: ^18.17 || >=20.6.1} + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-lib-source-maps@5.0.6: + resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} + engines: {node: '>=10'} + + istanbul-reports@3.1.7: + resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + engines: {node: '>=8'} + jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} @@ -4855,6 +4918,10 @@ packages: resolution: {integrity: sha512-rum1bPifK5SSar35Z6EKZuYPJx85pkNaFrxBK3mwdfSJ1/WKbYrjoW/zTPSjRRamfmVX1ACBIdFAO0VRErW/EA==} engines: {node: '>=18'} + parse-json@8.2.0: + resolution: {integrity: sha512-eONBZy4hm2AgxjNFd8a4nyDJnzUAH0g34xSQAwWEVGCjdZ4ZL7dKZBfq267GWP/JaS9zW62Xs2FeAdDvpHHJGQ==} + engines: {node: '>=18'} + parse-ms@3.0.0: resolution: {integrity: sha512-Tpb8Z7r7XbbtBTrM9UhpkzzaMrqA2VXMT3YChzYltwV3P3pM6t8wl7TvpMnSTosz1aQAdVib7kdoys7vYOPerw==} engines: {node: '>=12'} @@ -5101,8 +5168,8 @@ packages: resolution: {integrity: sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==} engines: {node: '>=0.6'} - quansync@0.2.8: - resolution: {integrity: sha512-4+saucphJMazjt7iOM27mbFCk+D9dd/zmgMDCzRZ8MEoBfYp7lAvoN38et/phRQF6wOPMy/OROBGgoWeSKyluA==} + quansync@0.2.10: + resolution: {integrity: sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A==} queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -5794,6 +5861,10 @@ packages: engines: {node: '>=10'} hasBin: true + test-exclude@7.0.1: + resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} + engines: {node: '>=18'} + text-decoder@1.2.3: resolution: {integrity: sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==} @@ -6031,8 +6102,8 @@ packages: resolution: {integrity: sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==} engines: {node: '>=14.0.0'} - unplugin@2.2.0: - resolution: {integrity: sha512-m1ekpSwuOT5hxkJeZGRxO7gXbXT3gF26NjQ7GdVHoLoF8/nopLcd/QfPigpCy7i51oFHiRJg/CyHhj4vs2+KGw==} + unplugin@2.2.2: + resolution: {integrity: sha512-Qp+iiD+qCRnUek+nDoYvtWX7tfnYyXsrOnJ452FRTgOyKmTM7TUJ3l+PLPJOOWPTUyKISKp4isC5JJPSXUjGgw==} engines: {node: '>=18.12.0'} unstorage@1.15.0: @@ -6252,9 +6323,17 @@ packages: webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + webpack-virtual-modules@0.6.2: resolution: {integrity: sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==} + whatwg-mimetype@3.0.0: + resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} + engines: {node: '>=12'} + whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} @@ -6442,6 +6521,11 @@ packages: snapshots: + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + '@babel/code-frame@7.26.2': dependencies: '@babel/helper-validator-identifier': 7.25.9 @@ -6452,15 +6536,26 @@ snapshots: '@babel/helper-validator-identifier@7.25.9': {} + '@babel/parser@7.26.10': + dependencies: + '@babel/types': 7.26.10 + '@babel/parser@7.26.9': dependencies: '@babel/types': 7.26.9 + '@babel/types@7.26.10': + dependencies: + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/types@7.26.9': dependencies: '@babel/helper-string-parser': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 + '@bcoe/v8-coverage@1.0.2': {} + '@bugsnag/browser@7.25.0': dependencies: '@bugsnag/core': 7.25.0 @@ -7063,6 +7158,8 @@ snapshots: dependencies: minipass: 7.1.2 + '@istanbuljs/schema@0.1.3': {} + '@jest/types@27.5.1': dependencies: '@types/istanbul-lib-coverage': 2.0.6 @@ -7685,7 +7782,7 @@ snapshots: '@redocly/config@0.22.1': {} - '@redocly/openapi-core@1.33.0(supports-color@9.4.0)': + '@redocly/openapi-core@1.34.0(supports-color@9.4.0)': dependencies: '@redocly/ajv': 8.11.2 '@redocly/config': 0.22.1 @@ -8035,6 +8132,24 @@ snapshots: - rollup - supports-color + '@vitest/coverage-v8@3.0.8(vitest@3.0.8(@types/node@22.13.10)(happy-dom@17.4.4)(jiti@2.4.2)(terser@5.39.0)(yaml@2.7.0))': + dependencies: + '@ampproject/remapping': 2.3.0 + '@bcoe/v8-coverage': 1.0.2 + debug: 4.4.0(supports-color@9.4.0) + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6 + istanbul-reports: 3.1.7 + magic-string: 0.30.17 + magicast: 0.3.5 + std-env: 3.8.1 + test-exclude: 7.0.1 + tinyrainbow: 2.0.0 + vitest: 3.0.8(@types/node@22.13.10)(happy-dom@17.4.4)(jiti@2.4.2)(terser@5.39.0)(yaml@2.7.0) + transitivePeerDependencies: + - supports-color + '@vitest/expect@3.0.8': dependencies: '@vitest/spy': 3.0.8 @@ -10057,6 +10172,11 @@ snapshots: optionalDependencies: uglify-js: 2.8.29 + happy-dom@17.4.4: + dependencies: + webidl-conversions: 7.0.0 + whatwg-mimetype: 3.0.0 + has-flag@3.0.0: {} has-flag@4.0.0: {} @@ -10085,6 +10205,8 @@ snapshots: optionalDependencies: unix-dgram: 2.0.6 + html-escaper@2.0.2: {} + http-cache-semantics@4.1.1: {} http-errors@1.6.2: @@ -10206,6 +10328,8 @@ snapshots: index-to-position@0.1.2: {} + index-to-position@1.0.0: {} + inflight@1.0.6: dependencies: once: 1.4.0 @@ -10451,6 +10575,27 @@ snapshots: lodash.isstring: 4.0.1 lodash.uniqby: 4.7.0 + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-lib-source-maps@5.0.6: + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + debug: 4.4.0(supports-color@9.4.0) + istanbul-lib-coverage: 3.2.2 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.1.7: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + jackspeak@3.4.3: dependencies: '@isaacs/cliui': 8.0.2 @@ -10620,7 +10765,7 @@ snapshots: dependencies: mlly: 1.7.4 pkg-types: 2.1.0 - quansync: 0.2.8 + quansync: 0.2.10 locate-path@6.0.0: dependencies: @@ -10736,8 +10881,8 @@ snapshots: magicast@0.3.5: dependencies: - '@babel/parser': 7.26.9 - '@babel/types': 7.26.9 + '@babel/parser': 7.26.10 + '@babel/types': 7.26.10 source-map-js: 1.2.1 make-dir@3.1.0: @@ -11231,7 +11376,7 @@ snapshots: node-source-walk@6.0.2: dependencies: - '@babel/parser': 7.26.9 + '@babel/parser': 7.26.10 node-stream-zip@1.15.0: {} @@ -11297,7 +11442,7 @@ snapshots: nypm@0.3.12: dependencies: citty: 0.1.6 - consola: 3.4.0 + consola: 3.4.2 execa: 8.0.1 pathe: 1.1.2 pkg-types: 1.3.1 @@ -11374,10 +11519,10 @@ snapshots: openapi-typescript@7.6.1(typescript@5.8.2): dependencies: - '@redocly/openapi-core': 1.33.0(supports-color@9.4.0) + '@redocly/openapi-core': 1.34.0(supports-color@9.4.0) ansi-colors: 4.1.3 change-case: 5.4.4 - parse-json: 8.1.0 + parse-json: 8.2.0 supports-color: 9.4.0 typescript: 5.8.2 yargs-parser: 21.1.1 @@ -11580,6 +11725,12 @@ snapshots: index-to-position: 0.1.2 type-fest: 4.37.0 + parse-json@8.2.0: + dependencies: + '@babel/code-frame': 7.26.2 + index-to-position: 1.0.0 + type-fest: 4.37.0 + parse-ms@3.0.0: {} parse-ms@4.0.0: {} @@ -11824,7 +11975,7 @@ snapshots: dependencies: side-channel: 1.1.0 - quansync@0.2.8: {} + quansync@0.2.10: {} queue-microtask@1.2.3: {} @@ -12655,6 +12806,12 @@ snapshots: commander: 2.20.3 source-map-support: 0.5.21 + test-exclude@7.0.1: + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 10.4.5 + minimatch: 9.0.5 + text-decoder@1.2.3: dependencies: b4a: 1.6.7 @@ -12817,7 +12974,7 @@ snapshots: acorn: 8.14.1 estree-walker: 3.0.3 magic-string: 0.30.17 - unplugin: 2.2.0 + unplugin: 2.2.2 undici-types@6.20.0: {} @@ -12857,7 +13014,7 @@ snapshots: scule: 1.3.0 strip-literal: 3.0.0 tinyglobby: 0.2.12 - unplugin: 2.2.0 + unplugin: 2.2.2 unplugin-utils: 0.2.4 unique-string@3.0.0: @@ -12890,7 +13047,7 @@ snapshots: acorn: 8.14.1 webpack-virtual-modules: 0.6.2 - unplugin@2.2.0: + unplugin@2.2.2: dependencies: acorn: 8.14.1 webpack-virtual-modules: 0.6.2 @@ -13019,7 +13176,7 @@ snapshots: terser: 5.39.0 yaml: 2.7.0 - vitest@3.0.8(@types/node@22.13.10)(jiti@2.4.2)(terser@5.39.0)(yaml@2.7.0): + vitest@3.0.8(@types/node@22.13.10)(happy-dom@17.4.4)(jiti@2.4.2)(terser@5.39.0)(yaml@2.7.0): dependencies: '@vitest/expect': 3.0.8 '@vitest/mocker': 3.0.8(vite@6.2.1(@types/node@22.13.10)(jiti@2.4.2)(terser@5.39.0)(yaml@2.7.0)) @@ -13043,6 +13200,7 @@ snapshots: why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.13.10 + happy-dom: 17.4.4 transitivePeerDependencies: - jiti - less @@ -13075,8 +13233,12 @@ snapshots: webidl-conversions@3.0.1: {} + webidl-conversions@7.0.0: {} + webpack-virtual-modules@0.6.2: {} + whatwg-mimetype@3.0.0: {} + whatwg-url@5.0.0: dependencies: tr46: 0.0.3 diff --git a/src/WebComponent.test.mjs b/src/WebComponent.test.mjs new file mode 100644 index 0000000..49406f4 --- /dev/null +++ b/src/WebComponent.test.mjs @@ -0,0 +1,25 @@ +import { beforeEach, describe, expect, it } from 'vitest' +import { WebComponent } from './WebComponent.js' + +let componentUnderTest + +describe('WebComponent', () => { + // Browsers throw an error when you instantiate a custom element class not in the registry + window.customElements.define('component-test', WebComponent) + + beforeEach(() => { + componentUnderTest = new WebComponent() + }) + + it('is instantiated', () => { + expect(componentUnderTest).toBeDefined() + }) + + it('has a readonly template prop', () => { + expect(componentUnderTest.template).toBe('') + const assignToReadonly = () => { + componentUnderTest.template = 'should error' + } + expect(() => assignToReadonly()).toThrowError() + }) +}) diff --git a/src/utils/serialize.test.mjs b/src/utils/serialize.test.mjs new file mode 100644 index 0000000..570455a --- /dev/null +++ b/src/utils/serialize.test.mjs @@ -0,0 +1,27 @@ +import { describe, expect, test } from 'vitest' +import { serialize } from './serialize.mjs' + +describe('serialize', () => { + test('should stringify number', () => { + const result = serialize(3) + expect(result).toBeTypeOf('string') + expect(result).toEqual('3') + }) + + test('should stringify boolean', () => { + const result = serialize(false) + expect(result).toBeTypeOf('string') + expect(result).toEqual('false') + }) + + test('should stringify object', () => { + const result = serialize({ hello: 'world' }) + expect(result).toBeTypeOf('string') + expect(result).toEqual('{"hello":"world"}') + }) + + test('should return undefined', () => { + const result = serialize(undefined) + expect(result).toBeUndefined() + }) +}) diff --git a/vitest.config.mjs b/vitest.config.mjs new file mode 100644 index 0000000..4f5e69e --- /dev/null +++ b/vitest.config.mjs @@ -0,0 +1,13 @@ +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + environment: 'happy-dom', + coverage: { + enabled: true, + provider: 'v8', + reporter: ['html', 'text'], + include: ['src'], + }, + }, +})