diff --git a/.prettierrc.json b/.oxfmtrc.json
similarity index 64%
rename from .prettierrc.json
rename to .oxfmtrc.json
index 54211b89..0eca6fbc 100644
--- a/.prettierrc.json
+++ b/.oxfmtrc.json
@@ -1,22 +1,15 @@
{
+ "$schema": "./node_modules/oxfmt/configuration_schema.json",
"printWidth": 80,
"tabWidth": 4,
"semi": true,
"singleQuote": true,
- "quoteProps": "as-needed",
"trailingComma": "none",
"bracketSpacing": true,
"arrowParens": "always",
- "endOfLine": "auto",
"overrides": [
{
- "files": "*.js",
- "options": {
- "parser": "meriyah"
- }
- },
- {
- "files": "*.vue",
+ "files": ["*.vue"],
"options": {
"printWidth": 120,
"bracketSameLine": true,
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index 6c600fb1..53754fa8 100644
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -3,8 +3,7 @@
"vue.volar",
"lokalise.i18n-ally",
"dbaeumer.vscode-eslint",
- "esbenp.prettier-vscode",
- "lllllllqw.jsdoc",
+ "oxc.oxc-vscode",
"bradlc.vscode-tailwindcss"
]
}
diff --git a/.vscode/settings.json b/.vscode/settings.json
index f7e0adcd..724a9607 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -3,7 +3,8 @@
"i18n-ally.keystyle": "nested",
"i18n-ally.sourceLanguage": "en",
"i18n-ally.indent": 4,
- "editor.defaultFormatter": "esbenp.prettier-vscode",
+ "oxc.fmt.configPath": ".oxfmtrc.json",
+ "editor.defaultFormatter": "oxc.oxc-vscode",
"editor.formatOnSave": true,
"omnisharp.enableRoslynAnalyzers": true,
"omnisharp.useModernNet": false,
diff --git a/eslint.config.mjs b/eslint.config.mjs
index 9dd78c76..75b34495 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -1,7 +1,6 @@
import { defineConfig } from 'eslint/config';
import { jsdoc } from 'eslint-plugin-jsdoc';
-import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
import globals from 'globals';
import js from '@eslint/js';
import pluginVue from 'eslint-plugin-vue';
@@ -108,7 +107,7 @@ export default defineConfig([
'jsdoc/require-returns-description': 'off',
'jsdoc/reject-function-type': 'off'
}
- }),
+ })
// {
// ignores: [
// '**/__tests__/**',
@@ -127,12 +126,4 @@ export default defineConfig([
// 'pretty-import/sort-import-names': 'warn'
// }
// },
- {
- ...eslintPluginPrettierRecommended,
- ignores: [
- '**/__tests__/**',
- '**/*.spec.{js,mjs,cjs,vue}',
- '**/*.test.{js,mjs,cjs,vue}'
- ]
- }
]);
diff --git a/package-lock.json b/package-lock.json
index f08de7d8..4a50659e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -46,9 +46,7 @@
"electron-builder": "^26.8.1",
"embla-carousel-vue": "^8.6.0",
"eslint": "^9.39.4",
- "eslint-config-prettier": "^10.1.8",
"eslint-plugin-jsdoc": "^62.8.0",
- "eslint-plugin-prettier": "^5.5.5",
"eslint-plugin-vue": "^9.33.0",
"globals": "^17.4.0",
"graphology": "^0.26.0",
@@ -59,8 +57,8 @@
"lightningcss": "^1.32.0",
"lucide-vue-next": "^0.562.0",
"noty": "^3.2.0-beta-deprecated",
+ "oxfmt": "^0.40.0",
"pinia": "^3.0.4",
- "prettier": "^3.8.1",
"reka-ui": "^2.9.1",
"remixicon": "^4.9.1",
"sigma": "^3.0.2",
@@ -2243,6 +2241,353 @@
"url": "https://github.com/sponsors/Boshen"
}
},
+ "node_modules/@oxfmt/binding-android-arm-eabi": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.40.0.tgz",
+ "integrity": "sha512-S6zd5r1w/HmqR8t0CTnGjFTBLDq2QKORPwriCHxo4xFNuhmOTABGjPaNvCJJVnrKBLsohOeiDX3YqQfJPF+FXw==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-android-arm64": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm64/-/binding-android-arm64-0.40.0.tgz",
+ "integrity": "sha512-/mbS9UUP/5Vbl2D6osIdcYiP0oie63LKMoTyGj5hyMCK/SFkl3EhtyRAfdjPvuvHC0SXdW6ePaTKkBSq1SNcIw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-darwin-arm64": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-arm64/-/binding-darwin-arm64-0.40.0.tgz",
+ "integrity": "sha512-wRt8fRdfLiEhnRMBonlIbKrJWixoEmn6KCjKE9PElnrSDSXETGZfPb8ee+nQNTobXkCVvVLytp2o0obAsxl78Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-darwin-x64": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-x64/-/binding-darwin-x64-0.40.0.tgz",
+ "integrity": "sha512-fzowhqbOE/NRy+AE5ob0+Y4X243WbWzDb00W+pKwD7d9tOqsAFbtWUwIyqqCoCLxj791m2xXIEeLH/3uz7zCCg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-freebsd-x64": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-freebsd-x64/-/binding-freebsd-x64-0.40.0.tgz",
+ "integrity": "sha512-agZ9ITaqdBjcerRRFEHB8s0OyVcQW8F9ZxsszjxzeSthQ4fcN2MuOtQFWec1ed8/lDa50jSLHVE2/xPmTgtCfQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-linux-arm-gnueabihf": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.40.0.tgz",
+ "integrity": "sha512-ZM2oQ47p28TP1DVIp7HL1QoMUgqlBFHey0ksHct7tMXoU5BqjNvPWw7888azzMt25lnyPODVuye1wvNbvVUFOA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-linux-arm-musleabihf": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.40.0.tgz",
+ "integrity": "sha512-RBFPAxRAIsMisKM47Oe6Lwdv6agZYLz02CUhVCD1sOv5ajAcRMrnwCFBPWwGXpazToW2mjnZxFos8TuFjTU15A==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-linux-arm64-gnu": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.40.0.tgz",
+ "integrity": "sha512-Nb2XbQ+wV3W2jSIihXdPj7k83eOxeSgYP3N/SRXvQ6ZYPIk6Q86qEh5Gl/7OitX3bQoQrESqm1yMLvZV8/J7dA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-linux-arm64-musl": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.40.0.tgz",
+ "integrity": "sha512-tGmWhLD/0YMotCdfezlT6tC/MJG/wKpo4vnQ3Cq+4eBk/BwNv7EmkD0VkD5F/dYkT3b8FNU01X2e8vvJuWoM1w==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-linux-ppc64-gnu": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.40.0.tgz",
+ "integrity": "sha512-rVbFyM3e7YhkVnp0IVYjaSHfrBWcTRWb60LEcdNAJcE2mbhTpbqKufx0FrhWfoxOrW/+7UJonAOShoFFLigDqQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-linux-riscv64-gnu": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.40.0.tgz",
+ "integrity": "sha512-3ZqBw14JtWeEoLiioJcXSJz8RQyPE+3jLARnYM1HdPzZG4vk+Ua8CUupt2+d+vSAvMyaQBTN2dZK+kbBS/j5mA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-linux-riscv64-musl": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.40.0.tgz",
+ "integrity": "sha512-JJ4PPSdcbGBjPvb+O7xYm2FmAsKCyuEMYhqatBAHMp/6TA6rVlf9Z/sYPa4/3Bommb+8nndm15SPFRHEPU5qFA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-linux-s390x-gnu": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.40.0.tgz",
+ "integrity": "sha512-Kp0zNJoX9Ik77wUya2tpBY3W9f40VUoMQLWVaob5SgCrblH/t2xr/9B2bWHfs0WCefuGmqXcB+t0Lq77sbBmZw==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-linux-x64-gnu": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.40.0.tgz",
+ "integrity": "sha512-7YTCNzleWTaQTqNGUNQ66qVjpoV6DjbCOea+RnpMBly2bpzrI/uu7Rr+2zcgRfNxyjXaFTVQKaRKjqVdeUfeVA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "glibc"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-linux-x64-musl": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.40.0.tgz",
+ "integrity": "sha512-hWnSzJ0oegeOwfOEeejYXfBqmnRGHusgtHfCPzmvJvHTwy1s3Neo59UKc1CmpE3zxvrCzJoVHos0rr97GHMNPw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "libc": [
+ "musl"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-openharmony-arm64": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-openharmony-arm64/-/binding-openharmony-arm64-0.40.0.tgz",
+ "integrity": "sha512-28sJC1lR4qtBJGzSRRbPnSW3GxU2+4YyQFE6rCmsUYqZ5XYH8jg0/w+CvEzQ8TuAQz5zLkcA25nFQGwoU0PT3Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "openharmony"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-win32-arm64-msvc": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.40.0.tgz",
+ "integrity": "sha512-cDkRnyT0dqwF5oIX1Cv59HKCeZQFbWWdUpXa3uvnHFT2iwYSSZspkhgjXjU6iDp5pFPaAEAe9FIbMoTgkTmKPg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-win32-ia32-msvc": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.40.0.tgz",
+ "integrity": "sha512-7rPemBJjqm5Gkv6ZRCPvK8lE6AqQ/2z31DRdWazyx2ZvaSgL7QGofHXHNouRpPvNsT9yxRNQJgigsWkc+0qg4w==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
+ "node_modules/@oxfmt/binding-win32-x64-msvc": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.40.0.tgz",
+ "integrity": "sha512-/Zmj0yTYSvmha6TG1QnoLqVT7ZMRDqXvFXXBQpIjteEwx9qvUYMBH2xbiOFhDeMUJkGwC3D6fdKsFtaqUvkwNA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ }
+ },
"node_modules/@pinia/testing": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@pinia/testing/-/testing-1.0.3.tgz",
@@ -2267,19 +2612,6 @@
"node": ">=14"
}
},
- "node_modules/@pkgr/core": {
- "version": "0.2.9",
- "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz",
- "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/pkgr"
- }
- },
"node_modules/@preact/signals-core": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/@preact/signals-core/-/signals-core-1.13.0.tgz",
@@ -6658,22 +6990,6 @@
}
}
},
- "node_modules/eslint-config-prettier": {
- "version": "10.1.8",
- "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz",
- "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "eslint-config-prettier": "bin/cli.js"
- },
- "funding": {
- "url": "https://opencollective.com/eslint-config-prettier"
- },
- "peerDependencies": {
- "eslint": ">=7.0.0"
- }
- },
"node_modules/eslint-plugin-jsdoc": {
"version": "62.8.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-62.8.0.tgz",
@@ -6734,37 +7050,6 @@
"url": "https://opencollective.com/eslint"
}
},
- "node_modules/eslint-plugin-prettier": {
- "version": "5.5.5",
- "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.5.tgz",
- "integrity": "sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "prettier-linter-helpers": "^1.0.1",
- "synckit": "^0.11.12"
- },
- "engines": {
- "node": "^14.18.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint-plugin-prettier"
- },
- "peerDependencies": {
- "@types/eslint": ">=8.0.0",
- "eslint": ">=8.0.0",
- "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0",
- "prettier": ">=3.0.0"
- },
- "peerDependenciesMeta": {
- "@types/eslint": {
- "optional": true
- },
- "eslint-config-prettier": {
- "optional": true
- }
- }
- },
"node_modules/eslint-plugin-vue": {
"version": "9.33.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.33.0.tgz",
@@ -6996,13 +7281,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/fast-diff": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
- "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
- "dev": true,
- "license": "Apache-2.0"
- },
"node_modules/fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
@@ -9465,6 +9743,46 @@
"node": ">=8"
}
},
+ "node_modules/oxfmt": {
+ "version": "0.40.0",
+ "resolved": "https://registry.npmjs.org/oxfmt/-/oxfmt-0.40.0.tgz",
+ "integrity": "sha512-g0C3I7xUj4b4DcagevM9kgH6+pUHytikxUcn3/VUkvzTNaaXBeyZqb7IBsHwojeXm4mTBEC/aBjBTMVUkZwWUQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tinypool": "2.1.0"
+ },
+ "bin": {
+ "oxfmt": "bin/oxfmt"
+ },
+ "engines": {
+ "node": "^20.19.0 || >=22.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/Boshen"
+ },
+ "optionalDependencies": {
+ "@oxfmt/binding-android-arm-eabi": "0.40.0",
+ "@oxfmt/binding-android-arm64": "0.40.0",
+ "@oxfmt/binding-darwin-arm64": "0.40.0",
+ "@oxfmt/binding-darwin-x64": "0.40.0",
+ "@oxfmt/binding-freebsd-x64": "0.40.0",
+ "@oxfmt/binding-linux-arm-gnueabihf": "0.40.0",
+ "@oxfmt/binding-linux-arm-musleabihf": "0.40.0",
+ "@oxfmt/binding-linux-arm64-gnu": "0.40.0",
+ "@oxfmt/binding-linux-arm64-musl": "0.40.0",
+ "@oxfmt/binding-linux-ppc64-gnu": "0.40.0",
+ "@oxfmt/binding-linux-riscv64-gnu": "0.40.0",
+ "@oxfmt/binding-linux-riscv64-musl": "0.40.0",
+ "@oxfmt/binding-linux-s390x-gnu": "0.40.0",
+ "@oxfmt/binding-linux-x64-gnu": "0.40.0",
+ "@oxfmt/binding-linux-x64-musl": "0.40.0",
+ "@oxfmt/binding-openharmony-arm64": "0.40.0",
+ "@oxfmt/binding-win32-arm64-msvc": "0.40.0",
+ "@oxfmt/binding-win32-ia32-msvc": "0.40.0",
+ "@oxfmt/binding-win32-x64-msvc": "0.40.0"
+ }
+ },
"node_modules/p-cancelable": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz",
@@ -9821,35 +10139,6 @@
"node": ">= 0.8.0"
}
},
- "node_modules/prettier": {
- "version": "3.8.1",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz",
- "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "prettier": "bin/prettier.cjs"
- },
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/prettier/prettier?sponsor=1"
- }
- },
- "node_modules/prettier-linter-helpers": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz",
- "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fast-diff": "^1.1.2"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
"node_modules/proc-log": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/proc-log/-/proc-log-5.0.0.tgz",
@@ -10809,22 +11098,6 @@
"dev": true,
"license": "MIT"
},
- "node_modules/synckit": {
- "version": "0.11.12",
- "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.12.tgz",
- "integrity": "sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@pkgr/core": "^0.2.9"
- },
- "engines": {
- "node": "^14.18.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/synckit"
- }
- },
"node_modules/tailwind-merge": {
"version": "3.5.0",
"resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.5.0.tgz",
@@ -11033,6 +11306,16 @@
"url": "https://github.com/sponsors/jonschlinkert"
}
},
+ "node_modules/tinypool": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-2.1.0.tgz",
+ "integrity": "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^20.0.0 || >=22.0.0"
+ }
+ },
"node_modules/tinyrainbow": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.1.0.tgz",
diff --git a/package.json b/package.json
index 4de50af1..fc4a9628 100644
--- a/package.json
+++ b/package.json
@@ -65,9 +65,7 @@
"electron-builder": "^26.8.1",
"embla-carousel-vue": "^8.6.0",
"eslint": "^9.39.4",
- "eslint-config-prettier": "^10.1.8",
"eslint-plugin-jsdoc": "^62.8.0",
- "eslint-plugin-prettier": "^5.5.5",
"eslint-plugin-vue": "^9.33.0",
"globals": "^17.4.0",
"graphology": "^0.26.0",
@@ -78,8 +76,8 @@
"lightningcss": "^1.32.0",
"lucide-vue-next": "^0.562.0",
"noty": "^3.2.0-beta-deprecated",
+ "oxfmt": "^0.40.0",
"pinia": "^3.0.4",
- "prettier": "^3.8.1",
"reka-ui": "^2.9.1",
"remixicon": "^4.9.1",
"sigma": "^3.0.2",
diff --git a/src-electron/offscreen-preload.js b/src-electron/offscreen-preload.js
index 1417a98f..e8559086 100644
--- a/src-electron/offscreen-preload.js
+++ b/src-electron/offscreen-preload.js
@@ -1,5 +1,6 @@
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
- onUpdateImage: (callback) => ipcRenderer.on('update-image', (event, base64) => callback(base64))
-});
\ No newline at end of file
+ onUpdateImage: (callback) =>
+ ipcRenderer.on('update-image', (event, base64) => callback(base64))
+});
diff --git a/src/api/__tests__/entityQuerySync.test.js b/src/api/__tests__/entityQuerySync.test.js
index 3d0fbe99..668c5850 100644
--- a/src/api/__tests__/entityQuerySync.test.js
+++ b/src/api/__tests__/entityQuerySync.test.js
@@ -3,7 +3,10 @@ import { beforeEach, describe, expect, test, vi } from 'vitest';
const mockRequest = vi.fn();
const mockPatchAndRefetchActiveQuery = vi.fn(() => Promise.resolve());
-const mockApplyCurrentUser = vi.fn((json) => ({ id: json.id || 'usr_me', ...json }));
+const mockApplyCurrentUser = vi.fn((json) => ({
+ id: json.id || 'usr_me',
+ ...json
+}));
const mockApplyUser = vi.fn((json) => ({ ...json }));
const mockApplyWorld = vi.fn((json) => ({ ...json }));
@@ -91,5 +94,4 @@ describe('entity mutation query sync', () => {
})
);
});
-
});
diff --git a/src/api/__tests__/favoriteQuerySync.test.js b/src/api/__tests__/favoriteQuerySync.test.js
index 2906635f..cb2772d4 100644
--- a/src/api/__tests__/favoriteQuerySync.test.js
+++ b/src/api/__tests__/favoriteQuerySync.test.js
@@ -19,8 +19,7 @@ vi.mock('../../stores', () => ({
vi.mock('../../coordinators/favoriteCoordinator', () => ({
handleFavoriteAdd: (...args) => mockHandleFavoriteAdd(...args),
handleFavoriteDelete: (...args) => mockHandleFavoriteDelete(...args),
- handleFavoriteGroupClear: (...args) =>
- mockHandleFavoriteGroupClear(...args)
+ handleFavoriteGroupClear: (...args) => mockHandleFavoriteGroupClear(...args)
}));
vi.mock('../../queries', () => ({
@@ -39,7 +38,10 @@ describe('favorite query sync', () => {
test('favorite mutations invalidate active favorite queries', async () => {
mockRequest.mockResolvedValue({ ok: true });
- await favoriteRequest.addFavorite({ type: 'world', favoriteId: 'wrld_1' });
+ await favoriteRequest.addFavorite({
+ type: 'world',
+ favoriteId: 'wrld_1'
+ });
await favoriteRequest.deleteFavorite({ objectId: 'fav_1' });
await favoriteRequest.saveFavoriteGroup({
type: 'world',
diff --git a/src/api/__tests__/mediaQuerySync.test.js b/src/api/__tests__/mediaQuerySync.test.js
index f2dbb87c..970e7ce6 100644
--- a/src/api/__tests__/mediaQuerySync.test.js
+++ b/src/api/__tests__/mediaQuerySync.test.js
@@ -24,7 +24,12 @@ vi.mock('../../queries', () => ({
prints: (params) => ['gallery', 'prints', params],
print: (printId) => ['gallery', 'print', printId],
inventoryItems: (params) => ['inventory', 'items', params],
- userInventoryItem: (params) => ['inventory', 'item', params.userId, params.inventoryId],
+ userInventoryItem: (params) => [
+ 'inventory',
+ 'item',
+ params.userId,
+ params.inventoryId
+ ],
file: (fileId) => ['file', fileId]
}
}));
diff --git a/src/api/__tests__/queryRequest.test.js b/src/api/__tests__/queryRequest.test.js
index b59616a6..715f8b97 100644
--- a/src/api/__tests__/queryRequest.test.js
+++ b/src/api/__tests__/queryRequest.test.js
@@ -10,28 +10,138 @@ vi.mock('../../queries', () => ({
invalidateQueries: vi.fn().mockResolvedValue(undefined)
},
entityQueryPolicies: {
- user: { staleTime: 20000, gcTime: 90000, retry: 1, refetchOnWindowFocus: false },
- worldCollection: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false },
- groupCollection: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false },
- groupCalendarCollection: { staleTime: 120000, gcTime: 600000, retry: 1, refetchOnWindowFocus: false },
- groupFollowingCalendarCollection: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false },
- groupFeaturedCalendarCollection: { staleTime: 300000, gcTime: 900000, retry: 1, refetchOnWindowFocus: false },
- groupCalendarEvent: { staleTime: 120000, gcTime: 600000, retry: 1, refetchOnWindowFocus: false },
- avatar: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false },
- avatarCollection: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false },
- avatarGallery: { staleTime: 30000, gcTime: 120000, retry: 1, refetchOnWindowFocus: false },
- world: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false },
- group: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false },
- friendList: { staleTime: 20000, gcTime: 90000, retry: 1, refetchOnWindowFocus: false },
- favoriteCollection: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false },
- galleryCollection: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false },
- inventoryCollection: { staleTime: 20000, gcTime: 120000, retry: 1, refetchOnWindowFocus: false },
- inventoryObject: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false },
- fileAnalysis: { staleTime: 120000, gcTime: 600000, retry: 1, refetchOnWindowFocus: false },
- worldPersistData: { staleTime: 120000, gcTime: 600000, retry: 1, refetchOnWindowFocus: false },
- mutualCounts: { staleTime: 120000, gcTime: 600000, retry: 1, refetchOnWindowFocus: false },
- visits: { staleTime: 300000, gcTime: 900000, retry: 1, refetchOnWindowFocus: false },
- fileObject: { staleTime: 60000, gcTime: 300000, retry: 1, refetchOnWindowFocus: false }
+ user: {
+ staleTime: 20000,
+ gcTime: 90000,
+ retry: 1,
+ refetchOnWindowFocus: false
+ },
+ worldCollection: {
+ staleTime: 60000,
+ gcTime: 300000,
+ retry: 1,
+ refetchOnWindowFocus: false
+ },
+ groupCollection: {
+ staleTime: 60000,
+ gcTime: 300000,
+ retry: 1,
+ refetchOnWindowFocus: false
+ },
+ groupCalendarCollection: {
+ staleTime: 120000,
+ gcTime: 600000,
+ retry: 1,
+ refetchOnWindowFocus: false
+ },
+ groupFollowingCalendarCollection: {
+ staleTime: 60000,
+ gcTime: 300000,
+ retry: 1,
+ refetchOnWindowFocus: false
+ },
+ groupFeaturedCalendarCollection: {
+ staleTime: 300000,
+ gcTime: 900000,
+ retry: 1,
+ refetchOnWindowFocus: false
+ },
+ groupCalendarEvent: {
+ staleTime: 120000,
+ gcTime: 600000,
+ retry: 1,
+ refetchOnWindowFocus: false
+ },
+ avatar: {
+ staleTime: 60000,
+ gcTime: 300000,
+ retry: 1,
+ refetchOnWindowFocus: false
+ },
+ avatarCollection: {
+ staleTime: 60000,
+ gcTime: 300000,
+ retry: 1,
+ refetchOnWindowFocus: false
+ },
+ avatarGallery: {
+ staleTime: 30000,
+ gcTime: 120000,
+ retry: 1,
+ refetchOnWindowFocus: false
+ },
+ world: {
+ staleTime: 60000,
+ gcTime: 300000,
+ retry: 1,
+ refetchOnWindowFocus: false
+ },
+ group: {
+ staleTime: 60000,
+ gcTime: 300000,
+ retry: 1,
+ refetchOnWindowFocus: false
+ },
+ friendList: {
+ staleTime: 20000,
+ gcTime: 90000,
+ retry: 1,
+ refetchOnWindowFocus: false
+ },
+ favoriteCollection: {
+ staleTime: 60000,
+ gcTime: 300000,
+ retry: 1,
+ refetchOnWindowFocus: false
+ },
+ galleryCollection: {
+ staleTime: 60000,
+ gcTime: 300000,
+ retry: 1,
+ refetchOnWindowFocus: false
+ },
+ inventoryCollection: {
+ staleTime: 20000,
+ gcTime: 120000,
+ retry: 1,
+ refetchOnWindowFocus: false
+ },
+ inventoryObject: {
+ staleTime: 60000,
+ gcTime: 300000,
+ retry: 1,
+ refetchOnWindowFocus: false
+ },
+ fileAnalysis: {
+ staleTime: 120000,
+ gcTime: 600000,
+ retry: 1,
+ refetchOnWindowFocus: false
+ },
+ worldPersistData: {
+ staleTime: 120000,
+ gcTime: 600000,
+ retry: 1,
+ refetchOnWindowFocus: false
+ },
+ mutualCounts: {
+ staleTime: 120000,
+ gcTime: 600000,
+ retry: 1,
+ refetchOnWindowFocus: false
+ },
+ visits: {
+ staleTime: 300000,
+ gcTime: 900000,
+ retry: 1,
+ refetchOnWindowFocus: false
+ },
+ fileObject: {
+ staleTime: 60000,
+ gcTime: 300000,
+ retry: 1,
+ refetchOnWindowFocus: false
+ }
},
fetchWithEntityPolicy: (...args) => mockFetchWithEntityPolicy(...args),
queryKeys: {
@@ -40,16 +150,46 @@ vi.mock('../../queries', () => ({
worldsByUser: (params) => ['worlds', 'user', params.userId, params],
groupCalendar: (groupId) => ['group', groupId, 'calendar'],
groupCalendars: (params) => ['group', 'calendar', params],
- followingGroupCalendars: (params) => ['group', 'calendar', 'following', params],
- featuredGroupCalendars: (params) => ['group', 'calendar', 'featured', params],
+ followingGroupCalendars: (params) => [
+ 'group',
+ 'calendar',
+ 'following',
+ params
+ ],
+ featuredGroupCalendars: (params) => [
+ 'group',
+ 'calendar',
+ 'featured',
+ params
+ ],
avatar: (avatarId) => ['avatar', avatarId],
world: (worldId) => ['world', worldId],
- group: (groupId, includeRoles) => ['group', groupId, Boolean(includeRoles)],
+ group: (groupId, includeRoles) => [
+ 'group',
+ groupId,
+ Boolean(includeRoles)
+ ],
groupPosts: (params) => ['group', params.groupId, 'posts', params],
- groupMember: (params) => ['group', params.groupId, 'member', params.userId],
+ groupMember: (params) => [
+ 'group',
+ params.groupId,
+ 'member',
+ params.userId
+ ],
groupMembers: (params) => ['group', params.groupId, 'members', params],
- groupGallery: (params) => ['group', params.groupId, 'gallery', params.galleryId, params],
- groupCalendarEvent: (params) => ['group', params.groupId, 'calendarEvent', params.eventId],
+ groupGallery: (params) => [
+ 'group',
+ params.groupId,
+ 'gallery',
+ params.galleryId,
+ params
+ ],
+ groupCalendarEvent: (params) => [
+ 'group',
+ params.groupId,
+ 'calendarEvent',
+ params.eventId
+ ],
avatarGallery: (avatarId) => ['avatar', avatarId, 'gallery'],
friends: (params) => ['friends', params],
favoriteLimits: () => ['favorite', 'limits'],
@@ -61,10 +201,24 @@ vi.mock('../../queries', () => ({
prints: (params) => ['gallery', 'prints', params],
print: (printId) => ['gallery', 'print', printId],
inventoryItem: (inventoryId) => ['inventory', 'item', inventoryId],
- userInventoryItem: (params) => ['inventory', 'item', params.userId, params.inventoryId],
+ userInventoryItem: (params) => [
+ 'inventory',
+ 'item',
+ params.userId,
+ params.inventoryId
+ ],
inventoryItems: (params) => ['inventory', 'items', params],
- inventoryTemplate: (inventoryTemplateId) => ['inventory', 'template', inventoryTemplateId],
- fileAnalysis: (params) => ['analysis', params.fileId, Number(params.version), String(params.variant || '')],
+ inventoryTemplate: (inventoryTemplateId) => [
+ 'inventory',
+ 'template',
+ inventoryTemplateId
+ ],
+ fileAnalysis: (params) => [
+ 'analysis',
+ params.fileId,
+ Number(params.version),
+ String(params.variant || '')
+ ],
worldPersistData: (worldId) => ['world', worldId, 'persistData'],
mutualCounts: (userId) => ['user', userId, 'mutualCounts'],
visits: () => ['visits'],
@@ -102,7 +256,11 @@ vi.mock('../group', () => ({
}));
vi.mock('../avatar', () => ({
- default: { getAvatar: vi.fn(), getAvatarGallery: vi.fn(), getAvatars: vi.fn() }
+ default: {
+ getAvatar: vi.fn(),
+ getAvatarGallery: vi.fn(),
+ getAvatars: vi.fn()
+ }
}));
vi.mock('../friend', () => ({ default: { getFriends: vi.fn() } }));
vi.mock('../favorite', () => ({
diff --git a/src/components/Location.vue b/src/components/Location.vue
index af899540..da87d5d5 100644
--- a/src/components/Location.vue
+++ b/src/components/Location.vue
@@ -43,12 +43,7 @@
resolveRegion,
translateAccessType
} from '../shared/utils';
- import {
- useAppearanceSettingsStore,
- useInstanceStore,
- useSearchStore,
- useWorldStore
- } from '../stores';
+ import { useAppearanceSettingsStore, useInstanceStore, useSearchStore, useWorldStore } from '../stores';
import { showGroupDialog } from '../coordinators/groupCoordinator';
import { showWorldDialog } from '../coordinators/worldCoordinator';
import { Spinner } from './ui/spinner';
@@ -104,9 +99,7 @@
}
]);
const tooltipContent = computed(() => `${t('dialog.new_instance.instance_id')}: #${instanceName.value}`);
- const tooltipDisabled = computed(
- () => props.disableTooltip || !instanceName.value || showInstanceIdInLocation.value
- );
+ const tooltipDisabled = computed(() => props.disableTooltip || !instanceName.value || showInstanceIdInLocation.value);
const closedTooltip = computed(() => t('dialog.user.info.instance_closed'));
let isDisposed = false;
diff --git a/src/components/__tests__/AvatarInfo.test.js b/src/components/__tests__/AvatarInfo.test.js
index 04a4e607..c4f48f07 100644
--- a/src/components/__tests__/AvatarInfo.test.js
+++ b/src/components/__tests__/AvatarInfo.test.js
@@ -216,7 +216,9 @@ describe('AvatarInfo.vue', () => {
test('does not call showAvatarAuthorDialog when no imageurl', async () => {
const wrapper = mountAvatarInfo({});
await wrapper.trigger('click');
- expect(avatarCoordinatorModule.showAvatarAuthorDialog).not.toHaveBeenCalled();
+ expect(
+ avatarCoordinatorModule.showAvatarAuthorDialog
+ ).not.toHaveBeenCalled();
});
});
});
diff --git a/src/components/__tests__/BackToTop.test.js b/src/components/__tests__/BackToTop.test.js
index 5f88b058..1aa16056 100644
--- a/src/components/__tests__/BackToTop.test.js
+++ b/src/components/__tests__/BackToTop.test.js
@@ -11,7 +11,8 @@ vi.mock('@/components/ui/tooltip', () => ({
vi.mock('@/components/ui/button', () => ({
Button: {
emits: ['click'],
- template: ''
+ template:
+ ''
}
}));
@@ -58,7 +59,10 @@ describe('BackToTop.vue', () => {
await btn.trigger('click');
- expect(window.scrollTo).toHaveBeenCalledWith({ top: 0, behavior: 'smooth' });
+ expect(window.scrollTo).toHaveBeenCalledWith({
+ top: 0,
+ behavior: 'smooth'
+ });
});
it('uses virtualizer scrollToIndex when provided', async () => {
@@ -78,7 +82,10 @@ describe('BackToTop.vue', () => {
const btn = wrapper.get('[data-testid="back-btn"]');
await btn.trigger('click');
- expect(scrollToIndex).toHaveBeenCalledWith(0, { align: 'start', behavior: 'auto' });
+ expect(scrollToIndex).toHaveBeenCalledWith(0, {
+ align: 'start',
+ behavior: 'auto'
+ });
expect(window.scrollTo).not.toHaveBeenCalled();
});
@@ -103,6 +110,9 @@ describe('BackToTop.vue', () => {
const btn = wrapper.get('[data-testid="back-btn"]');
await btn.trigger('click');
- expect(target.scrollTo).toHaveBeenCalledWith({ top: 0, behavior: 'auto' });
+ expect(target.scrollTo).toHaveBeenCalledWith({
+ top: 0,
+ behavior: 'auto'
+ });
});
});
diff --git a/src/components/__tests__/CountdownTimer.test.js b/src/components/__tests__/CountdownTimer.test.js
index d759d215..9628e574 100644
--- a/src/components/__tests__/CountdownTimer.test.js
+++ b/src/components/__tests__/CountdownTimer.test.js
@@ -24,7 +24,9 @@ describe('CountdownTimer.vue', () => {
mocks.setInterval.mockClear();
mocks.clearInterval.mockClear();
mocks.timeToText.mockClear();
- vi.spyOn(Date, 'now').mockReturnValue(new Date('2026-01-01T00:00:00.000Z').getTime());
+ vi.spyOn(Date, 'now').mockReturnValue(
+ new Date('2026-01-01T00:00:00.000Z').getTime()
+ );
});
afterEach(() => {
@@ -55,7 +57,10 @@ describe('CountdownTimer.vue', () => {
expect(wrapper.text()).toBe('-');
- await wrapper.setProps({ datetime: '2025-12-31T23:59:30.000Z', hours: 0 });
+ await wrapper.setProps({
+ datetime: '2025-12-31T23:59:30.000Z',
+ hours: 0
+ });
await nextTick();
expect(wrapper.text()).toBe('-');
});
diff --git a/src/components/__tests__/DeprecationAlert.test.js b/src/components/__tests__/DeprecationAlert.test.js
index ff78ba82..0702de43 100644
--- a/src/components/__tests__/DeprecationAlert.test.js
+++ b/src/components/__tests__/DeprecationAlert.test.js
@@ -22,7 +22,8 @@ describe('DeprecationAlert.vue', () => {
global: {
stubs: {
i18nT: {
- template: ''
+ template:
+ ''
}
}
}
diff --git a/src/components/__tests__/DisplayName.test.js b/src/components/__tests__/DisplayName.test.js
index 17921daf..dbd56c42 100644
--- a/src/components/__tests__/DisplayName.test.js
+++ b/src/components/__tests__/DisplayName.test.js
@@ -2,7 +2,9 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
import { mount } from '@vue/test-utils';
const mocks = vi.hoisted(() => ({
- fetch: vi.fn(() => Promise.resolve({ json: { displayName: 'Fetched User' } })),
+ fetch: vi.fn(() =>
+ Promise.resolve({ json: { displayName: 'Fetched User' } })
+ ),
showUserDialog: vi.fn()
}));
@@ -52,7 +54,9 @@ describe('DisplayName.vue', () => {
await flush();
- expect(mocks.fetch).toHaveBeenCalledWith('user.dialog', { userId: 'usr_2' });
+ expect(mocks.fetch).toHaveBeenCalledWith('user.dialog', {
+ userId: 'usr_2'
+ });
expect(wrapper.text()).toBe('Fetched User');
});
diff --git a/src/components/__tests__/Emoji.test.js b/src/components/__tests__/Emoji.test.js
index 4ac3f474..e84a358b 100644
--- a/src/components/__tests__/Emoji.test.js
+++ b/src/components/__tests__/Emoji.test.js
@@ -27,8 +27,13 @@ vi.mock('../../shared/utils', () => ({
vi.mock('../ui/avatar', () => ({
Avatar: { template: '
' },
- AvatarImage: { props: ['src'], template: '
' },
- AvatarFallback: { template: '' }
+ AvatarImage: {
+ props: ['src'],
+ template: '
'
+ },
+ AvatarFallback: {
+ template: ''
+ }
}));
vi.mock('lucide-vue-next', () => ({
@@ -87,8 +92,12 @@ describe('Emoji.vue', () => {
expect(mocks.getCachedEmoji).toHaveBeenCalledWith('file_1');
expect(wrapper.find('[data-testid="avatar"]').exists()).toBe(true);
- expect(wrapper.find('[data-testid="avatar-image"]').attributes('src')).toBe('https://example.com/file_2.png');
- expect(wrapper.find('[data-testid="avatar-fallback"]').exists()).toBe(true);
+ expect(
+ wrapper.find('[data-testid="avatar-image"]').attributes('src')
+ ).toBe('https://example.com/file_2.png');
+ expect(wrapper.find('[data-testid="avatar-fallback"]').exists()).toBe(
+ true
+ );
});
it('updates when imageUrl changes', async () => {
diff --git a/src/components/__tests__/FullscreenImagePreview.test.js b/src/components/__tests__/FullscreenImagePreview.test.js
index df09d1f0..6b52fcb3 100644
--- a/src/components/__tests__/FullscreenImagePreview.test.js
+++ b/src/components/__tests__/FullscreenImagePreview.test.js
@@ -2,20 +2,66 @@ import { describe, expect, it, vi } from 'vitest';
import { mount } from '@vue/test-utils';
const mocks = vi.hoisted(() => ({
- dialog: { value: { visible: true, imageUrl: 'https://example.com/a.png', fileName: 'a.png' } }
+ dialog: {
+ value: {
+ visible: true,
+ imageUrl: 'https://example.com/a.png',
+ fileName: 'a.png'
+ }
+ }
}));
vi.mock('pinia', async (i) => ({ ...(await i()), storeToRefs: (s) => s }));
vi.mock('vue-i18n', () => ({ useI18n: () => ({ t: (k) => k }) }));
-vi.mock('@/stores/settings/general', () => ({ useGeneralSettingsStore: () => ({ disableGpuAcceleration: { value: false } }) }));
-vi.mock('../../stores', () => ({ useGalleryStore: () => ({ fullscreenImageDialog: mocks.dialog, showFullscreenImageDialog: vi.fn() }) }));
-vi.mock('@/lib/modalPortalLayers', () => ({ acquireModalPortalLayer: () => ({ element: 'body', bringToFront: vi.fn(), release: vi.fn() }) }));
+vi.mock('@/stores/settings/general', () => ({
+ useGeneralSettingsStore: () => ({
+ disableGpuAcceleration: { value: false }
+ })
+}));
+vi.mock('../../stores', () => ({
+ useGalleryStore: () => ({
+ fullscreenImageDialog: mocks.dialog,
+ showFullscreenImageDialog: vi.fn()
+ })
+}));
+vi.mock('@/lib/modalPortalLayers', () => ({
+ acquireModalPortalLayer: () => ({
+ element: 'body',
+ bringToFront: vi.fn(),
+ release: vi.fn()
+ })
+}));
vi.mock('@/lib/utils', () => ({ cn: (...a) => a.filter(Boolean).join(' ') }));
-vi.mock('../../shared/utils', () => ({ escapeTag: (s) => s, extractFileId: () => 'f1' }));
-vi.mock('vue-sonner', () => ({ toast: { info: vi.fn(() => 'id'), success: vi.fn(), error: vi.fn(), dismiss: vi.fn() } }));
-vi.mock('@/components/ui/dialog', () => ({ Dialog: { template: '
' } }));
-vi.mock('reka-ui', () => ({ DialogPortal: { template: '
' }, DialogOverlay: { template: '
' }, DialogContent: { emits: ['click'], template: '
' } }));
-vi.mock('@/components/ui/button', () => ({ Button: { emits: ['click'], template: '' } }));
+vi.mock('../../shared/utils', () => ({
+ escapeTag: (s) => s,
+ extractFileId: () => 'f1'
+}));
+vi.mock('vue-sonner', () => ({
+ toast: {
+ info: vi.fn(() => 'id'),
+ success: vi.fn(),
+ error: vi.fn(),
+ dismiss: vi.fn()
+ }
+}));
+vi.mock('@/components/ui/dialog', () => ({
+ Dialog: { template: '
' }
+}));
+vi.mock('reka-ui', () => ({
+ DialogPortal: { template: '
' },
+ DialogOverlay: { template: '
' },
+ DialogContent: {
+ emits: ['click'],
+ template: '
'
+ }
+}));
+vi.mock('@/components/ui/button', () => ({
+ Button: {
+ emits: ['click'],
+ template:
+ ''
+ }
+}));
vi.mock('lucide-vue-next', () => ({
Copy: { template: '' },
Download: { template: '' },
diff --git a/src/components/__tests__/GlobalSearchDialog.test.js b/src/components/__tests__/GlobalSearchDialog.test.js
index edb4b81f..3cdeaf4b 100644
--- a/src/components/__tests__/GlobalSearchDialog.test.js
+++ b/src/components/__tests__/GlobalSearchDialog.test.js
@@ -33,17 +33,35 @@ vi.mock('../../stores/globalSearch', () => ({
selectResult: (...args) => mocks.selectResult(...args)
})
}));
-vi.mock('../../composables/useUserDisplay', () => ({ useUserDisplay: () => ({ userImage: (...a) => mocks.userImage(...a) }) }));
-vi.mock('../GlobalSearchSync.vue', () => ({ default: { template: '' } }));
-vi.mock('@/components/ui/dialog', () => ({ Dialog: { template: '
' }, DialogContent: { template: '
' }, DialogHeader: { template: '
' }, DialogTitle: { template: '
' }, DialogDescription: { template: '
' } }));
+vi.mock('../../composables/useUserDisplay', () => ({
+ useUserDisplay: () => ({ userImage: (...a) => mocks.userImage(...a) })
+}));
+vi.mock('../GlobalSearchSync.vue', () => ({
+ default: { template: '' }
+}));
+vi.mock('@/components/ui/dialog', () => ({
+ Dialog: { template: '
' },
+ DialogContent: { template: '
' },
+ DialogHeader: { template: '
' },
+ DialogTitle: { template: '
' },
+ DialogDescription: { template: '
' }
+}));
vi.mock('@/components/ui/command', () => ({
Command: { template: '
' },
CommandInput: { template: '' },
CommandList: { template: '
' },
CommandGroup: { template: '
' },
- CommandItem: { emits: ['select'], template: '' }
+ CommandItem: {
+ emits: ['select'],
+ template:
+ ''
+ }
+}));
+vi.mock('lucide-vue-next', () => ({
+ Globe: { template: '' },
+ Image: { template: '' },
+ Users: { template: '' }
}));
-vi.mock('lucide-vue-next', () => ({ Globe: { template: '' }, Image: { template: '' }, Users: { template: '' } }));
import GlobalSearchDialog from '../GlobalSearchDialog.vue';
diff --git a/src/components/__tests__/GlobalSearchSync.test.js b/src/components/__tests__/GlobalSearchSync.test.js
index d8e483fe..8d2e8a79 100644
--- a/src/components/__tests__/GlobalSearchSync.test.js
+++ b/src/components/__tests__/GlobalSearchSync.test.js
@@ -12,7 +12,10 @@ const mocks = vi.hoisted(() => ({
}
},
filterState: null,
- allItemsEntries: [['a', {}], ['b', {}]],
+ allItemsEntries: [
+ ['a', {}],
+ ['b', {}]
+ ],
allGroupsEntries: [['g1', {}]]
}));
diff --git a/src/components/__tests__/InstanceActionBar.test.js b/src/components/__tests__/InstanceActionBar.test.js
index 0736e9fa..7d983b8c 100644
--- a/src/components/__tests__/InstanceActionBar.test.js
+++ b/src/components/__tests__/InstanceActionBar.test.js
@@ -4,11 +4,18 @@ import { nextTick } from 'vue';
const mocks = vi.hoisted(() => ({
checkCanInviteSelf: vi.fn(() => true),
- parseLocation: vi.fn(() => ({ isRealInstance: true, instanceId: 'inst_1', worldId: 'wrld_1', tag: 'wrld_1:inst_1' })),
+ parseLocation: vi.fn(() => ({
+ isRealInstance: true,
+ instanceId: 'inst_1',
+ worldId: 'wrld_1',
+ tag: 'wrld_1:inst_1'
+ })),
hasGroupPermission: vi.fn(() => false),
formatDateFilter: vi.fn(() => 'formatted-date'),
selfInvite: vi.fn(() => Promise.resolve({})),
- closeInstance: vi.fn(() => Promise.resolve({ json: { id: 'inst_closed' } })),
+ closeInstance: vi.fn(() =>
+ Promise.resolve({ json: { id: 'inst_closed' } })
+ ),
showUserDialog: vi.fn(),
toastSuccess: vi.fn(),
applyInstance: vi.fn(),
@@ -18,7 +25,10 @@ const mocks = vi.hoisted(() => ({
instanceJoinHistory: { value: new Map() },
canOpenInstanceInGame: false,
isOpeningInstance: false,
- lastLocation: { location: 'wrld_here:111', playerList: new Set(['u1', 'u2']) },
+ lastLocation: {
+ location: 'wrld_here:111',
+ playerList: new Set(['u1', 'u2'])
+ },
currentUser: { id: 'usr_me' },
cachedGroups: new Map()
}));
@@ -31,7 +41,9 @@ vi.mock('pinia', async (importOriginal) => {
Object.fromEntries(
Object.entries(store).map(([key, value]) => [
key,
- key === 'instanceJoinHistory' ? value : value?.value ?? value
+ key === 'instanceJoinHistory'
+ ? value
+ : (value?.value ?? value)
])
)
};
@@ -104,7 +116,8 @@ vi.mock('../../coordinators/userCoordinator', () => ({
vi.mock('@/components/ui/button', () => ({
Button: {
emits: ['click'],
- template: ''
+ template:
+ ''
}
}));
@@ -157,7 +170,8 @@ function mountBar(props = {}) {
stubs: {
TooltipWrapper: {
props: ['content'],
- template: '{{ content }}
'
+ template:
+ '{{ content }}
'
},
Timer: {
props: ['epoch'],
@@ -185,8 +199,12 @@ describe('InstanceActionBar.vue', () => {
mocks.applyInstance.mockClear();
mocks.showLaunchDialog.mockClear();
mocks.tryOpenInstanceInVrc.mockClear();
- mocks.modalConfirm.mockImplementation(() => Promise.resolve({ ok: true }));
- mocks.instanceJoinHistory.value = new Map([['wrld_base:111', 1700000000]]);
+ mocks.modalConfirm.mockImplementation(() =>
+ Promise.resolve({ ok: true })
+ );
+ mocks.instanceJoinHistory.value = new Map([
+ ['wrld_base:111', 1700000000]
+ ]);
mocks.canOpenInstanceInGame = false;
mocks.isOpeningInstance = false;
mocks.lastLocation.location = 'wrld_here:111';
@@ -203,8 +221,12 @@ describe('InstanceActionBar.vue', () => {
});
expect(wrapper.findAll('[data-testid="btn"]')).toHaveLength(2);
- expect(wrapper.text()).toContain('dialog.user.info.launch_invite_tooltip');
- expect(wrapper.text()).toContain('dialog.user.info.self_invite_tooltip');
+ expect(wrapper.text()).toContain(
+ 'dialog.user.info.launch_invite_tooltip'
+ );
+ expect(wrapper.text()).toContain(
+ 'dialog.user.info.self_invite_tooltip'
+ );
});
it('launch button opens launch dialog with resolved launchLocation', async () => {
@@ -240,7 +262,9 @@ describe('InstanceActionBar.vue', () => {
worldId: 'wrld_1',
shortName: 'sn'
});
- expect(mocks.toastSuccess).toHaveBeenCalledWith('message.invite.self_sent');
+ expect(mocks.toastSuccess).toHaveBeenCalledWith(
+ 'message.invite.self_sent'
+ );
});
it('invite button opens in VRChat when canOpenInstanceInGame is true', async () => {
@@ -256,7 +280,10 @@ describe('InstanceActionBar.vue', () => {
await inviteBtn.trigger('click');
- expect(mocks.tryOpenInstanceInVrc).toHaveBeenCalledWith('wrld_1:inst_1', 'sn');
+ expect(mocks.tryOpenInstanceInVrc).toHaveBeenCalledWith(
+ 'wrld_1:inst_1',
+ 'sn'
+ );
expect(mocks.selfInvite).not.toHaveBeenCalled();
});
@@ -302,7 +329,11 @@ describe('InstanceActionBar.vue', () => {
}
});
- const closeBtn = wrapper.findAll('button').find((btn) => btn.text().includes('dialog.user.info.close_instance'));
+ const closeBtn = wrapper
+ .findAll('button')
+ .find((btn) =>
+ btn.text().includes('dialog.user.info.close_instance')
+ );
expect(closeBtn).toBeTruthy();
await closeBtn.trigger('click');
@@ -311,9 +342,14 @@ describe('InstanceActionBar.vue', () => {
await nextTick();
expect(mocks.modalConfirm).toHaveBeenCalled();
- expect(mocks.closeInstance).toHaveBeenCalledWith({ location: 'wrld_close:444', hardClose: false });
+ expect(mocks.closeInstance).toHaveBeenCalledWith({
+ location: 'wrld_close:444',
+ hardClose: false
+ });
expect(mocks.applyInstance).toHaveBeenCalledWith({ id: 'inst_closed' });
- expect(mocks.toastSuccess).toHaveBeenCalledWith('message.instance.closed');
+ expect(mocks.toastSuccess).toHaveBeenCalledWith(
+ 'message.instance.closed'
+ );
});
it('hides launch and invite buttons when invite-self is not allowed', () => {
diff --git a/src/components/__tests__/LocationWorld.test.js b/src/components/__tests__/LocationWorld.test.js
index 5b8f53ef..fbdce6b0 100644
--- a/src/components/__tests__/LocationWorld.test.js
+++ b/src/components/__tests__/LocationWorld.test.js
@@ -7,7 +7,11 @@ const mocks = vi.hoisted(() => ({
showLaunchDialog: vi.fn(),
showGroupDialog: vi.fn(),
getGroupName: vi.fn(() => Promise.resolve('Fetched Group')),
- parseLocation: vi.fn(() => ({ isRealInstance: true, tag: 'wrld_1:inst_1', groupId: 'grp_1' }))
+ parseLocation: vi.fn(() => ({
+ isRealInstance: true,
+ tag: 'wrld_1:inst_1',
+ groupId: 'grp_1'
+ }))
}));
vi.mock('pinia', async (importOriginal) => {
@@ -102,13 +106,19 @@ describe('LocationWorld.vue', () => {
mocks.showGroupDialog.mockClear();
mocks.getGroupName.mockClear();
mocks.parseLocation.mockClear();
- mocks.parseLocation.mockImplementation(() => ({ isRealInstance: true, tag: 'wrld_1:inst_1', groupId: 'grp_1' }));
+ mocks.parseLocation.mockImplementation(() => ({
+ isRealInstance: true,
+ tag: 'wrld_1:inst_1',
+ groupId: 'grp_1'
+ }));
});
it('renders translated access type and instance name', () => {
const wrapper = mountComponent();
- expect(wrapper.text()).toContain('dialog.world.instance.friends #Instance Name');
+ expect(wrapper.text()).toContain(
+ 'dialog.world.instance.friends #Instance Name'
+ );
expect(wrapper.find('.flags.eu').exists()).toBe(true);
});
@@ -119,7 +129,10 @@ describe('LocationWorld.vue', () => {
await wrapper.findAll('.cursor-pointer')[0].trigger('click');
- expect(mocks.showLaunchDialog).toHaveBeenCalledWith('wrld_1:inst_1', 'short-1');
+ expect(mocks.showLaunchDialog).toHaveBeenCalledWith(
+ 'wrld_1:inst_1',
+ 'short-1'
+ );
});
it('shows group hint and opens group dialog', async () => {
diff --git a/src/components/dialogs/AvatarDialog/AvatarDialog.vue b/src/components/dialogs/AvatarDialog/AvatarDialog.vue
index 6924a85d..f92d0cbd 100644
--- a/src/components/dialogs/AvatarDialog/AvatarDialog.vue
+++ b/src/components/dialogs/AvatarDialog/AvatarDialog.vue
@@ -695,11 +695,7 @@
const platforms = [];
if (ref.unityPackages) {
for (const unityPackage of ref.unityPackages) {
- if (
- unityPackage.variant &&
- unityPackage.variant !== 'standard' &&
- unityPackage.variant !== 'security'
- ) {
+ if (unityPackage.variant && unityPackage.variant !== 'standard' && unityPackage.variant !== 'security') {
// skip imposters
continue;
}
diff --git a/src/components/dialogs/CustomNavDialog.vue b/src/components/dialogs/CustomNavDialog.vue
index ea88232f..ae495a9b 100644
--- a/src/components/dialogs/CustomNavDialog.vue
+++ b/src/components/dialogs/CustomNavDialog.vue
@@ -426,12 +426,7 @@
if (byId) return byId;
}
- if (
- allowIndexFallback &&
- typeof entity.index === 'number' &&
- entity.index >= 0 &&
- entity.index < nodes.length
- ) {
+ if (allowIndexFallback && typeof entity.index === 'number' && entity.index >= 0 && entity.index < nodes.length) {
return nodes[entity.index] || null;
}
@@ -620,8 +615,7 @@
const sourceNode =
(sourceIdSnapshot
? visibleNodes.find(
- (node) =>
- node.id === sourceIdSnapshot && node.type === (sourceIsFolderSnapshot ? 'folder' : 'item')
+ (node) => node.id === sourceIdSnapshot && node.type === (sourceIsFolderSnapshot ? 'folder' : 'item')
)
: null) || resolveNodeFromDnDEntity(source, visibleNodes);
if (!sourceNode) return;
diff --git a/src/components/dialogs/GroupDialog/GroupDialogInfoTab.vue b/src/components/dialogs/GroupDialog/GroupDialogInfoTab.vue
index b29aa518..fed1a9a8 100644
--- a/src/components/dialogs/GroupDialog/GroupDialogInfoTab.vue
+++ b/src/components/dialogs/GroupDialog/GroupDialogInfoTab.vue
@@ -381,8 +381,7 @@
const { showFullscreenImageDialog } = useGalleryStore();
const instanceStore = useInstanceStore();
- const { pastCalenderEvents, upcomingCalenderEvents, updateFollowingCalendarData } =
- useGroupCalendarEvents(groupDialog);
+ const { pastCalenderEvents, upcomingCalenderEvents, updateFollowingCalendarData } = useGroupCalendarEvents(groupDialog);
/**
*
diff --git a/src/components/dialogs/GroupDialog/GroupMemberModerationDialog.vue b/src/components/dialogs/GroupDialog/GroupMemberModerationDialog.vue
index 80363d47..a2a05131 100644
--- a/src/components/dialogs/GroupDialog/GroupMemberModerationDialog.vue
+++ b/src/components/dialogs/GroupDialog/GroupMemberModerationDialog.vue
@@ -122,11 +122,7 @@
import { useI18n } from 'vue-i18n';
import { useAppearanceSettingsStore, useGalleryStore, useGroupStore, useUserStore } from '../../../stores';
- import {
- applyGroupMember,
- handleGroupMember,
- handleGroupMemberProps
- } from '../../../coordinators/groupCoordinator';
+ import { applyGroupMember, handleGroupMember, handleGroupMemberProps } from '../../../coordinators/groupCoordinator';
import { hasGroupPermission } from '../../../shared/utils';
import { useUserDisplay } from '../../../composables/useUserDisplay';
import { groupDialogFilterOptions, groupDialogSortingOptions } from '../../../shared/constants';
diff --git a/src/components/dialogs/GroupDialog/GroupMemberModerationExportDialog.vue b/src/components/dialogs/GroupDialog/GroupMemberModerationExportDialog.vue
index 4545ae6c..12785c26 100644
--- a/src/components/dialogs/GroupDialog/GroupMemberModerationExportDialog.vue
+++ b/src/components/dialogs/GroupDialog/GroupMemberModerationExportDialog.vue
@@ -74,13 +74,7 @@
{ label: 'description', text: 'dialog.group_member_moderation.description' },
{ label: 'data', text: 'dialog.group_member_moderation.data' }
];
- const checkedGroupLogsExportLogsOptions = ref([
- 'created_at',
- 'eventType',
- 'actorDisplayName',
- 'description',
- 'data'
- ]);
+ const checkedGroupLogsExportLogsOptions = ref(['created_at', 'eventType', 'actorDisplayName', 'description', 'data']);
/**
*
diff --git a/src/components/dialogs/GroupDialog/__tests__/GroupDialogPhotosTab.test.js b/src/components/dialogs/GroupDialog/__tests__/GroupDialogPhotosTab.test.js
index 753cb796..5c9387c0 100644
--- a/src/components/dialogs/GroupDialog/__tests__/GroupDialogPhotosTab.test.js
+++ b/src/components/dialogs/GroupDialog/__tests__/GroupDialogPhotosTab.test.js
@@ -10,7 +10,7 @@ vi.mock('vue-i18n', () => ({
locale: require('vue').ref('en')
}),
createI18n: () => ({
- global: { t: (key) => key , locale: require('vue').ref('en') },
+ global: { t: (key) => key, locale: require('vue').ref('en') },
install: vi.fn()
})
}));
diff --git a/src/components/dialogs/GroupDialog/__tests__/GroupModerationBulkActions.test.js b/src/components/dialogs/GroupDialog/__tests__/GroupModerationBulkActions.test.js
index a4ab902f..9ec8e1d9 100644
--- a/src/components/dialogs/GroupDialog/__tests__/GroupModerationBulkActions.test.js
+++ b/src/components/dialogs/GroupDialog/__tests__/GroupModerationBulkActions.test.js
@@ -3,12 +3,11 @@ import { mount } from '@vue/test-utils';
vi.mock('vue-i18n', () => ({
useI18n: () => ({
- t: (key) => key
- ,
- locale: require('vue').ref('en')
- }),
+ t: (key) => key,
+ locale: require('vue').ref('en')
+ }),
createI18n: () => ({
- global: { t: (key) => key , locale: require('vue').ref('en') },
+ global: { t: (key) => key, locale: require('vue').ref('en') },
install: vi.fn()
})
}));
@@ -53,7 +52,8 @@ function mountComponent(props = {}) {
Trash2: { template: '' },
X: { template: '' },
TooltipWrapper: {
- template: '
'
+ template:
+ '
'
}
}
}
@@ -68,24 +68,32 @@ describe('GroupModerationBulkActions.vue', () => {
describe('rendering', () => {
test('renders user ID input field', () => {
const wrapper = mountComponent();
- expect(wrapper.text()).toContain('dialog.group_member_moderation.user_id');
+ expect(wrapper.text()).toContain(
+ 'dialog.group_member_moderation.user_id'
+ );
});
test('renders selected users section', () => {
const wrapper = mountComponent();
- expect(wrapper.text()).toContain('dialog.group_member_moderation.selected_users');
+ expect(wrapper.text()).toContain(
+ 'dialog.group_member_moderation.selected_users'
+ );
});
test('renders roles dropdown with available roles', () => {
const wrapper = mountComponent();
- expect(wrapper.text()).toContain('dialog.group_member_moderation.selected_roles');
+ expect(wrapper.text()).toContain(
+ 'dialog.group_member_moderation.selected_roles'
+ );
});
test('renders action buttons', () => {
const wrapper = mountComponent();
const text = wrapper.text();
expect(text).toContain('dialog.group_member_moderation.add_roles');
- expect(text).toContain('dialog.group_member_moderation.remove_roles');
+ expect(text).toContain(
+ 'dialog.group_member_moderation.remove_roles'
+ );
expect(text).toContain('dialog.group_member_moderation.save_note');
expect(text).toContain('dialog.group_member_moderation.kick');
expect(text).toContain('dialog.group_member_moderation.ban');
@@ -95,8 +103,18 @@ describe('GroupModerationBulkActions.vue', () => {
test('renders selected user badges', () => {
const wrapper = mountComponent({
selectedUsersArray: [
- { id: 'usr_1', userId: 'usr_1', membershipStatus: 'member', user: { displayName: 'Alice' } },
- { id: 'usr_2', userId: 'usr_2', membershipStatus: 'member', user: { displayName: 'Bob' } }
+ {
+ id: 'usr_1',
+ userId: 'usr_1',
+ membershipStatus: 'member',
+ user: { displayName: 'Alice' }
+ },
+ {
+ id: 'usr_2',
+ userId: 'usr_2',
+ membershipStatus: 'member',
+ user: { displayName: 'Bob' }
+ }
]
});
expect(wrapper.text()).toContain('Alice');
@@ -106,54 +124,88 @@ describe('GroupModerationBulkActions.vue', () => {
test('shows warning tooltip for non-member users', () => {
const wrapper = mountComponent({
selectedUsersArray: [
- { id: 'usr_1', userId: 'usr_1', membershipStatus: 'banned', user: { displayName: 'Charlie' } }
+ {
+ id: 'usr_1',
+ userId: 'usr_1',
+ membershipStatus: 'banned',
+ user: { displayName: 'Charlie' }
+ }
]
});
- expect(wrapper.text()).toContain('dialog.group_member_moderation.user_isnt_in_group');
+ expect(wrapper.text()).toContain(
+ 'dialog.group_member_moderation.user_isnt_in_group'
+ );
});
test('does not show warning for member users', () => {
const wrapper = mountComponent({
selectedUsersArray: [
- { id: 'usr_1', userId: 'usr_1', membershipStatus: 'member', user: { displayName: 'Alice' } }
+ {
+ id: 'usr_1',
+ userId: 'usr_1',
+ membershipStatus: 'member',
+ user: { displayName: 'Alice' }
+ }
]
});
- expect(wrapper.text()).not.toContain('dialog.group_member_moderation.user_isnt_in_group');
+ expect(wrapper.text()).not.toContain(
+ 'dialog.group_member_moderation.user_isnt_in_group'
+ );
});
});
describe('progress indicator', () => {
test('shows progress when progressCurrent > 0', () => {
- const wrapper = mountComponent({ progressCurrent: 3, progressTotal: 10 });
- expect(wrapper.text()).toContain('dialog.group_member_moderation.progress');
+ const wrapper = mountComponent({
+ progressCurrent: 3,
+ progressTotal: 10
+ });
+ expect(wrapper.text()).toContain(
+ 'dialog.group_member_moderation.progress'
+ );
expect(wrapper.text()).toContain('3/10');
});
test('shows cancel button during progress', () => {
- const wrapper = mountComponent({ progressCurrent: 3, progressTotal: 10 });
- expect(wrapper.text()).toContain('dialog.group_member_moderation.cancel');
+ const wrapper = mountComponent({
+ progressCurrent: 3,
+ progressTotal: 10
+ });
+ expect(wrapper.text()).toContain(
+ 'dialog.group_member_moderation.cancel'
+ );
});
test('hides progress when not in progress', () => {
const wrapper = mountComponent({ progressCurrent: 0 });
- expect(wrapper.text()).not.toContain('dialog.group_member_moderation.progress');
+ expect(wrapper.text()).not.toContain(
+ 'dialog.group_member_moderation.progress'
+ );
});
});
describe('button disabled states', () => {
test('add/remove roles disabled when no roles selected', () => {
const wrapper = mountComponent({ selectedRoles: [] });
- const addBtn = wrapper.findAll('button').find((b) =>
- b.text().includes('dialog.group_member_moderation.add_roles')
- );
+ const addBtn = wrapper
+ .findAll('button')
+ .find((b) =>
+ b
+ .text()
+ .includes('dialog.group_member_moderation.add_roles')
+ );
expect(addBtn.attributes('disabled')).toBeDefined();
});
test('add/remove roles enabled when roles are selected', () => {
const wrapper = mountComponent({ selectedRoles: ['role_1'] });
- const addBtn = wrapper.findAll('button').find((b) =>
- b.text().includes('dialog.group_member_moderation.add_roles')
- );
+ const addBtn = wrapper
+ .findAll('button')
+ .find((b) =>
+ b
+ .text()
+ .includes('dialog.group_member_moderation.add_roles')
+ );
expect(addBtn.attributes('disabled')).toBeUndefined();
});
@@ -163,25 +215,35 @@ describe('GroupModerationBulkActions.vue', () => {
progressCurrent: 5,
progressTotal: 10
});
- const kickBtn = wrapper.findAll('button').find((b) =>
- b.text().includes('dialog.group_member_moderation.kick')
- );
+ const kickBtn = wrapper
+ .findAll('button')
+ .find((b) =>
+ b.text().includes('dialog.group_member_moderation.kick')
+ );
expect(kickBtn.attributes('disabled')).toBeDefined();
});
test('select user button disabled when no user ID entered', () => {
const wrapper = mountComponent({ selectUserId: '' });
- const selectBtn = wrapper.findAll('button').find((b) =>
- b.text().includes('dialog.group_member_moderation.select_user')
- );
+ const selectBtn = wrapper
+ .findAll('button')
+ .find((b) =>
+ b
+ .text()
+ .includes('dialog.group_member_moderation.select_user')
+ );
expect(selectBtn.attributes('disabled')).toBeDefined();
});
test('select user button enabled when user ID is entered', () => {
const wrapper = mountComponent({ selectUserId: 'usr_test' });
- const selectBtn = wrapper.findAll('button').find((b) =>
- b.text().includes('dialog.group_member_moderation.select_user')
- );
+ const selectBtn = wrapper
+ .findAll('button')
+ .find((b) =>
+ b
+ .text()
+ .includes('dialog.group_member_moderation.select_user')
+ );
expect(selectBtn.attributes('disabled')).toBeUndefined();
});
});
@@ -194,9 +256,11 @@ describe('GroupModerationBulkActions.vue', () => {
_mockPermissions: ['group-bans-manage']
}
});
- const kickBtn = wrapper.findAll('button').find((b) =>
- b.text().includes('dialog.group_member_moderation.kick')
- );
+ const kickBtn = wrapper
+ .findAll('button')
+ .find((b) =>
+ b.text().includes('dialog.group_member_moderation.kick')
+ );
expect(kickBtn.attributes('disabled')).toBeDefined();
});
@@ -207,12 +271,16 @@ describe('GroupModerationBulkActions.vue', () => {
_mockPermissions: ['group-members-remove']
}
});
- const banBtn = wrapper.findAll('button').find((b) =>
- b.text().includes('dialog.group_member_moderation.ban')
- );
- const unbanBtn = wrapper.findAll('button').find((b) =>
- b.text().includes('dialog.group_member_moderation.unban')
- );
+ const banBtn = wrapper
+ .findAll('button')
+ .find((b) =>
+ b.text().includes('dialog.group_member_moderation.ban')
+ );
+ const unbanBtn = wrapper
+ .findAll('button')
+ .find((b) =>
+ b.text().includes('dialog.group_member_moderation.unban')
+ );
expect(banBtn.attributes('disabled')).toBeDefined();
expect(unbanBtn.attributes('disabled')).toBeDefined();
});
@@ -221,9 +289,13 @@ describe('GroupModerationBulkActions.vue', () => {
describe('events', () => {
test('emits select-user on select button click', async () => {
const wrapper = mountComponent({ selectUserId: 'usr_test' });
- const selectBtn = wrapper.findAll('button').find((b) =>
- b.text().includes('dialog.group_member_moderation.select_user')
- );
+ const selectBtn = wrapper
+ .findAll('button')
+ .find((b) =>
+ b
+ .text()
+ .includes('dialog.group_member_moderation.select_user')
+ );
await selectBtn.trigger('click');
expect(wrapper.emitted('select-user')).toBeTruthy();
});
@@ -241,7 +313,12 @@ describe('GroupModerationBulkActions.vue', () => {
});
test('emits delete-user when removing a selected user', async () => {
- const user = { id: 'usr_1', userId: 'usr_1', membershipStatus: 'member', user: { displayName: 'Alice' } };
+ const user = {
+ id: 'usr_1',
+ userId: 'usr_1',
+ membershipStatus: 'member',
+ user: { displayName: 'Alice' }
+ };
const wrapper = mountComponent({ selectedUsersArray: [user] });
// The X button is a native