add test for Location component

This commit is contained in:
pa
2026-02-12 16:49:54 +09:00
parent 6c6f2211cd
commit b12c3d679b
5 changed files with 1176 additions and 3 deletions

768
package-lock.json generated
View File

@@ -20,6 +20,7 @@
"@fontsource-variable/noto-sans-tc": "^5.2.10",
"@internationalized/date": "^3.11.0",
"@kamiya4047/eslint-plugin-pretty-import": "^0.1.6",
"@pinia/testing": "^1.0.3",
"@sentry/vite-plugin": "^4.9.1",
"@sentry/vue": "^10.38.0",
"@sigma/edge-curve": "^3.1.0",
@@ -31,6 +32,7 @@
"@vee-validate/zod": "^4.15.1",
"@vitejs/plugin-vue": "^6.0.4",
"@vitejs/plugin-vue-jsx": "^5.1.4",
"@vue/test-utils": "^2.4.6",
"@vueuse/core": "^14.2.1",
"animate.css": "^4.1.1",
"babel-runtime": "^6.26.0",
@@ -51,6 +53,7 @@
"graphology-communities-louvain": "^2.0.2",
"graphology-layout-forceatlas2": "^0.10.1",
"graphology-layout-noverlap": "^0.4.2",
"jsdom": "^28.0.0",
"lightningcss": "^1.31.1",
"lucide-vue-next": "^0.562.0",
"noty": "^3.2.0-beta-deprecated",
@@ -82,6 +85,68 @@
"npm": ">=11.5.0"
}
},
"node_modules/@acemir/cssom": {
"version": "0.9.31",
"resolved": "https://registry.npmjs.org/@acemir/cssom/-/cssom-0.9.31.tgz",
"integrity": "sha512-ZnR3GSaH+/vJ0YlHau21FjfLYjMpYVIzTD8M8vIEQvIGxeOXyXdzCI140rrCY862p/C/BbzWsjc1dgnM9mkoTA==",
"dev": true,
"license": "MIT"
},
"node_modules/@asamuzakjp/css-color": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-4.1.2.tgz",
"integrity": "sha512-NfBUvBaYgKIuq6E/RBLY1m0IohzNHAYyaJGuTK79Z23uNwmz2jl1mPsC5ZxCCxylinKhT1Amn5oNTlx1wN8cQg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@csstools/css-calc": "^3.0.0",
"@csstools/css-color-parser": "^4.0.1",
"@csstools/css-parser-algorithms": "^4.0.0",
"@csstools/css-tokenizer": "^4.0.0",
"lru-cache": "^11.2.5"
}
},
"node_modules/@asamuzakjp/css-color/node_modules/lru-cache": {
"version": "11.2.6",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz",
"integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==",
"dev": true,
"license": "BlueOak-1.0.0",
"engines": {
"node": "20 || >=22"
}
},
"node_modules/@asamuzakjp/dom-selector": {
"version": "6.7.8",
"resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-6.7.8.tgz",
"integrity": "sha512-stisC1nULNc9oH5lakAj8MH88ZxeGxzyWNDfbdCxvJSJIvDsHNZqYvscGTgy/ysgXWLJPt6K/4t0/GjvtKcFJQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@asamuzakjp/nwsapi": "^2.3.9",
"bidi-js": "^1.0.3",
"css-tree": "^3.1.0",
"is-potential-custom-element-name": "^1.0.1",
"lru-cache": "^11.2.5"
}
},
"node_modules/@asamuzakjp/dom-selector/node_modules/lru-cache": {
"version": "11.2.6",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz",
"integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==",
"dev": true,
"license": "BlueOak-1.0.0",
"engines": {
"node": "20 || >=22"
}
},
"node_modules/@asamuzakjp/nwsapi": {
"version": "2.3.9",
"resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz",
"integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==",
"dev": true,
"license": "MIT"
},
"node_modules/@babel/code-frame": {
"version": "7.29.0",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
@@ -525,6 +590,138 @@
"dev": true,
"license": "(Apache-2.0 AND BSD-3-Clause)"
},
"node_modules/@csstools/color-helpers": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.0.1.tgz",
"integrity": "sha512-NmXRccUJMk2AWA5A7e5a//3bCIMyOu2hAtdRYrhPPHjDxINuCwX1w6rnIZ4xjLcp0ayv6h8Pc3X0eJUGiAAXHQ==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/csstools"
},
{
"type": "opencollective",
"url": "https://opencollective.com/csstools"
}
],
"license": "MIT-0",
"engines": {
"node": ">=20.19.0"
}
},
"node_modules/@csstools/css-calc": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.0.1.tgz",
"integrity": "sha512-bsDKIP6f4ta2DO9t+rAbSSwv4EMESXy5ZIvzQl1afmD6Z1XHkVu9ijcG9QR/qSgQS1dVa+RaQ/MfQ7FIB/Dn1Q==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/csstools"
},
{
"type": "opencollective",
"url": "https://opencollective.com/csstools"
}
],
"license": "MIT",
"engines": {
"node": ">=20.19.0"
},
"peerDependencies": {
"@csstools/css-parser-algorithms": "^4.0.0",
"@csstools/css-tokenizer": "^4.0.0"
}
},
"node_modules/@csstools/css-color-parser": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.0.1.tgz",
"integrity": "sha512-vYwO15eRBEkeF6xjAno/KQ61HacNhfQuuU/eGwH67DplL0zD5ZixUa563phQvUelA07yDczIXdtmYojCphKJcw==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/csstools"
},
{
"type": "opencollective",
"url": "https://opencollective.com/csstools"
}
],
"license": "MIT",
"dependencies": {
"@csstools/color-helpers": "^6.0.1",
"@csstools/css-calc": "^3.0.0"
},
"engines": {
"node": ">=20.19.0"
},
"peerDependencies": {
"@csstools/css-parser-algorithms": "^4.0.0",
"@csstools/css-tokenizer": "^4.0.0"
}
},
"node_modules/@csstools/css-parser-algorithms": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz",
"integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/csstools"
},
{
"type": "opencollective",
"url": "https://opencollective.com/csstools"
}
],
"license": "MIT",
"engines": {
"node": ">=20.19.0"
},
"peerDependencies": {
"@csstools/css-tokenizer": "^4.0.0"
}
},
"node_modules/@csstools/css-syntax-patches-for-csstree": {
"version": "1.0.27",
"resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.0.27.tgz",
"integrity": "sha512-sxP33Jwg1bviSUXAV43cVYdmjt2TLnLXNqCWl9xmxHawWVjGz/kEbdkr7F9pxJNBN2Mh+dq0crgItbW6tQvyow==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/csstools"
},
{
"type": "opencollective",
"url": "https://opencollective.com/csstools"
}
],
"license": "MIT-0"
},
"node_modules/@csstools/css-tokenizer": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz",
"integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/csstools"
},
{
"type": "opencollective",
"url": "https://opencollective.com/csstools"
}
],
"license": "MIT",
"engines": {
"node": ">=20.19.0"
}
},
"node_modules/@develar/schema-utils": {
"version": "2.6.5",
"resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz",
@@ -1761,6 +1958,24 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@exodus/bytes": {
"version": "1.14.0",
"resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.14.0.tgz",
"integrity": "sha512-YiY1OmY6Qhkvmly8vZiD8wZRpW/npGZNg+0Sk8mstxirRHCg6lolHt5tSODCfuNPE/fBsAqRwDJE417x7jDDHA==",
"dev": true,
"license": "MIT",
"engines": {
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
},
"peerDependencies": {
"@noble/hashes": "^1.8.0 || ^2.0.0"
},
"peerDependenciesMeta": {
"@noble/hashes": {
"optional": true
}
}
},
"node_modules/@floating-ui/core": {
"version": "1.7.3",
"resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz",
@@ -2282,6 +2497,13 @@
"node": "^18.17.0 || >=20.5.0"
}
},
"node_modules/@one-ini/wasm": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz",
"integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==",
"dev": true,
"license": "MIT"
},
"node_modules/@parcel/watcher": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz",
@@ -2614,6 +2836,19 @@
"license": "MIT",
"optional": true
},
"node_modules/@pinia/testing": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@pinia/testing/-/testing-1.0.3.tgz",
"integrity": "sha512-g+qR49GNdI1Z8rZxKrQC3GN+LfnGTNf5Kk8Nz5Cz6mIGva5WRS+ffPXQfzhA0nu6TveWzPNYTjGl4nJqd3Cu9Q==",
"dev": true,
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/posva"
},
"peerDependencies": {
"pinia": ">=3.0.4"
}
},
"node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
@@ -4552,6 +4787,17 @@
"dev": true,
"license": "MIT"
},
"node_modules/@vue/test-utils": {
"version": "2.4.6",
"resolved": "https://registry.npmjs.org/@vue/test-utils/-/test-utils-2.4.6.tgz",
"integrity": "sha512-FMxEjOpYNYiFe0GkaHsnJPXFHxQ6m4t8vI/ElPGpMWxZKpmRvQ33OIrvRXemy6yha03RxhOlQuy+gZMC3CQSow==",
"dev": true,
"license": "MIT",
"dependencies": {
"js-beautify": "^1.14.9",
"vue-component-type-helpers": "^2.0.0"
}
},
"node_modules/@vueuse/core": {
"version": "14.2.1",
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-14.2.1.tgz",
@@ -5051,6 +5297,16 @@
"baseline-browser-mapping": "dist/cli.js"
}
},
"node_modules/bidi-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz",
"integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==",
"dev": true,
"license": "MIT",
"dependencies": {
"require-from-string": "^2.0.2"
}
},
"node_modules/binary-extensions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
@@ -5758,6 +6014,17 @@
"dev": true,
"license": "MIT"
},
"node_modules/config-chain": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
"integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"ini": "^1.3.4",
"proto-list": "~1.2.1"
}
},
"node_modules/convert-source-map": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
@@ -5851,6 +6118,20 @@
"node": ">= 8"
}
},
"node_modules/css-tree": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz",
"integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==",
"dev": true,
"license": "MIT",
"dependencies": {
"mdn-data": "2.12.2",
"source-map-js": "^1.0.1"
},
"engines": {
"node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
}
},
"node_modules/cssesc": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
@@ -5864,6 +6145,32 @@
"node": ">=4"
}
},
"node_modules/cssstyle": {
"version": "5.3.7",
"resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-5.3.7.tgz",
"integrity": "sha512-7D2EPVltRrsTkhpQmksIu+LxeWAIEk6wRDMJ1qljlv+CKHJM+cJLlfhWIzNA44eAsHXSNe3+vO6DW1yCYx8SuQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@asamuzakjp/css-color": "^4.1.1",
"@csstools/css-syntax-patches-for-csstree": "^1.0.21",
"css-tree": "^3.1.0",
"lru-cache": "^11.2.4"
},
"engines": {
"node": ">=20"
}
},
"node_modules/cssstyle/node_modules/lru-cache": {
"version": "11.2.6",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.6.tgz",
"integrity": "sha512-ESL2CrkS/2wTPfuend7Zhkzo2u0daGJ/A2VucJOgQ/C48S/zB8MMeMHSGKYpXhIjbPxfuezITkaBH1wqv00DDQ==",
"dev": true,
"license": "BlueOak-1.0.0",
"engines": {
"node": "20 || >=22"
}
},
"node_modules/csstype": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
@@ -5871,6 +6178,58 @@
"dev": true,
"license": "MIT"
},
"node_modules/data-urls": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz",
"integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==",
"dev": true,
"license": "MIT",
"dependencies": {
"whatwg-mimetype": "^5.0.0",
"whatwg-url": "^16.0.0"
},
"engines": {
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
}
},
"node_modules/data-urls/node_modules/tr46": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz",
"integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==",
"dev": true,
"license": "MIT",
"dependencies": {
"punycode": "^2.3.1"
},
"engines": {
"node": ">=20"
}
},
"node_modules/data-urls/node_modules/webidl-conversions": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz",
"integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==",
"dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=20"
}
},
"node_modules/data-urls/node_modules/whatwg-url": {
"version": "16.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-16.0.0.tgz",
"integrity": "sha512-9CcxtEKsf53UFwkSUZjG+9vydAsFO4lFHBpJUtjBcoJOCJpKnSJNwCw813zrYJHpCJ7sgfbtOe0V5Ku7Pa1XMQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@exodus/bytes": "^1.11.0",
"tr46": "^6.0.0",
"webidl-conversions": "^8.0.1"
},
"engines": {
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
}
},
"node_modules/dayjs": {
"version": "1.11.19",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz",
@@ -5896,6 +6255,13 @@
}
}
},
"node_modules/decimal.js": {
"version": "10.6.0",
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz",
"integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==",
"dev": true,
"license": "MIT"
},
"node_modules/decompress-response": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
@@ -6206,6 +6572,61 @@
"zrender": "6.0.0"
}
},
"node_modules/editorconfig": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz",
"integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"@one-ini/wasm": "0.1.1",
"commander": "^10.0.0",
"minimatch": "9.0.1",
"semver": "^7.5.3"
},
"bin": {
"editorconfig": "bin/editorconfig"
},
"engines": {
"node": ">=14"
}
},
"node_modules/editorconfig/node_modules/brace-expansion": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/editorconfig/node_modules/commander": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
"integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=14"
}
},
"node_modules/editorconfig/node_modules/minimatch": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz",
"integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==",
"dev": true,
"license": "ISC",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/ejs": {
"version": "3.1.10",
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
@@ -7780,6 +8201,19 @@
"dev": true,
"license": "ISC"
},
"node_modules/html-encoding-sniffer": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz",
"integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@exodus/bytes": "^1.6.0"
},
"engines": {
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
}
},
"node_modules/http-cache-semantics": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
@@ -7967,6 +8401,13 @@
"dev": true,
"license": "ISC"
},
"node_modules/ini": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
"dev": true,
"license": "ISC"
},
"node_modules/ip-address": {
"version": "10.1.0",
"resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz",
@@ -8043,6 +8484,13 @@
"node": ">=0.12.0"
}
},
"node_modules/is-potential-custom-element-name": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
"integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
"dev": true,
"license": "MIT"
},
"node_modules/is-unicode-supported": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
@@ -8133,6 +8581,64 @@
"jiti": "lib/jiti-cli.mjs"
}
},
"node_modules/js-beautify": {
"version": "1.15.4",
"resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.4.tgz",
"integrity": "sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==",
"dev": true,
"license": "MIT",
"dependencies": {
"config-chain": "^1.1.13",
"editorconfig": "^1.0.4",
"glob": "^10.4.2",
"js-cookie": "^3.0.5",
"nopt": "^7.2.1"
},
"bin": {
"css-beautify": "js/bin/css-beautify.js",
"html-beautify": "js/bin/html-beautify.js",
"js-beautify": "js/bin/js-beautify.js"
},
"engines": {
"node": ">=14"
}
},
"node_modules/js-beautify/node_modules/abbrev": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz",
"integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==",
"dev": true,
"license": "ISC",
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/js-beautify/node_modules/nopt": {
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz",
"integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==",
"dev": true,
"license": "ISC",
"dependencies": {
"abbrev": "^2.0.0"
},
"bin": {
"nopt": "bin/nopt.js"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/js-cookie": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz",
"integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=14"
}
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -8153,6 +8659,108 @@
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/jsdom": {
"version": "28.0.0",
"resolved": "https://registry.npmjs.org/jsdom/-/jsdom-28.0.0.tgz",
"integrity": "sha512-KDYJgZ6T2TKdU8yBfYueq5EPG/EylMsBvCaenWMJb2OXmjgczzwveRCoJ+Hgj1lXPDyasvrgneSn4GBuR1hYyA==",
"dev": true,
"license": "MIT",
"dependencies": {
"@acemir/cssom": "^0.9.31",
"@asamuzakjp/dom-selector": "^6.7.6",
"@exodus/bytes": "^1.11.0",
"cssstyle": "^5.3.7",
"data-urls": "^7.0.0",
"decimal.js": "^10.6.0",
"html-encoding-sniffer": "^6.0.0",
"http-proxy-agent": "^7.0.2",
"https-proxy-agent": "^7.0.6",
"is-potential-custom-element-name": "^1.0.1",
"parse5": "^8.0.0",
"saxes": "^6.0.0",
"symbol-tree": "^3.2.4",
"tough-cookie": "^6.0.0",
"undici": "^7.20.0",
"w3c-xmlserializer": "^5.0.0",
"webidl-conversions": "^8.0.1",
"whatwg-mimetype": "^5.0.0",
"whatwg-url": "^16.0.0",
"xml-name-validator": "^5.0.0"
},
"engines": {
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
},
"peerDependencies": {
"canvas": "^3.0.0"
},
"peerDependenciesMeta": {
"canvas": {
"optional": true
}
}
},
"node_modules/jsdom/node_modules/https-proxy-agent": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz",
"integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==",
"dev": true,
"license": "MIT",
"dependencies": {
"agent-base": "^7.1.2",
"debug": "4"
},
"engines": {
"node": ">= 14"
}
},
"node_modules/jsdom/node_modules/tr46": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz",
"integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==",
"dev": true,
"license": "MIT",
"dependencies": {
"punycode": "^2.3.1"
},
"engines": {
"node": ">=20"
}
},
"node_modules/jsdom/node_modules/webidl-conversions": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz",
"integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==",
"dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=20"
}
},
"node_modules/jsdom/node_modules/whatwg-url": {
"version": "16.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-16.0.0.tgz",
"integrity": "sha512-9CcxtEKsf53UFwkSUZjG+9vydAsFO4lFHBpJUtjBcoJOCJpKnSJNwCw813zrYJHpCJ7sgfbtOe0V5Ku7Pa1XMQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@exodus/bytes": "^1.11.0",
"tr46": "^6.0.0",
"webidl-conversions": "^8.0.1"
},
"engines": {
"node": "^20.19.0 || ^22.12.0 || >=24.0.0"
}
},
"node_modules/jsdom/node_modules/xml-name-validator": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz",
"integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==",
"dev": true,
"license": "Apache-2.0",
"engines": {
"node": ">=18"
}
},
"node_modules/jsesc": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
@@ -8654,6 +9262,13 @@
"node": ">= 0.4"
}
},
"node_modules/mdn-data": {
"version": "2.12.2",
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz",
"integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==",
"dev": true,
"license": "CC0-1.0"
},
"node_modules/micromatch": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
@@ -9355,6 +9970,32 @@
"node": ">=6"
}
},
"node_modules/parse5": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.0.tgz",
"integrity": "sha512-9m4m5GSgXjL4AjumKzq1Fgfp3Z8rsvjRNbnkVwfu2ImRqE5D0LnY2QfDen18FSY9C573YU5XxSapdHZTZ2WolA==",
"dev": true,
"license": "MIT",
"dependencies": {
"entities": "^6.0.0"
},
"funding": {
"url": "https://github.com/inikulin/parse5?sponsor=1"
}
},
"node_modules/parse5/node_modules/entities": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
"integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
"dev": true,
"license": "BSD-2-Clause",
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -9677,6 +10318,13 @@
"dev": true,
"license": "ISC"
},
"node_modules/proto-list": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
"integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==",
"dev": true,
"license": "ISC"
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
@@ -9807,6 +10455,16 @@
"node": ">=0.10.0"
}
},
"node_modules/require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/resedit": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/resedit/-/resedit-1.7.2.tgz",
@@ -10440,6 +11098,19 @@
"node": ">=11.0.0"
}
},
"node_modules/saxes": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
"integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
"dev": true,
"license": "ISC",
"dependencies": {
"xmlchars": "^2.2.0"
},
"engines": {
"node": ">=v12.22.7"
}
},
"node_modules/semver": {
"version": "7.7.3",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
@@ -10928,6 +11599,13 @@
"node": ">=8"
}
},
"node_modules/symbol-tree": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
"integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
"dev": true,
"license": "MIT"
},
"node_modules/sync-child-process": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/sync-child-process/-/sync-child-process-1.0.2.tgz",
@@ -11202,6 +11880,26 @@
"node": ">=14.0.0"
}
},
"node_modules/tldts": {
"version": "7.0.23",
"resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.23.tgz",
"integrity": "sha512-ASdhgQIBSay0R/eXggAkQ53G4nTJqTXqC2kbaBbdDwM7SkjyZyO0OaaN1/FH7U/yCeqOHDwFO5j8+Os/IS1dXw==",
"dev": true,
"license": "MIT",
"dependencies": {
"tldts-core": "^7.0.23"
},
"bin": {
"tldts": "bin/cli.js"
}
},
"node_modules/tldts-core": {
"version": "7.0.23",
"resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.23.tgz",
"integrity": "sha512-0g9vrtDQLrNIiCj22HSe9d4mLVG3g5ph5DZ8zCKBr4OtrspmNB6ss7hVyzArAeE88ceZocIEGkyW1Ime7fxPtQ==",
"dev": true,
"license": "MIT"
},
"node_modules/tmp": {
"version": "0.2.5",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz",
@@ -11235,6 +11933,19 @@
"node": ">=8.0"
}
},
"node_modules/tough-cookie": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.0.tgz",
"integrity": "sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==",
"dev": true,
"license": "BSD-3-Clause",
"dependencies": {
"tldts": "^7.0.5"
},
"engines": {
"node": ">=16"
}
},
"node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
@@ -11297,6 +12008,16 @@
"node": ">=14.17"
}
},
"node_modules/undici": {
"version": "7.21.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-7.21.0.tgz",
"integrity": "sha512-Hn2tCQpoDt1wv23a68Ctc8Cr/BHpUSfaPYrkajTXOS9IKpxVRx/X5m1K2YkbK2ipgZgxXSgsUinl3x+2YdSSfg==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=20.18.1"
}
},
"node_modules/undici-types": {
"version": "7.16.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
@@ -11756,6 +12477,13 @@
}
}
},
"node_modules/vue-component-type-helpers": {
"version": "2.2.12",
"resolved": "https://registry.npmjs.org/vue-component-type-helpers/-/vue-component-type-helpers-2.2.12.tgz",
"integrity": "sha512-YbGqHZ5/eW4SnkPNR44mKVc6ZKQoRs/Rux1sxC6rdwXb4qpbOSYfDr9DsTHolOTGmIKgM9j141mZbBeg05R1pw==",
"dev": true,
"license": "MIT"
},
"node_modules/vue-eslint-parser": {
"version": "9.4.3",
"resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz",
@@ -11955,6 +12683,29 @@
}
}
},
"node_modules/w3c-xmlserializer": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz",
"integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==",
"dev": true,
"license": "MIT",
"dependencies": {
"xml-name-validator": "^5.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/w3c-xmlserializer/node_modules/xml-name-validator": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz",
"integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==",
"dev": true,
"license": "Apache-2.0",
"engines": {
"node": ">=18"
}
},
"node_modules/wcwidth": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
@@ -11989,6 +12740,16 @@
"dev": true,
"license": "MIT"
},
"node_modules/whatwg-mimetype": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz",
"integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=20"
}
},
"node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
@@ -12247,6 +13008,13 @@
"node": ">=8.0"
}
},
"node_modules/xmlchars": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
"dev": true,
"license": "MIT"
},
"node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",

