diff --git a/.eslintrc.js b/.eslintrc.js index aa0da332..706c027e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,21 +1,45 @@ -module.exports = { - extends: [ - 'eslint-config-airbnb-base', - 'plugin:vue/vue3-strongly-recommended' - ], - rules: { - 'linebreak-style': 'off', - 'vue/component-definition-name-casing': ['warn', 'kebab-case'], - 'vue/require-default-prop': 'off', - 'vue/attribute-hyphenation': ['warn', 'never'], - 'vue/v-on-event-hyphenation': ['warn', 'never'] - }, - settings: { - 'import/resolver': { - alias: { - map: [['@', './src/']], - extensions: ['.js', '.vue'] - } +module.exports = { + env: { + browser: true, + jest: true + }, + extends: [ + 'eslint-config-airbnb-base', + 'plugin:vue/vue3-recommended' + ], + rules: { + 'linebreak-style': 'off', + 'vue/component-definition-name-casing': ['warn', 'kebab-case'], + 'vue/require-default-prop': 'off', + 'vue/attribute-hyphenation': ['warn', 'never'], + 'vue/v-on-event-hyphenation': ['warn', 'never'], + 'object-curly-newline': ['error', { consistent: true }], + 'function-paren-newline': ['error', 'never'], + 'operator-linebreak': ['error', 'before'], + 'implicit-arrow-linebreak': ['error', 'below'], + 'comma-dangle': ['error', 'never'], + indent: ['error', 4], + 'vue/html-indent': 'off', + 'vue/html-closing-bracket-newline': ['error', { + singleline: 'never', + multiline: 'never' + }], + 'vue/html-self-closing': ['error', { + html: { + void: 'any', + normal: 'any', + component: 'any' + }, + svg: 'always', + math: 'always' + }] + }, + settings: { + 'import/resolver': { + alias: { + map: [['@', './src/']], + extensions: ['.js', '.vue'] + } + } } - } -}; \ No newline at end of file +}; diff --git a/package-lock.json b/package-lock.json index 08d9d17a..a2a2b4e6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,7 +39,8 @@ "eslint-plugin-vue": "9.8.0", "jest": "^27.0.5", "sass": "^1.32.7", - "sass-loader": "^12.0.0" + "sass-loader": "^12.0.0", + "vitest": "^0.32.4" } }, "node_modules/@achrinza/node-ipc": { @@ -1774,6 +1775,358 @@ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", "dev": true }, + "node_modules/@esbuild/android-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.17.19.tgz", + "integrity": "sha512-rIKddzqhmav7MSmoFCmDIb6e2W57geRsM94gV2l38fzhXMwq7hZoClug9USI2pFRGL06f4IOPHHpFNOkWieR8A==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.17.19.tgz", + "integrity": "sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.17.19.tgz", + "integrity": "sha512-uUTTc4xGNDT7YSArp/zbtmbhO0uEEK9/ETW29Wk1thYUJBz3IVnvgEiEwEa9IeLyvnpKrWK64Utw2bgUmDveww==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.17.19.tgz", + "integrity": "sha512-80wEoCfF/hFKM6WE1FyBHc9SfUblloAWx6FJkFWTWiCoht9Mc0ARGEM47e67W9rI09YoUxJL68WHfDRYEAvOhg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.17.19.tgz", + "integrity": "sha512-IJM4JJsLhRYr9xdtLytPLSH9k/oxR3boaUIYiHkAawtwNOXKE8KoU8tMvryogdcT8AU+Bflmh81Xn6Q0vTZbQw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.19.tgz", + "integrity": "sha512-pBwbc7DufluUeGdjSU5Si+P3SoMF5DQ/F/UmTSb8HXO80ZEAJmrykPyzo1IfNbAoaqw48YRpv8shwd1NoI0jcQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.17.19.tgz", + "integrity": "sha512-4lu+n8Wk0XlajEhbEffdy2xy53dpR06SlzvhGByyg36qJw6Kpfk7cp45DR/62aPH9mtJRmIyrXAS5UWBrJT6TQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.17.19.tgz", + "integrity": "sha512-cdmT3KxjlOQ/gZ2cjfrQOtmhG4HJs6hhvm3mWSRDPtZ/lP5oe8FWceS10JaSJC13GBd4eH/haHnqf7hhGNLerA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.17.19.tgz", + "integrity": "sha512-ct1Tg3WGwd3P+oZYqic+YZF4snNl2bsnMKRkb3ozHmnM0dGWuxcPTTntAF6bOP0Sp4x0PjSF+4uHQ1xvxfRKqg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.17.19.tgz", + "integrity": "sha512-w4IRhSy1VbsNxHRQpeGCHEmibqdTUx61Vc38APcsRbuVgK0OPEnQ0YD39Brymn96mOx48Y2laBQGqgZ0j9w6SQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.17.19.tgz", + "integrity": "sha512-2iAngUbBPMq439a+z//gE+9WBldoMp1s5GWsUSgqHLzLJ9WoZLZhpwWuym0u0u/4XmZ3gpHmzV84PonE+9IIdQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.17.19.tgz", + "integrity": "sha512-LKJltc4LVdMKHsrFe4MGNPp0hqDFA1Wpt3jE1gEyM3nKUvOiO//9PheZZHfYRfYl6AwdTH4aTcXSqBerX0ml4A==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.17.19.tgz", + "integrity": "sha512-/c/DGybs95WXNS8y3Ti/ytqETiW7EU44MEKuCAcpPto3YjQbyK3IQVKfF6nbghD7EcLUGl0NbiL5Rt5DMhn5tg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.17.19.tgz", + "integrity": "sha512-FC3nUAWhvFoutlhAkgHf8f5HwFWUL6bYdvLc/TTuxKlvLi3+pPzdZiFKSWz/PF30TB1K19SuCxDTI5KcqASJqA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.17.19.tgz", + "integrity": "sha512-IbFsFbxMWLuKEbH+7sTkKzL6NJmG2vRyy6K7JJo55w+8xDk7RElYn6xvXtDW8HCfoKBFK69f3pgBJSUSQPr+4Q==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.17.19.tgz", + "integrity": "sha512-68ngA9lg2H6zkZcyp22tsVt38mlhWde8l3eJLWkyLrp4HwMUr3c1s/M2t7+kHIhvMjglIBrFpncX1SzMckomGw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.17.19.tgz", + "integrity": "sha512-CwFq42rXCR8TYIjIfpXCbRX0rp1jo6cPIUPSaWwzbVI4aOfX96OXY8M6KNmtPcg7QjYeDmN+DD0Wp3LaBOLf4Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.17.19.tgz", + "integrity": "sha512-cnq5brJYrSZ2CF6c35eCmviIN3k3RczmHz8eYaVlNasVqsNY+JKohZU5MKmaOI+KkllCdzOKKdPs762VCPC20g==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.17.19.tgz", + "integrity": "sha512-vCRT7yP3zX+bKWFeP/zdS6SqdWB8OIpaRq/mbXQxTGHnIxspRtigpkUcDMlSCOejlHowLqII7K2JKevwyRP2rg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.17.19.tgz", + "integrity": "sha512-yYx+8jwowUstVdorcMdNlzklLYhPxjniHWFKgRqH7IFlUEa0Umu3KuYplf1HUZZ422e3NU9F4LGb+4O0Kdcaag==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.17.19.tgz", + "integrity": "sha512-eggDKanJszUtCdlVs0RB+h35wNlb5v4TWEkq4vZcmVt5u/HiDZrTXe2bWFQUez3RgNHwx/x4sk5++4NSSicKkw==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.17.19.tgz", + "integrity": "sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, "node_modules/@eslint/eslintrc": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.3.3.tgz", @@ -3099,6 +3452,21 @@ "@types/node": "*" } }, + "node_modules/@types/chai": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz", + "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==", + "dev": true + }, + "node_modules/@types/chai-subset": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@types/chai-subset/-/chai-subset-1.3.3.tgz", + "integrity": "sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw==", + "dev": true, + "dependencies": { + "@types/chai": "*" + } + }, "node_modules/@types/connect": { "version": "3.4.35", "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", @@ -3370,6 +3738,222 @@ "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==", "dev": true }, + "node_modules/@vitest/expect": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.32.4.tgz", + "integrity": "sha512-m7EPUqmGIwIeoU763N+ivkFjTzbaBn0n9evsTOcde03ugy2avPs3kZbYmw3DkcH1j5mxhMhdamJkLQ6dM1bk/A==", + "dev": true, + "dependencies": { + "@vitest/spy": "0.32.4", + "@vitest/utils": "0.32.4", + "chai": "^4.3.7" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.32.4.tgz", + "integrity": "sha512-cHOVCkiRazobgdKLnczmz2oaKK9GJOw6ZyRcaPdssO1ej+wzHVIkWiCiNacb3TTYPdzMddYkCgMjZ4r8C0JFCw==", + "dev": true, + "dependencies": { + "@vitest/utils": "0.32.4", + "p-limit": "^4.0.0", + "pathe": "^1.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^1.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vitest/runner/node_modules/yocto-queue": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", + "integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==", + "dev": true, + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vitest/snapshot": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.32.4.tgz", + "integrity": "sha512-IRpyqn9t14uqsFlVI2d7DFMImGMs1Q9218of40bdQQgMePwVdmix33yMNnebXcTzDU5eiV3eUsoxxH5v0x/IQA==", + "dev": true, + "dependencies": { + "magic-string": "^0.30.0", + "pathe": "^1.1.1", + "pretty-format": "^29.5.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot/node_modules/@jest/schemas": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", + "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.25.16" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@vitest/snapshot/node_modules/@sinclair/typebox": { + "version": "0.25.24", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", + "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", + "dev": true + }, + "node_modules/@vitest/snapshot/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@vitest/snapshot/node_modules/magic-string": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz", + "integrity": "sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.13" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@vitest/snapshot/node_modules/pretty-format": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", + "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.4.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@vitest/snapshot/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/@vitest/spy": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.32.4.tgz", + "integrity": "sha512-oA7rCOqVOOpE6rEoXuCOADX7Lla1LIa4hljI2MSccbpec54q+oifhziZIJXxlE/CvI2E+ElhBHzVu0VEvJGQKQ==", + "dev": true, + "dependencies": { + "tinyspy": "^2.1.1" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.32.4.tgz", + "integrity": "sha512-Gwnl8dhd1uJ+HXrYyV0eRqfmk9ek1ASE/LWfTCuWMw+d07ogHqp4hEAV28NiecimK6UY9DpSEPh+pXBA5gtTBg==", + "dev": true, + "dependencies": { + "diff-sequences": "^29.4.3", + "loupe": "^2.3.6", + "pretty-format": "^29.5.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils/node_modules/@jest/schemas": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.4.3.tgz", + "integrity": "sha512-VLYKXQmtmuEz6IxJsrZwzG9NvtkQsWNnWMsKxqWNu3+CnfzJQhp0WDDKWLVV9hLKr0l3SLLFRqcYHjhtyuDVxg==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.25.16" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@vitest/utils/node_modules/@sinclair/typebox": { + "version": "0.25.24", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.25.24.tgz", + "integrity": "sha512-XJfwUVUKDHF5ugKwIcxEgc9k8b7HbznCp6eUfWgu710hMPNIO4aw4/zB5RogDQz8nd6gyCDpU9O/m6qYEWY6yQ==", + "dev": true + }, + "node_modules/@vitest/utils/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@vitest/utils/node_modules/diff-sequences": { + "version": "29.4.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.4.3.tgz", + "integrity": "sha512-ofrBgwpPhCD85kMKtE9RYFFq6OC1A89oW2vvgWZNCwxrUpRUILopY7lsYyMDSjc8g6U6aiO0Qubg6r4Wgt5ZnA==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@vitest/utils/node_modules/pretty-format": { + "version": "29.5.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.5.0.tgz", + "integrity": "sha512-V2mGkI31qdttvTFX7Mt4efOqHXqJWMu4/r66Xh3Z3BwZaPfPJgp6/gbwoujRpPUtfEF6AUUWx3Jim3GCw5g/Qw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.4.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@vitest/utils/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, "node_modules/@vue/babel-helper-vue-jsx-merge-props": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.4.0.tgz", @@ -4335,9 +4919,9 @@ } }, "node_modules/acorn": { - "version": "8.8.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.0.tgz", - "integrity": "sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz", + "integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==", "dev": true, "bin": { "acorn": "bin/acorn" @@ -4645,6 +5229,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/assertion-error": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", + "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/async": { "version": "2.6.4", "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", @@ -5251,6 +5844,15 @@ "node": ">= 0.8" } }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/call-bind": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", @@ -5329,6 +5931,24 @@ "node": ">=4" } }, + "node_modules/chai": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", + "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", + "dev": true, + "dependencies": { + "assertion-error": "^1.1.0", + "check-error": "^1.0.2", + "deep-eql": "^4.1.2", + "get-func-name": "^2.0.0", + "loupe": "^2.3.1", + "pathval": "^1.1.1", + "type-detect": "^4.0.5" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", @@ -5352,6 +5972,15 @@ "node": ">=10" } }, + "node_modules/check-error": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", + "integrity": "sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -6290,6 +6919,18 @@ "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", "dev": true }, + "node_modules/deep-eql": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz", + "integrity": "sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==", + "dev": true, + "dependencies": { + "type-detect": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/deep-equal": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.1.0.tgz", @@ -6964,6 +7605,43 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/esbuild": { + "version": "0.17.19", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.17.19.tgz", + "integrity": "sha512-XQ0jAPFkK/u3LcVRcvVHQcTIqD6E2H1fvZMA5dQPSOWb3suUbWbfbRf94pjc0bNzRYLfIrDRQXr7X+LHIm5oHw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.17.19", + "@esbuild/android-arm64": "0.17.19", + "@esbuild/android-x64": "0.17.19", + "@esbuild/darwin-arm64": "0.17.19", + "@esbuild/darwin-x64": "0.17.19", + "@esbuild/freebsd-arm64": "0.17.19", + "@esbuild/freebsd-x64": "0.17.19", + "@esbuild/linux-arm": "0.17.19", + "@esbuild/linux-arm64": "0.17.19", + "@esbuild/linux-ia32": "0.17.19", + "@esbuild/linux-loong64": "0.17.19", + "@esbuild/linux-mips64el": "0.17.19", + "@esbuild/linux-ppc64": "0.17.19", + "@esbuild/linux-riscv64": "0.17.19", + "@esbuild/linux-s390x": "0.17.19", + "@esbuild/linux-x64": "0.17.19", + "@esbuild/netbsd-x64": "0.17.19", + "@esbuild/openbsd-x64": "0.17.19", + "@esbuild/sunos-x64": "0.17.19", + "@esbuild/win32-arm64": "0.17.19", + "@esbuild/win32-ia32": "0.17.19", + "@esbuild/win32-x64": "0.17.19" + } + }, "node_modules/escalade": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", @@ -8216,6 +8894,15 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-func-name": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", + "integrity": "sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/get-intrinsic": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.3.tgz", @@ -11975,6 +12662,12 @@ "node": ">=6" } }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", @@ -12108,6 +12801,18 @@ "json5": "lib/cli.js" } }, + "node_modules/local-pkg": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.4.3.tgz", + "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", @@ -12379,6 +13084,15 @@ "node": ">=4" } }, + "node_modules/loupe": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-2.3.6.tgz", + "integrity": "sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA==", + "dev": true, + "dependencies": { + "get-func-name": "^2.0.0" + } + }, "node_modules/lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", @@ -12694,6 +13408,18 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/mlly": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.4.0.tgz", + "integrity": "sha512-ua8PAThnTwpprIaU47EPeZ/bPUVp2QYBbWMphUQpVdBI3Lgqzm5KZQ45Agm3YJedHXaIHl6pBGabaLSUPPSptg==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "pathe": "^1.1.1", + "pkg-types": "^1.0.3", + "ufo": "^1.1.2" + } + }, "node_modules/module-alias": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/module-alias/-/module-alias-2.2.2.tgz", @@ -12740,9 +13466,15 @@ } }, "node_modules/nanoid": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", - "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", + "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "bin": { "nanoid": "bin/nanoid.cjs" }, @@ -13411,6 +14143,21 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.1.tgz", + "integrity": "sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==", + "dev": true + }, + "node_modules/pathval": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", + "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", + "dev": true, + "engines": { + "node": "*" + } + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -13487,6 +14234,17 @@ "node": ">=8" } }, + "node_modules/pkg-types": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.0.3.tgz", + "integrity": "sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A==", + "dev": true, + "dependencies": { + "jsonc-parser": "^3.2.0", + "mlly": "^1.2.0", + "pathe": "^1.1.0" + } + }, "node_modules/portfinder": { "version": "1.0.32", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.32.tgz", @@ -13511,9 +14269,9 @@ } }, "node_modules/postcss": { - "version": "8.4.16", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.16.tgz", - "integrity": "sha512-ipHE1XBvKzm5xI7hiHCZJCSugxvsdq2mPnsq5+UF+VHCjiBvtDrlxJfMBToWaP9D5XlgNmcFGqoHmUn0EYEaRQ==", + "version": "8.4.24", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz", + "integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==", "funding": [ { "type": "opencollective", @@ -13522,10 +14280,14 @@ { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" } ], "dependencies": { - "nanoid": "^3.3.4", + "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -14647,6 +15409,22 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/rollup": { + "version": "3.26.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.26.0.tgz", + "integrity": "sha512-YzJH0eunH2hr3knvF3i6IkLO/jTjAEwU4HoMUbQl4//Tnl3ou0e7P5SjxdDr8HQJdeUJShlbEHXrrnEHy1l7Yg==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -15023,6 +15801,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true + }, "node_modules/sigmund": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", @@ -15215,6 +15999,12 @@ "node": ">=8" } }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true + }, "node_modules/stackframe": { "version": "1.3.4", "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", @@ -15230,6 +16020,12 @@ "node": ">= 0.8" } }, + "node_modules/std-env": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.3.3.tgz", + "integrity": "sha512-Rz6yejtVyWnVjC1RFvNmYL10kgjC49EOghxWn0RFqlCHGFpQx+Xe7yW3I4ceK1SGrWIGMjD5Kbue8W/udkbMJg==", + "dev": true + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -15376,6 +16172,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-literal": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.0.1.tgz", + "integrity": "sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q==", + "dev": true, + "dependencies": { + "acorn": "^8.8.2" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/stylehacks": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.0.tgz", @@ -15665,6 +16473,30 @@ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", "dev": true }, + "node_modules/tinybench": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.0.tgz", + "integrity": "sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==", + "dev": true + }, + "node_modules/tinypool": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-0.5.0.tgz", + "integrity": "sha512-paHQtnrlS1QZYKF/GnLoOM/DN9fqaGOFbCbxzAhwniySnzl9Ebk8w73/dd34DAhe/obUbPAOldTyYXQZxnPBPQ==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.1.1.tgz", + "integrity": "sha512-XPJL2uSzcOyBMky6OFrusqWlzfFrXtE0hPuMgW8A2HmaqrPo4ZQHRN/V0QXN3FSjKxpsbRrFc5LI7KOwBsT1/w==", + "dev": true, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tmpl": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", @@ -15870,6 +16702,12 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/ufo": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.1.2.tgz", + "integrity": "sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ==", + "dev": true + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -16070,6 +16908,166 @@ "vue": "^3.0.0" } }, + "node_modules/vite": { + "version": "4.3.9", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.9.tgz", + "integrity": "sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==", + "dev": true, + "dependencies": { + "esbuild": "^0.17.5", + "postcss": "^8.4.23", + "rollup": "^3.21.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.32.4.tgz", + "integrity": "sha512-L2gIw+dCxO0LK14QnUMoqSYpa9XRGnTTTDjW2h19Mr+GR0EFj4vx52W41gFXfMLqpA00eK4ZjOVYo1Xk//LFEw==", + "dev": true, + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.3.4", + "mlly": "^1.4.0", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "vite": "^3.0.0 || ^4.0.0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": ">=v14.18.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vitest": { + "version": "0.32.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.32.4.tgz", + "integrity": "sha512-3czFm8RnrsWwIzVDu/Ca48Y/M+qh3vOnF16czJm98Q/AN1y3B6PBsyV8Re91Ty5s7txKNjEhpgtGPcfdbh2MZg==", + "dev": true, + "dependencies": { + "@types/chai": "^4.3.5", + "@types/chai-subset": "^1.3.3", + "@types/node": "*", + "@vitest/expect": "0.32.4", + "@vitest/runner": "0.32.4", + "@vitest/snapshot": "0.32.4", + "@vitest/spy": "0.32.4", + "@vitest/utils": "0.32.4", + "acorn": "^8.9.0", + "acorn-walk": "^8.2.0", + "cac": "^6.7.14", + "chai": "^4.3.7", + "debug": "^4.3.4", + "local-pkg": "^0.4.3", + "magic-string": "^0.30.0", + "pathe": "^1.1.1", + "picocolors": "^1.0.0", + "std-env": "^3.3.3", + "strip-literal": "^1.0.1", + "tinybench": "^2.5.0", + "tinypool": "^0.5.0", + "vite": "^3.0.0 || ^4.0.0", + "vite-node": "0.32.4", + "why-is-node-running": "^2.2.2" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": ">=v14.18.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@vitest/browser": "*", + "@vitest/ui": "*", + "happy-dom": "*", + "jsdom": "*", + "playwright": "*", + "safaridriver": "*", + "webdriverio": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + }, + "playwright": { + "optional": true + }, + "safaridriver": { + "optional": true + }, + "webdriverio": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/magic-string": { + "version": "0.30.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.0.tgz", + "integrity": "sha512-LA+31JYDJLs82r2ScLrlz1GjSgu66ZV518eyWT+S8VhyQn/JL0u9MeBOvQMGYiPk1DBiSN9DDMOcXvigJZaViQ==", + "dev": true, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.13" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/vue": { "version": "3.2.38", "resolved": "https://registry.npmjs.org/vue/-/vue-3.2.38.tgz", @@ -16900,6 +17898,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/why-is-node-running": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.2.2.tgz", + "integrity": "sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==", + "dev": true, + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/wildcard": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", diff --git a/package.json b/package.json index 66144ba2..dea685b5 100644 --- a/package.json +++ b/package.json @@ -40,6 +40,7 @@ "eslint-plugin-vue": "9.8.0", "jest": "^27.0.5", "sass": "^1.32.7", - "sass-loader": "^12.0.0" + "sass-loader": "^12.0.0", + "vitest": "^0.32.4" } } diff --git a/src/constants/global-rules.js b/src/constants/global-rules.js new file mode 100644 index 00000000..c78cd07e --- /dev/null +++ b/src/constants/global-rules.js @@ -0,0 +1,22 @@ +/** +* @file global-rules.js +* @author MB +* @copyright Safelite +*/ + +/** + * @summary Contains all the globally defined rules. + */ +const globalRules = { + POLICYHOLDER_FIRST_NAME_REQUIRED: 'policyholder-first-name-required', + POLICYHOLDER_LAST_NAME_REQUIRED: 'policyholder-last-name-required', + FIRST_NAME_REQUIRED: 'first-name-required', + LAST_NAME_REQUIRED: 'last-name-required', + PHONE_NUMBER_REQUIRED: 'phone-number-required', + EMAIL_ADDRESS_REQUIRED: 'email-required', + EMAIL_ADDRESS_FORMAT: 'email-address-format', + PHONE_NUMBER_FORMAT: 'phone-number-format', + OPTION_REQUIRED: 'option-required' +}; + +export default globalRules; diff --git a/src/digital-components/textarea-question/textarea-question.spec.js b/src/digital-components/textarea-question/textarea-question.spec.js new file mode 100644 index 00000000..8e4d93c6 --- /dev/null +++ b/src/digital-components/textarea-question/textarea-question.spec.js @@ -0,0 +1,348 @@ +// Components +import textareaQuestion from '@/digital-components/textarea-question/textarea-question.vue'; + +// Supporting Files +import { shallowMount } from '@vue/test-utils'; +import { getRandomString, getRandomInt } from '@/helpers/data-generation'; +import { nextTick } from 'vue'; +import { defineRule } from 'vee-validate'; +import { required } from '@/helpers/validation-rules'; + +describe('textarea-question.vue', () => { + const mockMixin = { + methods: { + getCmsContent: jest.fn().mockImplementation(() => + getRandomString(10, 20)), + setCmsContent: jest.fn() + } + }; + describe('Expected components rendered', () => { + test('Label rendered', () => { + // Arrange + const questionText = getRandomString(10, 20); + const mixinWithQuestion = { + methods: { + getCmsContent: jest.fn().mockImplementation(() => + questionText), + setCmsContent: jest.fn() + } + }; + const wrapper = shallowMount(textareaQuestion, { + propsData: { + inputId: getRandomString(10, 20), + cmsWidgetName: getRandomString(10, 20) + }, + mixins: [mixinWithQuestion] + }); + + // Act + const label = wrapper.find('label'); + + // Assert + expect(label.exists()).toBe(true); + expect(wrapper.text()).toContain(questionText); + }); + test('Textarea rendered', () => { + // Arrange + const wrapper = shallowMount(textareaQuestion, { + propsData: { + inputId: getRandomString(10, 20), + cmsWidgetName: getRandomString(10, 20) + }, + mixins: [mockMixin] + }); + + // Act + const textarea = wrapper.find('textarea'); + + // Assert + expect(textarea.exists()).toBe(true); + }); + test('Character count rendered', () => { + // Arrange + const maxLength = getRandomInt(100, 900); + const wrapper = shallowMount(textareaQuestion, { + propsData: { + inputId: getRandomString(10, 20), + cmsWidgetName: getRandomString(10, 20), + maxLength + }, + mixins: [mockMixin] + }); + const expected = `0/${maxLength}`; + + // Act + // Assert + expect(wrapper.text()).toContain(expected); + }); + test('Error rendered', async () => { + // Arrange + const maxLength = getRandomInt(100, 900); + const wrapper = shallowMount(textareaQuestion, { + propsData: { + inputId: getRandomString(10, 20), + cmsWidgetName: getRandomString(10, 20), + maxLength + }, + mixins: [mockMixin] + }); + + // Act + const errorComponent = wrapper.find('#error-message'); + expect(errorComponent.text()).toBe(''); + + const errorMessage = getRandomString(20, 30); + wrapper.vm.resetField({ + errors: [errorMessage] + }); + await nextTick(); + + // Assert + expect(errorComponent.text()).toBe(errorMessage); + }); + test('Not required => optional text rendered', () => { + // Arrange + const wrapper = shallowMount(textareaQuestion, { + propsData: { + inputId: getRandomString(10, 20), + cmsWidgetName: getRandomString(10, 20), + isRequired: false + }, + mixins: [mockMixin] + }); + + // Act + // Assert + expect(wrapper.text()).toContain('Optional'); + }); + test('Required => optional text not rendered', () => { + // Arrange + const wrapper = shallowMount(textareaQuestion, { + propsData: { + inputId: getRandomString(10, 20), + cmsWidgetName: getRandomString(10, 20), + isRequired: true + }, + mixins: [mockMixin] + }); + + // Act + // Assert + expect(wrapper.text()).not.toContain('Optional'); + }); + }); + describe('Computed properties rendered', () => { + describe('characterCount', () => { + test('Model value null => character count is 0 ', () => { + // Arrange + const wrapper = shallowMount(textareaQuestion, { + propsData: { + inputId: getRandomString(10, 20), + cmsWidgetName: getRandomString(10, 20), + modelValue: null + }, + mixins: [mockMixin] + }); + + // Act + // Assert + expect(wrapper.vm.characterCount).toBe(0); + }); + test('Model value undefined => character count is 0', () => { + // Arrange + const wrapper = shallowMount(textareaQuestion, { + propsData: { + inputId: getRandomString(10, 20), + cmsWidgetName: getRandomString(10, 20), + modelValue: undefined + }, + mixins: [mockMixin] + }); + + // Act + // Assert + expect(wrapper.vm.characterCount).toBe(0); + }); + test('Model value empty string => character count is 0', () => { + // Arrange + const wrapper = shallowMount(textareaQuestion, { + propsData: { + inputId: getRandomString(10, 20), + cmsWidgetName: getRandomString(10, 20), + modelValue: '' + }, + mixins: [mockMixin] + }); + + // Act + // Assert + expect(wrapper.vm.characterCount).toBe(0); + }); + test('Model value non-empty string => character count is as expected', () => { + // Arrange + const length = getRandomInt(10, 30); + const value = getRandomString(length, length); + const wrapper = shallowMount(textareaQuestion, { + propsData: { + inputId: getRandomString(10, 20), + cmsWidgetName: getRandomString(10, 20), + modelValue: value + }, + mixins: [mockMixin] + }); + + // Act + // Assert + expect(wrapper.vm.characterCount).toBe(length); + }); + }); + describe('value', () => { + test('Get value corresponds to modelValue', () => { + // Arrange + const modelValue = getRandomString(10, 20); + const wrapper = shallowMount(textareaQuestion, { + propsData: { + inputId: getRandomString(10, 20), + cmsWidgetName: getRandomString(10, 20), + modelValue + }, + mixins: [mockMixin] + }); + + // Act + // Assert + expect(wrapper.vm.value).toBe(modelValue); + }); + test('Set value => update modelValue event emitted with new value', () => { + // Arrange + const modelValue = getRandomString(10, 20); + const wrapper = shallowMount(textareaQuestion, { + propsData: { + inputId: getRandomString(10, 20), + cmsWidgetName: getRandomString(10, 20), + modelValue + }, + mixins: [mockMixin] + }); + const newValue = getRandomString(10, 20); + + // Act + wrapper.vm.value = newValue; + + // Assert + expect(wrapper.emitted('update:modelValue')).toBeTruthy(); + expect(wrapper.emitted('update:modelValue')[0][0]).toEqual(newValue); + }); + }); + }); + describe('Properties properly affect initial state', () => { + test('Placeholder text sets placeholder text of text area', () => { + // Arrange + const placeholderText = getRandomString(10, 20); + const wrapper = shallowMount(textareaQuestion, { + propsData: { + inputId: getRandomString(10, 20), + cmsWidgetName: getRandomString(10, 20), + placeholderText + }, + mixins: [mockMixin] + }); + + // Act + const textarea = wrapper.find('textarea'); + + // Assert + expect(textarea.attributes().placeholder).toBe(placeholderText); + }); + test('isDisabled true => textarea disabled', () => { + // Arrange + const wrapper = shallowMount(textareaQuestion, { + propsData: { + inputId: getRandomString(10, 20), + cmsWidgetName: getRandomString(10, 20), + isDisabled: true + }, + mixins: [mockMixin] + }); + + // Act + const textarea = wrapper.find('textarea'); + + // Assert + expect(textarea.attributes().disabled).toBeDefined(); + }); + test('isRequired true => textarea required', () => { + // Arrange + const wrapper = shallowMount(textareaQuestion, { + propsData: { + inputId: getRandomString(10, 20), + cmsWidgetName: getRandomString(10, 20), + isRequired: true + }, + mixins: [mockMixin] + }); + + // Act + const textarea = wrapper.find('textarea'); + + // Assert + expect(textarea.attributes().required).toBeDefined(); + }); + test('validationRules set rules of text area', () => { + // Arrange + const rule = getRandomString(10, 20); + const errorMessage = getRandomString(20, 30); + defineRule(rule, required(errorMessage)); + const wrapper = shallowMount(textareaQuestion, { + propsData: { + inputId: getRandomString(10, 20), + cmsWidgetName: getRandomString(10, 20), + validationRules: rule + }, + mixins: [mockMixin] + }); + + // Act + const textarea = wrapper.find('textarea'); + + // Assert + expect(textarea.attributes().validationrules).toBe(rule); + }); + test('maxLength set max length of text area', () => { + // Arrange + const maxLength = toString(getRandomInt(100, 900)); + const wrapper = shallowMount(textareaQuestion, { + propsData: { + inputId: getRandomString(10, 20), + cmsWidgetName: getRandomString(10, 20), + maxLength + }, + mixins: [mockMixin] + }); + + // Act + const textarea = wrapper.find('textarea'); + + // Assert + expect(textarea.attributes().maxlength).toBe(maxLength); + }); + test('inputRows set input rows of text area', () => { + // Arrange + const inputRows = getRandomInt(10, 20); + const wrapper = shallowMount(textareaQuestion, { + propsData: { + inputId: getRandomString(10, 20), + cmsWidgetName: getRandomString(10, 20), + inputRows + }, + mixins: [mockMixin] + }); + + // Act + const textarea = wrapper.find('textarea'); + + // Assert + expect(textarea.attributes().rows).toBe(`${inputRows}`); + }); + }); +}); diff --git a/src/digital-components/textarea-question/textarea-question.vue b/src/digital-components/textarea-question/textarea-question.vue new file mode 100644 index 00000000..9336a1c0 --- /dev/null +++ b/src/digital-components/textarea-question/textarea-question.vue @@ -0,0 +1,197 @@ + + + + + diff --git a/src/digital-components/textbox-question/textbox-question.vue b/src/digital-components/textbox-question/textbox-question.vue index 2a71b795..f7e0d858 100644 --- a/src/digital-components/textbox-question/textbox-question.vue +++ b/src/digital-components/textbox-question/textbox-question.vue @@ -1,325 +1,340 @@ diff --git a/src/helpers/global-rule-definer.js b/src/helpers/global-rule-definer.js new file mode 100644 index 00000000..4763d8e6 --- /dev/null +++ b/src/helpers/global-rule-definer.js @@ -0,0 +1,47 @@ +import { defineRule } from 'vee-validate'; +import { errorMessages } from '@/constants/error-messages'; +import globalRules from '@/constants/global-rules'; +import { required, regex } from '@/helpers/validation-rules'; + +/** + * @summary Define global rules related to names + */ +function defineGlobalNameRules() { + defineRule(globalRules.FIRST_NAME_REQUIRED, required(errorMessages.FIRST_NAME_REQUIRED)); + defineRule(globalRules.LAST_NAME_REQUIRED, required(errorMessages.LAST_NAME_REQUIRED)); + defineRule(globalRules.POLICYHOLDER_FIRST_NAME_REQUIRED, + required(errorMessages.POLICYHOLDER_FIRST_NAME_REQUIRED)); + defineRule(globalRules.POLICYHOLDER_LAST_NAME_REQUIRED, + required(errorMessages.POLICYHOLDER_LAST_NAME_REQUIRED)); +} + +/** + * @summary Define global rules related to email addresses + */ +function defineGlobalEmailRules() { + defineRule(globalRules.EMAIL_ADDRESS_REQUIRED, required(errorMessages.EMAIL_ADDRESS_REQUIRED)); + defineRule(globalRules.EMAIL_ADDRESS_FORMAT, + regex(/^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9_\-.]+)\.([a-zA-Z]{2,})$/, + errorMessages.EMAIL_ADDRESS_FORMAT)); +} + +/** + * @summary Define global rules related to phone numbers + */ +function defineGlobalPhoneNumberRules() { + defineRule(globalRules.PHONE_NUMBER_REQUIRED, required(errorMessages.PHONE_NUMBER_REQUIRED)); + defineRule(globalRules.PHONE_NUMBER_FORMAT, + regex(/^(\([0-9]{3}\)|[0-9]{3}) *[-.]? *[0-9]{3} *[-.]? *[0-9]{4}$/, + errorMessages.PHONE_NUMBER_FORMAT)); +} + +/** + * @summary Define all global rules + */ +export default function defineGlobalRules() { + defineGlobalNameRules(); + defineGlobalEmailRules(); + defineGlobalPhoneNumberRules(); + + defineRule(globalRules.OPTION_REQUIRED, required(errorMessages.OPTION_REQUIRED)); +} diff --git a/src/layouts/address-lookup/customer-questions/customer-questions.vue b/src/layouts/address-lookup/customer-questions/customer-questions.vue index f4062fe6..349d0702 100644 --- a/src/layouts/address-lookup/customer-questions/customer-questions.vue +++ b/src/layouts/address-lookup/customer-questions/customer-questions.vue @@ -8,7 +8,7 @@ ref="firstName" inputId="08497a2efd9a4a73a70360ab47b4838d" disableAutoFill - validationRules="first-name-required" /> + :validationRules="rules.firstName" />
@@ -19,21 +19,15 @@ ref="lastName" inputId="0030e56a57e74a4ab92de7fb8e97fec5" disableAutoFill - validationRules="last-name-required" /> + :validationRules="rules.lastName" />
- diff --git a/src/layouts/molding-questions/molding-questions.vue b/src/layouts/molding-questions/molding-questions.vue index e06dfe58..c842a312 100644 --- a/src/layouts/molding-questions/molding-questions.vue +++ b/src/layouts/molding-questions/molding-questions.vue @@ -12,7 +12,7 @@ :alertFewMoreQuestionsHeader="AlertFewMoreQuestionsHeader" :alertFewMoreQuestionsCopy="AlertFewMoreQuestionsCopy" :questionsData="questionsData" - validationRules="questions-required" + :validationRules="rules.optionRequired" v-model="selectedAnswers" @forwardButtonAction="forwardButtonAction" @back-click="navigateBack" @@ -25,9 +25,7 @@ // Import Supporting Files import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { settleAllPromises } from "@/helpers/layout-helper"; -import { defineRule } from "vee-validate"; -import { required } from "@/helpers/validation-rules"; -import { errorMessages } from "@/constants/error-messages"; +import globalRules from '@/constants/global-rules'; import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin"; import { useMainStore } from "@/store"; import { issPageValues } from "@/router/router-constants/issPage-values"; @@ -37,9 +35,6 @@ import BaseFormMixin from '@/mixins/base-form-mixin.js'; import { Form } from "vee-validate"; import questionsPageLayout from "@/iss-components/questions-page-layout/questions-page-layout.vue"; -// DEFINE VALIDATION RULES -defineRule("questions-required", required(errorMessages.OPTION_REQUIRED)); - export default { name: "molding-questions", mixins: [BaseFormMixin, vehicleQuestionsMixin], @@ -65,6 +60,9 @@ export default { questionsData: [], selectedAnswers: {}, currentGlassIndex: 0, + rules: { + optionRequired: globalRules.OPTION_REQUIRED + } }; }, computed: { diff --git a/src/layouts/part-questions/part-questions.vue b/src/layouts/part-questions/part-questions.vue index 58a60621..e53e6dcf 100644 --- a/src/layouts/part-questions/part-questions.vue +++ b/src/layouts/part-questions/part-questions.vue @@ -6,7 +6,7 @@ :alertFewMoreQuestionsHeader="AlertFewMoreQuestionsHeader" :alertFewMoreQuestionsCopy="AlertFewMoreQuestionsCopy" :questionsData="questionsData" - validationRules="questions-required" + :validationRules="rules.optionRequired" v-model="selectedAnswers" @forwardButtonAction="forwardButtonAction" @back-click="navigateBack" @@ -23,14 +23,10 @@ import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { settleAllPromises } from "@/helpers/layout-helper"; import { useMainStore } from '@/store'; import { issPageValues } from "@/router/router-constants/issPage-values"; -import { Form, defineRule } from "vee-validate"; -import { required } from "@/helpers/validation-rules"; -import { errorMessages } from "@/constants/error-messages"; +import { Form } from "vee-validate"; import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin"; import BaseFormMixin from '@/mixins/base-form-mixin.js'; - -// DEFINE VALIDATION RULES -defineRule("questions-required", required(errorMessages.OPTION_REQUIRED)); +import globalRules from '@/constants/global-rules'; export default { name: "part-questions", @@ -59,6 +55,9 @@ export default { questionsData: [], selectedAnswers: {}, currentGlassIndex: 0, + rules: { + optionRequired: globalRules.OPTION_REQUIRED + } }; }, computed: { diff --git a/src/layouts/policy-holder-details/policy-holder-details.vue b/src/layouts/policy-holder-details/policy-holder-details.vue index 42c266b2..a8e3e963 100644 --- a/src/layouts/policy-holder-details/policy-holder-details.vue +++ b/src/layouts/policy-holder-details/policy-holder-details.vue @@ -15,7 +15,7 @@ isRequired ref="policyHolderFirstName" disableAutoFill - validationRules="first-name-required" /> + :validationRules="rules.firstName" /> + :validationRules="rules.lastName" /> + :validationRules="rules.optionRequired" />
@@ -44,7 +44,6 @@ // Import Supporting Files import { fetchCmsContentForPage, setupModalLinks, processIfStatements } from '@/helpers/cms-content-helper'; import { settleAllPromises } from "@/helpers/layout-helper"; -import { required } from "@/helpers/validation-rules"; import { errorMessages } from "@/constants/error-messages"; import buttonQuestion from "@/digital-components/button-question/button-question"; import contentGroupModal from "@/iss-components/content-group-modal/content-group-modal"; @@ -52,7 +51,7 @@ import { issPageValues } from "@/router/router-constants/issPage-values"; // Import Component import baseFormMixin from "@/mixins/base-form-mixin"; -import { Form, defineRule } from "vee-validate"; +import { Form } from "vee-validate"; import siteFooter from "@/iss-components/site-footer/site-footer"; import siteHeader from "@/iss-components/site-header/site-header"; import siteSubHeader from "@/iss-components/site-sub-header/site-sub-header"; @@ -61,9 +60,8 @@ import recalModal from "@/layouts/coverage-statement/recal-modal/recal-modal"; import steeringModal from "@/layouts/provider-preference/steering-modal/steering-modal"; import shopPreferenceModal from "@/layouts/provider-preference/shop-preference-modal/shop-preference-modal"; import tpaRecalModal from "@/layouts/provider-preference/tpa-recal-modal/tpa-recal-modal.vue" +import globalRules from '@/constants/global-rules'; -// DEFINE VALIDATION RULES -defineRule('option-required', required(errorMessages.OPTION_REQUIRED)); const options = { SAFELITE: 'SafeliteOption', TPA: 'TPAOption' }; export default { @@ -88,6 +86,9 @@ export default { selectedProvider : null, showSteeringLink: false, tpaAcknowledgement: false, + rules: { + optionRequired: globalRules.OPTION_REQUIRED + } }; }, async beforeRouteEnter(to, from, next) { diff --git a/src/layouts/provider-preference/tpa-recal-modal/tpa-recal-modal.vue b/src/layouts/provider-preference/tpa-recal-modal/tpa-recal-modal.vue index 5aaea389..57035130 100644 --- a/src/layouts/provider-preference/tpa-recal-modal/tpa-recal-modal.vue +++ b/src/layouts/provider-preference/tpa-recal-modal/tpa-recal-modal.vue @@ -13,7 +13,7 @@

@@ -52,8 +52,7 @@ import { required } from '@/helpers/validation-rules'; import { errorMessages } from '@/constants/error-messages'; import { Form, defineRule } from 'vee-validate'; import { allGlassPartsAndItemsHavePrices } from '@/layouts/service-packages/service-package-helper/service-package-helper' - -defineRule('option-required', required(errorMessages.OPTION_REQUIRED)); +import globalRules from "@/constants/global-rules"; const store = useMainStore(); @@ -112,7 +111,10 @@ export default { selectedVaps: [], availableLineItems: [], supportingItems: [], - pricedGlassParts: [] + pricedGlassParts: [], + rules: { + optionRequired: globalRules.OPTION_REQUIRED + } }; }, computed: { diff --git a/src/layouts/vehicle-lookup/vehicle-lookup.spec.js b/src/layouts/vehicle-lookup/vehicle-lookup.spec.js index 398ce254..ede695c3 100644 --- a/src/layouts/vehicle-lookup/vehicle-lookup.spec.js +++ b/src/layouts/vehicle-lookup/vehicle-lookup.spec.js @@ -8,6 +8,10 @@ import {vinLookupMethodSelections} from '@/constants/vin-lookup-methods'; import { useMainStore } from '@/store'; import { createTestingPinia } from '@pinia/testing'; import { mapStores } from "pinia"; +import { defineRule } from 'vee-validate'; +import { errorMessages } from '@/constants/error-messages'; +import globalRules from '@/constants/global-rules'; +import { required } from '@/helpers/validation-rules'; const pinia = createTestingPinia(); useMainStore(pinia); @@ -44,6 +48,7 @@ const siteFooterWidgetMockData = { }; function setupMocks() { + defineRule(globalRules.OPTION_REQUIRED, required(errorMessages.OPTION_REQUIRED)); const mockRoute = { query: { issPage: 'vehicle-lookup', diff --git a/src/layouts/vehicle-lookup/vin-lookup-methods/vin-lookup-methods.vue b/src/layouts/vehicle-lookup/vin-lookup-methods/vin-lookup-methods.vue index 392dbdfa..82077f0a 100644 --- a/src/layouts/vehicle-lookup/vin-lookup-methods/vin-lookup-methods.vue +++ b/src/layouts/vehicle-lookup/vin-lookup-methods/vin-lookup-methods.vue @@ -5,7 +5,7 @@ button-type-string="listButton" :question-text="questionTextFromCms" is-required - validation-rules="option-required" + :validation-rules="rules.optionRequired" data-test-id="vin-lookup-methods-button-question" /> @@ -13,32 +13,30 @@