View File

@@ -40,6 +40,7 @@
"@fontsource-variable/noto-sans-tc": "^5.2.10",
"@internationalized/date": "^3.11.0",
"@kamiya4047/eslint-plugin-pretty-import": "^0.1.6",
"@pinia/testing": "^1.0.3",
"@sentry/vite-plugin": "^4.9.1",
"@sentry/vue": "^10.38.0",
"@sigma/edge-curve": "^3.1.0",
@@ -51,6 +52,7 @@
"@vee-validate/zod": "^4.15.1",
"@vitejs/plugin-vue": "^6.0.4",
"@vitejs/plugin-vue-jsx": "^5.1.4",
"@vue/test-utils": "^2.4.6",
"@vueuse/core": "^14.2.1",
"animate.css": "^4.1.1",
"babel-runtime": "^6.26.0",
@@ -71,6 +73,7 @@
"graphology-communities-louvain": "^2.0.2",
"graphology-layout-forceatlas2": "^0.10.1",
"graphology-layout-noverlap": "^0.4.2",
"jsdom": "^28.0.0",
"lightningcss": "^1.31.1",
"lucide-vue-next": "^0.562.0",
"noty": "^3.2.0-beta-deprecated",

View File

@@ -0,0 +1,345 @@
import { beforeEach, describe, expect, test, vi } from 'vitest';
import { createI18n } from 'vue-i18n';
import { createTestingPinia } from '@pinia/testing';
import { mount } from '@vue/test-utils';
import { ref } from 'vue';
import { getGroupName } from '../../shared/utils/group';
import { getWorldName } from '../../shared/utils/world';
import Location from '../Location.vue';
import en from '../../localization/en.json';
vi.mock('../../views/Feed/Feed.vue', () => ({
default: { template: '<div />' }
}));
vi.mock('../../views/Feed/columns.jsx', () => ({
columns: []
}));
vi.mock('../../plugin/router', () => ({
router: {
beforeEach: vi.fn(),
push: vi.fn(),
replace: vi.fn(),
currentRoute: ref({ path: '/', name: '', meta: {} }),
isReady: vi.fn().mockResolvedValue(true)
},
initRouter: vi.fn()
}));
vi.mock('vue-router', async (importOriginal) => {
const actual = await importOriginal();
return {
...actual,
useRouter: vi.fn(() => ({
push: vi.fn(),
replace: vi.fn(),
currentRoute: ref({ path: '/', name: '', meta: {} })
}))
};
});
vi.mock('../../plugin/interopApi', () => ({
initInteropApi: vi.fn()
}));
vi.mock('../../service/database', () => ({
database: new Proxy(
{},
{
get: (_target, prop) => {
if (prop === '__esModule') return false;
return vi.fn().mockResolvedValue(null);
}
}
)
}));
vi.mock('../../service/config', () => ({
default: {
init: vi.fn(),
getString: vi
.fn()
.mockImplementation((_key, defaultValue) => defaultValue ?? '{}'),
setString: vi.fn(),
getBool: vi
.fn()
.mockImplementation((_key, defaultValue) => defaultValue ?? false),
setBool: vi.fn(),
getInt: vi
.fn()
.mockImplementation((_key, defaultValue) => defaultValue ?? 0),
setInt: vi.fn(),
getFloat: vi
.fn()
.mockImplementation((_key, defaultValue) => defaultValue ?? 0),
setFloat: vi.fn(),
getObject: vi.fn().mockReturnValue(null),
setObject: vi.fn(),
getArray: vi.fn().mockReturnValue([]),
setArray: vi.fn(),
remove: vi.fn()
}
}));
vi.mock('../../service/jsonStorage', () => ({
default: vi.fn()
}));
vi.mock('../../service/watchState', () => ({
watchState: { isLoggedIn: false }
}));
vi.mock('../../shared/utils/world', () => ({
getWorldName: vi.fn().mockResolvedValue(''),
isRpcWorld: vi.fn().mockReturnValue(false)
}));
vi.mock('../../shared/utils/group', () => ({
getGroupName: vi.fn().mockResolvedValue(''),
hasGroupPermission: vi.fn().mockReturnValue(false),
hasGroupModerationPermission: vi.fn().mockReturnValue(false)
}));
const mockedGetWorldName = vi.mocked(getWorldName);
const mockedGetGroupName = vi.mocked(getGroupName);
const i18n = createI18n({
locale: 'en',
fallbackLocale: 'en',
legacy: false,
globalInjection: false,
missingWarn: false,
fallbackWarn: false,
messages: { en }
});
const stubs = {
TooltipWrapper: {
template: '<span><slot /></span>',
props: [
'content',
'disabled',
'delayDuration',
'delay-duration',
'side'
]
},
Spinner: { template: '<span class="spinner" />' },
AlertTriangle: { template: '<span class="alert-triangle" />' }
};
function mountLocation(props = {}) {
return mount(Location, {
props,
global: {
plugins: [
i18n,
createTestingPinia({
stubActions: true,
initialState: {
Instance: {},
World: {},
Search: {},
AppearanceSettings: {
showInstanceIdInLocation: false
},
Group: {}
}
})
],
stubs
}
});
}
describe('Location.vue', () => {
beforeEach(() => {
vi.clearAllMocks();
});
describe('special location states', () => {
test('shows translated text for offline location', () => {
const wrapper = mountLocation({ location: 'offline' });
expect(wrapper.text()).toContain('Offline');
});
test('shows translated text for private location', () => {
const wrapper = mountLocation({ location: 'private' });
expect(wrapper.text()).toContain('Private');
});
test('shows spinner and destination world when traveling', () => {
const wrapper = mountLocation({
location: 'traveling',
traveling: 'wrld_12345:67890~region(us)'
});
expect(wrapper.find('.spinner').exists()).toBe(true);
expect(wrapper.text()).toContain('wrld_12345');
});
test('shows dash placeholder when location is empty', () => {
const wrapper = mountLocation({ location: '' });
const placeholder = wrapper.find('.transparent');
expect(placeholder.exists()).toBe(true);
});
});
describe('hint display', () => {
test('shows hint with access type for valid instance', () => {
const wrapper = mountLocation({
location: 'wrld_12345:67890',
hint: 'My World'
});
expect(wrapper.text()).toContain('My World');
expect(wrapper.text()).toContain('Public');
});
test('shows only hint text when no instanceId', () => {
const wrapper = mountLocation({
location: 'wrld_12345',
hint: 'Just World Name'
});
expect(wrapper.text()).toContain('Just World Name');
expect(wrapper.text()).not.toContain('Public');
});
});
describe('world ID display (no hint)', () => {
test('shows worldId when no hint and no cached world', () => {
const wrapper = mountLocation({
location: 'wrld_12345:67890'
});
expect(wrapper.text()).toContain('wrld_12345');
});
test('updates text after getWorldName resolves', async () => {
mockedGetWorldName.mockResolvedValueOnce('Amazing World');
const wrapper = mountLocation({
location: 'wrld_12345:67890'
});
expect(wrapper.text()).toContain('wrld_12345');
await vi.waitFor(() => {
expect(wrapper.text()).toContain('Amazing World');
});
});
});
describe('region flags', () => {
test('shows region flag for real instances', () => {
const wrapper = mountLocation({
location: 'wrld_12345:67890~region(eu)'
});
expect(wrapper.find('.flags.eu').exists()).toBe(true);
});
test('defaults to us region when no region specified', () => {
const wrapper = mountLocation({
location: 'wrld_12345:67890'
});
expect(wrapper.find('.flags.us').exists()).toBe(true);
});
test('does not show region for offline', () => {
const wrapper = mountLocation({ location: 'offline' });
expect(wrapper.find('.flags').exists()).toBe(false);
});
});
describe('group name', () => {
test('uses grouphint when provided', () => {
const wrapper = mountLocation({
location: 'wrld_12345:67890~group(grp_abc)',
grouphint: 'My Group'
});
expect(wrapper.text()).toContain('My Group');
});
test('calls getGroupName when no grouphint and has groupId', () => {
mountLocation({
location: 'wrld_12345:67890~group(grp_abc)'
});
expect(mockedGetGroupName).toHaveBeenCalled();
});
test('shows resolved group name after async fetch', async () => {
mockedGetGroupName.mockResolvedValueOnce('Community Group');
const wrapper = mountLocation({
location: 'wrld_12345:67890~group(grp_abc)'
});
await vi.waitFor(() => {
expect(wrapper.text()).toContain('Community Group');
});
});
});
describe('strict and closed indicators', () => {
test('shows lock icon for strict instances', async () => {
const wrapper = mountLocation({
location: 'wrld_12345:67890~strict'
});
await wrapper.vm.$nextTick();
expect(wrapper.find('.lucide-lock').exists()).toBe(true);
});
test('does not show lock for non-strict instances', () => {
const wrapper = mountLocation({
location: 'wrld_12345:67890'
});
expect(wrapper.find('.lucide-lock').exists()).toBe(false);
});
});
describe('translateAccessType', () => {
test('shows Public for public instances', () => {
const wrapper = mountLocation({
location: 'wrld_12345:67890',
hint: 'Test'
});
expect(wrapper.text()).toContain('Public');
});
test('shows Invite for private instances', () => {
const wrapper = mountLocation({
location: 'wrld_12345:67890~private(usr_123)',
hint: 'Test'
});
expect(wrapper.text()).toContain('Invite');
});
test('shows Friends+ for hidden instances', () => {
const wrapper = mountLocation({
location: 'wrld_12345:67890~hidden(usr_123)',
hint: 'Test'
});
expect(wrapper.text()).toContain('Friends+');
});
test('shows Group prefix for groupPublic instances', () => {
const wrapper = mountLocation({
location:
'wrld_12345:67890~group(grp_123)~groupAccessType(public)',
hint: 'Test'
});
const text = wrapper.text();
expect(text).toContain('Group');
expect(text).toContain('Public');
});
});
describe('reactivity', () => {
test('updates when location prop changes', async () => {
const wrapper = mountLocation({ location: 'offline' });
expect(wrapper.text()).toContain('Offline');
await wrapper.setProps({ location: 'private' });
expect(wrapper.text()).toContain('Private');
});
test('updates when hint prop changes', async () => {
const wrapper = mountLocation({
location: 'wrld_12345:67890',
hint: 'First Name'
});
expect(wrapper.text()).toContain('First Name');
await wrapper.setProps({ hint: 'Second Name' });
expect(wrapper.text()).toContain('Second Name');
});
});
});

View File

@@ -6,17 +6,23 @@ import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()],
define: {
NIGHTLY: JSON.stringify(false),
WINDOWS: JSON.stringify(true),
LINUX: JSON.stringify(false)
},
test: {
globals: true,
environment: 'node',
environment: 'jsdom',
setupFiles: ['./vitest.setup.js'],
include: ['src/**/*.{test,spec}.js'],
coverage: {
reporter: ['text', 'text-summary'],
include: ['src/shared/utils/**/*.js'],
include: ['src/shared/utils/**/*.js', 'src/components/**/*.vue'],
exclude: [
'src/shared/utils/**/*.test.js',
'src/shared/utils/**/__tests__/**'
'src/shared/utils/**/__tests__/**',
'src/components/**/__tests__/**'
]
}
},

View File

@@ -2,9 +2,60 @@
* Vitest global setup file.
* Loads English locale messages into i18n so that
* translation calls return expected values in tests.
*
* Provides global stubs for CefSharp IPC bindings.
*/
import { i18n } from './src/plugin/i18n';
import en from './src/localization/en.json';
const noopAsync = () => Promise.resolve('');
globalThis.AppApi = new Proxy({}, { get: () => noopAsync });
globalThis.WebApi = new Proxy({}, { get: () => noopAsync });
globalThis.VRCXStorage = new Proxy({}, { get: () => noopAsync });
globalThis.SQLite = new Proxy({}, { get: () => noopAsync });
globalThis.LogWatcher = new Proxy({}, { get: () => noopAsync });
globalThis.Discord = new Proxy({}, { get: () => noopAsync });
globalThis.AssetBundleManager = new Proxy({}, { get: () => noopAsync });
// Browser API stubs not available in jsdom
globalThis.speechSynthesis = {
getVoices: () => [],
cancel: () => {},
speak: () => {}
};
// matchMedia polyfill (standard jsdom workaround)
Object.defineProperty(window, 'matchMedia', {
writable: true,
value: vi.fn().mockImplementation((query) => ({
matches: false,
media: query,
onchange: null,
addListener: vi.fn(),
removeListener: vi.fn(),
addEventListener: vi.fn(),
removeEventListener: vi.fn(),
dispatchEvent: vi.fn()
}))
});
// Notification API stub
globalThis.Notification = class {
static permission = 'denied';
static requestPermission = vi.fn().mockResolvedValue('denied');
constructor() {}
close() {}
};
// Mock worker-timers to use native timers (workers unavailable in jsdom)
vi.mock('worker-timers', () => ({
setInterval: globalThis.setInterval.bind(globalThis),
clearInterval: globalThis.clearInterval.bind(globalThis),
setTimeout: globalThis.setTimeout.bind(globalThis),
clearTimeout: globalThis.clearTimeout.bind(globalThis)
}));
i18n.global.setLocaleMessage('en', en);