From 669d1505a847909f3e5cc4360bf6f901db1a7c0c Mon Sep 17 00:00:00 2001 From: Yves Lavoie Date: Sun, 7 Apr 2024 18:04:36 -0400 Subject: [PATCH 01/17] Move eslint config from package.json to eslint.config.js for ESLint 9 --- UI/eslint.config.mjs | 218 +++++++++++++++++++++++++++++ UI/package.json | 256 ++-------------------------------- UI/yarn.lock | 322 +++++++++++++++++++++---------------------- 3 files changed, 387 insertions(+), 409 deletions(-) create mode 100644 UI/eslint.config.mjs diff --git a/UI/eslint.config.mjs b/UI/eslint.config.mjs new file mode 100644 index 0000000000..5bf6e86bd8 --- /dev/null +++ b/UI/eslint.config.mjs @@ -0,0 +1,218 @@ +/** @format */ + +import globals from "globals"; +import babelParser from "@babel/eslint-parser"; +// import compatPlugin from "eslint-plugin-compat"; +import eslintConfigESLint from "eslint-config-eslint"; +import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended"; +// import importPlugin from "eslint-plugin-import"; +import js from "@eslint/js"; +import jest from "eslint-plugin-jest"; +import packageJson from "eslint-plugin-package-json/configs/recommended"; +import pluginVue from "eslint-plugin-vue"; + +export default [ + js.configs.recommended, + eslintPluginPrettierRecommended, + ...pluginVue.configs["flat/recommended"], // Why global? + // compatPlugin.configs["flat/recommended"], + // importPlugin.configs["flat/recommended"], + + // Global config + { + ignores: ["{js,node_modules,__mocks__}/**/*.js"] + }, + // Config files + { + ...eslintConfigESLint, + files: ["**/*.config.m?js"] + }, + // JavaScript files + { + files: ["**/*.js"], + ignores: ["**/*.spec.js", "**/*.config.m?js"], + languageOptions: { + globals: { + ...globals.browser, + ...globals.es6, + ...globals.amd, + ...globals.node + }, + ecmaVersion: 6, + sourceType: "module", + parser: babelParser, + parserOptions: { + requireConfigFile: false, + templateSettings: { + evaluate: ["[%", "%]"], + interpolate: ["[%", "%]"], + escape: ["[%", "%]"] + } + } + }, + plugins: { + // "compat", // Not yet compatible with eslint 9 + // "import", // Not yet compatible with eslint 9 + }, + rules: { + ...js.configs.recommended.rules, + camelcase: "off", + // "compat/compat": "warn", // Not yet compatible with eslint 9 + "consistent-return": "error", + curly: ["error", "all"], + "dot-notation": "error", + eqeqeq: "error", + "func-names": 0, + "global-require": "error", + "guard-for-in": "error", + "new-cap": 0, + "no-alert": "error", + "no-console": "error", + "no-continue": 0, + "no-else-return": "error", + "no-lonely-if": "error", + "no-multi-assign": "error", + "no-multi-spaces": "off", + "no-new-object": "error", + "no-param-reassign": "error", + "no-plusplus": 0, + "no-restricted-globals": "error", + "no-shadow": "error", + "no-template-curly-in-string": "error", + "no-undef": "error", + "no-underscore-dangle": 0, + "no-unused-expressions": "error", + "no-unused-vars": "error", + "no-use-before-define": "error", + "no-useless-escape": "error", + "no-useless-return": "error", + "one-var": [ + "error", + { + initialized: "never", + uninitialized: "consecutive" + } + ], + radix: "error", + "spaced-comment": [ + "error", + "always", + { + block: { + balanced: true + } + } + ], + "vars-on-top": 0, + yoda: "error", + "no-restricted-syntax": ["error", "SequenceExpression"] + } + }, + // Package.json + { + files: ["package.json"], + ...packageJson, + rules: { + ...packageJson.rules, + "package-json/order-properties": [ + "error", + { + order: [ + "name", + "version", + "lockfileVersion", + "private", + "publishConfig", + "description", + "keywords", + "author", + "license", + "maintainers", + "contributors", + "bundlesize", + "main", + "browser", + "_browserslist-comment", + "browserslist", + "bugs", + "repository", + "files", + "bin", + "directories", + "man", + "config", + "dependencies", + "devDependencies", + "peerDependencies", + "optionalDependencies", + "bundledDependencies", + "homepage", + "scripts", + "engines", + "os", + "cpu", + "babel", + "eslintConfig", + "prettier", + "stylelint", + "lint-staged" + ] + } + ], + "package-json/sort-collections": [ + "error", + ["scripts", "devDependencies", "dependencies", "config"] + ], + "prettier/prettier": [ + "error", + { + tabWidth: 2 + } + ] + } + }, + // Test files + { + files: [ + "**/__tests__/**/*.[jt]s?(x)", + "**/?(*.)+(spec|test).[tj]s?(x)" + ], + ...jest.configs["flat/recommended"], + rules: { + ...jest.configs["flat/recommended"].rules, + "jest/prefer-expect-assertions": "off", + "jest/no-commented-out-tests": "off", + "jest/no-disabled-tests": "warn", + "jest/no-focused-tests": "error", + "jest/no-identical-title": "error", + "jest/prefer-to-have-length": "warn", + "jest/valid-expect": "error", + "no-console": "off", + camelcase: "off" + } + }, + // Vue files + { + files: ["**/*.vue"], + rules: { + "vue/attribute-hyphenation": "off", + "vue/block-order": [ + "error", + { + order: [ + "script:not([setup])", + "script[setup]", + "template", + "style:not([scoped])", + "style[scoped]" + ] + } + ], + "vue/first-attribute-linebreak": "off", + "vue/html-indent": ["error", 4], + "vue/multi-word-component-names": "off", + "vue/no-setup-props-reactivity-loss": "off", + "vue/require-prop-types": "off" + } + } +]; diff --git a/UI/package.json b/UI/package.json index 21c894ff96..628aca168c 100644 --- a/UI/package.json +++ b/UI/package.json @@ -38,7 +38,10 @@ "supports es6-module and supports async-functions and supports xhr2 and supports bloburls and supports css-variables and supports css3-boxsizing and supports border-radius and supports fetch and supports classlist and supports multicolumn and not edge <= 18 and supports css-display-contents and supports same-site-cookie-attribute" ], "bugs": "https://github.com/ledgersmb/LedgerSMB/issues", - "repository": "ledgersmb/LedgerSMB", + "repository": { + "type": "git", + "url": "https://github.com/ledgersmb/LedgerSMB" + }, "dependencies": { "content-disposition": "0.5.4", "dijit": "1.17.3", @@ -56,6 +59,8 @@ "@babel/eslint-parser": "7.24.6", "@babel/plugin-proposal-object-rest-spread": "7.20.7", "@babel/preset-env": "7.24.6", + "@eslint/js": "9.0.0", + "@eslint/eslintrc":"3.0.2", "@pinia/testing": "0.1.3", "@redocly/cli": "1.14.0", "@vue/test-utils": "2.4.6", @@ -76,16 +81,14 @@ "dojo-util": "1.17.3", "dojo-webpack-plugin": "3.0.6", "ejs-loader": "0.5.0", - "eslint": "8.57.0", + "eslint": "9.0.0", "eslint-config-eslint": "10.0.0", "eslint-config-prettier": "9.1.0", "eslint-import-resolver-webpack": "0.13.8", - "eslint-plugin-amd": "1.1.0", "eslint-plugin-compat": "4.2.0", "eslint-plugin-import": "2.29.1", - "eslint-plugin-jest": "28.5.0", - "eslint-plugin-jsdoc": "48.2.7", - "eslint-plugin-json": "4.0.0", + "eslint-plugin-jest": "28.2.0", + "eslint-plugin-json": "3.1.0", "eslint-plugin-n": "17.7.0", "eslint-plugin-package-json": "0.14.0", "eslint-plugin-prettier": "5.1.3", @@ -95,6 +98,7 @@ "eslint-plugin-vue": "9.26.0", "eslint-webpack-plugin": "4.2.0", "flush-promises": "1.0.2", + "globals": "15.0.0", "html-webpack-plugin": "5.6.0", "http-status-codes": "2.3.0", "i18next-conv": "15.0.0", @@ -146,11 +150,11 @@ "build:dev": "webpack --progress --mode=development --stats errors-warnings", "lint": "yarn run lint:css && yarn run lint:js && yarn run lint:markdown && yarn run lint:vue", "lint:css": "stylelint css/*.css", - "lint:js": "eslint --ext .js ./", - "lint:js:fix": "eslint --fix --ext .js ./", + "lint:js": "eslint ./{src,js-src}/**/*.js", + "lint:js:fix": "eslint --fix ./{src,js-src}/**/*.js", "lint:markdown": "markdownlint --config ../.markdownlint.json --ignore ./node_modules --ignore ./js .", - "lint:vue": "eslint --ext .vue ./", - "lint:vue:fix": "eslint --fix --ext .vue ./", + "lint:vue": "eslint ./src/**/*.vue", + "lint:vue:fix": "eslint --fix ./src/**/*.vue", "profile": "webpack --progress=profile --json > logs/stats.json", "readme": "webpack --mode production --stats errors-warnings", "serve": "webpack serve --mode development", @@ -164,238 +168,6 @@ ] ] }, - "eslintConfig": { - "settings": { - "import/resolver": "webpack" - }, - "overrides": [ - { - "extends": [ - "plugin:package-json/recommended" - ], - "files": [ - "package.json" - ], - "parser": "jsonc-eslint-parser", - "plugins": [ - "package-json" - ], - "rules": { - "package-json/sort-collections": "error", - "indent": [ - "error", - 2 - ] - } - }, - { - "files": [ - "**/__tests__/**/*.[jt]s?(x)", - "**/?(*.)+(spec|test).[tj]s?(x)" - ], - "plugins": [ - "jest" - ], - "extends": [ - "plugin:jest/recommended" - ], - "rules": { - "jest/prefer-expect-assertions": "off", - "jest/no-commented-out-tests": "off", - "no-console": "off" - } - }, - { - "files": [ - "**/*.vue" - ], - "rules": { - "vue/no-setup-props-destructure": "off" - } - } - ], - "plugins": [ - "amd", - "compat", - "import", - "jest", - "package-json", - "sort-dojo-dependency", - "vue", - "prettier" - ], - "parserOptions": { - "parser": "@babel/eslint-parser", - "ecmaVersion": 6, - "sourceType": "module", - "requireConfigFile": false, - "templateSettings": { - "evaluate": [ - "[%", - "%]" - ], - "interpolate": [ - "[%", - "%]" - ], - "escape": [ - "[%", - "%]" - ] - } - }, - "env": { - "browser": true, - "node": true, - "amd": true, - "es6": true - }, - "extends": [ - "eslint:recommended", - "plugin:import/errors", - "plugin:import/warnings", - "plugin:vue/vue3-recommended", - "prettier" - ], - "ignorePatterns": [ - "dojo/", - "dijit/", - "node_modules/", - "js/", - "**/*.po*", - "pod/**", - "!__mocks__/**" - ], - "rules": { - "compat/compat": "warn", - "consistent-return": "error", - "curly": [ - "error", - "all" - ], - "dot-notation": "error", - "eqeqeq": "error", - "func-names": 0, - "new-cap": 0, - "no-continue": 0, - "no-else-return": "error", - "no-lonely-if": "error", - "no-multi-assign": "error", - "no-multi-spaces": "off", - "no-new-object": "error", - "no-param-reassign": "error", - "no-plusplus": 0, - "no-restricted-globals": "error", - "no-shadow": "error", - "no-template-curly-in-string": "error", - "no-undef": "error", - "no-underscore-dangle": 0, - "no-unused-expressions": "error", - "no-unused-vars": "error", - "no-use-before-define": "error", - "no-useless-escape": "error", - "no-useless-return": "error", - "one-var": [ - "error", - "never" - ], - "radix": "error", - "spaced-comment": [ - "error", - "always", - { - "block": { - "balanced": true - } - } - ], - "vars-on-top": 0, - "yoda": "error", - "amd/no-unused-dependencies": "error", - "amd/obsolete-dependencies": "error", - "amd/sane-dependency-names": "error", - "jest/no-disabled-tests": "warn", - "jest/no-focused-tests": "error", - "jest/no-identical-title": "error", - "jest/prefer-to-have-length": "warn", - "jest/valid-expect": "error", - "package-json/order-properties": [ - "error", - { - "order": [ - "name", - "version", - "lockfileVersion", - "private", - "publishConfig", - "description", - "keywords", - "author", - "license", - "maintainers", - "contributors", - "bundlesize", - "main", - "browser", - "_browserslist-comment", - "browserslist", - "bugs", - "repository", - "files", - "bin", - "directories", - "man", - "config", - "dependencies", - "devDependencies", - "peerDependencies", - "optionalDependencies", - "bundledDependencies", - "homepage", - "scripts", - "engines", - "os", - "cpu", - "babel", - "eslintConfig", - "prettier", - "stylelint", - "lint-staged" - ] - } - ], - "package-json/sort-collections": [ - "error", - [ - "scripts", - "devDependencies", - "dependencies", - "config" - ] - ], - "package-json/valid-package-def": "error", - "no-restricted-syntax": [ - "error", - "SequenceExpression" - ], - "vue/attribute-hyphenation": "off", - "vue/first-attribute-linebreak": "off", - "vue/multi-word-component-names": "off", - "vue/require-prop-types": "off", - "vue/component-tags-order": [ - "error", - { - "order": [ - "script:not([setup])", - "script[setup]", - "template", - "style:not([scoped])", - "style[scoped]" - ] - } - ] - } - }, "stylelint": { "defaultSeverity": "warning", "extends": "stylelint-config-standard", diff --git a/UI/yarn.lock b/UI/yarn.lock index 0235003584..0bce2d4ae2 100644 --- a/UI/yarn.lock +++ b/UI/yarn.lock @@ -1292,18 +1292,6 @@ esquery "^1.5.0" jsdoc-type-pratt-parser "~4.0.0" -"@es-joy/jsdoccomment@~0.43.1": - version "0.43.1" - resolved "https://registry.yarnpkg.com/@es-joy/jsdoccomment/-/jsdoccomment-0.43.1.tgz#4b1979b7b4ff8b596fb19a3aa696a438e44608d7" - integrity sha512-I238eDtOolvCuvtxrnqtlBaw0BwdQuYqK7eA6XIonicMdOOOb75mqdIzkGDUbS04+1Di007rgm9snFRNeVrOog== - dependencies: - "@types/eslint" "^8.56.5" - "@types/estree" "^1.0.5" - "@typescript-eslint/types" "^7.2.0" - comment-parser "1.4.1" - esquery "^1.5.0" - jsdoc-type-pratt-parser "~4.0.0" - "@eslint-community/eslint-plugin-eslint-comments@^4.3.0": version "4.3.0" resolved "https://registry.yarnpkg.com/@eslint-community/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-4.3.0.tgz#e356a280764e14b1db9c94d0be7fab405431e2a6" @@ -1324,6 +1312,21 @@ resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== +"@eslint/eslintrc@3.0.2": + version "3.0.2" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.0.2.tgz#36180f8e85bf34d2fe3ccc2261e8e204a411ab4e" + integrity sha512-wV19ZEGEMAC1eHgrS7UQPqsdEiCIbTKTasEfcXAigzoXICcqZSjBZEHlZwNVvKg6UBCjSlos84XiLqsRJnIcIg== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^10.0.1" + globals "^14.0.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + "@eslint/eslintrc@^2.1.4": version "2.1.4" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" @@ -1339,10 +1342,25 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@8.57.0": - version "8.57.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" - integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== +"@eslint/eslintrc@^3.0.2": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-3.1.0.tgz#dbd3482bfd91efa663cbe7aa1f506839868207b6" + integrity sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^10.0.1" + globals "^14.0.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@9.0.0": + version "9.0.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-9.0.0.tgz#1a9e4b4c96d8c7886e0110ed310a0135144a1691" + integrity sha512-RThY/MnKrhubF6+s1JflwUjPEsnCEmYCWwqa/aRISKWNXGZ9epUwft4bUMM35SdKF9xvBrLydAM1RDHd1Z//ZQ== "@eslint/js@^9.0.0": version "9.1.1" @@ -1359,12 +1377,12 @@ resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.0.tgz#0709e9f4cb252351c609c6e6d8d6779a8d25edff" integrity sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA== -"@humanwhocodes/config-array@^0.11.14": - version "0.11.14" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" - integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== +"@humanwhocodes/config-array@^0.12.3": + version "0.12.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.12.3.tgz#a6216d90f81a30bedd1d4b5d799b47241f318072" + integrity sha512-jsNnTBlMWuTpDkeE3on7+dWJi0D6fdDfeANj/w7MpS8ztROCoLvIO2nG0CcFj+E4k8j4QrSTh4Oryi3i2G669g== dependencies: - "@humanwhocodes/object-schema" "^2.0.2" + "@humanwhocodes/object-schema" "^2.0.3" debug "^4.3.1" minimatch "^3.0.5" @@ -1373,10 +1391,10 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== -"@humanwhocodes/object-schema@^2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz#d9fae00a2d5cb40f92cfe64b47ad749fbc38f917" - integrity sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw== +"@humanwhocodes/object-schema@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3" + integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA== "@inquirer/confirm@^3.0.0": version "3.0.0" @@ -2031,14 +2049,6 @@ "@types/estree" "*" "@types/json-schema" "*" -"@types/eslint@^8.56.5": - version "8.56.5" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.56.5.tgz#94b88cab77588fcecdd0771a6d576fa1c0af9d02" - integrity sha512-u5/YPJHo1tvkSF2CE0USEkxon82Z5DBy2xR+qfyYNszpX9qcs4sT6uq2kBbj4BXY1+DBGDPnrhMZV3pKWGNukw== - dependencies: - "@types/estree" "*" - "@types/json-schema" "*" - "@types/estree@*", "@types/estree@^1.0.5": version "1.0.5" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" @@ -2124,7 +2134,7 @@ "@types/tough-cookie" "*" parse5 "^7.0.0" -"@types/json-schema@*", "@types/json-schema@^7.0.15", "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": +"@types/json-schema@*", "@types/json-schema@^7.0.12", "@types/json-schema@^7.0.7", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== @@ -2205,7 +2215,7 @@ resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.2.tgz#ed279a64fa438bb69f2480eda44937912bb7480a" integrity sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow== -"@types/semver@^7.5.8": +"@types/semver@^7.5.0": version "7.5.8" resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== @@ -2310,58 +2320,53 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/scope-manager@7.8.0": - version "7.8.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.8.0.tgz#bb19096d11ec6b87fb6640d921df19b813e02047" - integrity sha512-viEmZ1LmwsGcnr85gIq+FCYI7nO90DVbE37/ll51hjv9aG+YZMb4WDE2fyWpUR4O/UrhGRpYXK/XajcGTk2B8g== +"@typescript-eslint/scope-manager@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz#ea8a9bfc8f1504a6ac5d59a6df308d3a0630a2b1" + integrity sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg== dependencies: - "@typescript-eslint/types" "7.8.0" - "@typescript-eslint/visitor-keys" "7.8.0" + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" -"@typescript-eslint/types@7.8.0", "@typescript-eslint/types@^7.2.0": - version "7.8.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.8.0.tgz#1fd2577b3ad883b769546e2d1ef379f929a7091d" - integrity sha512-wf0peJ+ZGlcH+2ZS23aJbOv+ztjeeP8uQ9GgwMJGVLx/Nj9CJt17GWgWWoSmoRVKAX2X+7fzEnAjxdvK2gqCLw== +"@typescript-eslint/types@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d" + integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg== -"@typescript-eslint/typescript-estree@7.8.0": - version "7.8.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.8.0.tgz#b028a9226860b66e623c1ee55cc2464b95d2987c" - integrity sha512-5pfUCOwK5yjPaJQNy44prjCwtr981dO8Qo9J9PwYXZ0MosgAbfEMB008dJ5sNo3+/BN6ytBPuSvXUg9SAqB0dg== +"@typescript-eslint/typescript-estree@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz#c47ae7901db3b8bddc3ecd73daff2d0895688c46" + integrity sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ== dependencies: - "@typescript-eslint/types" "7.8.0" - "@typescript-eslint/visitor-keys" "7.8.0" + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/visitor-keys" "6.21.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" - minimatch "^9.0.4" - semver "^7.6.0" - ts-api-utils "^1.3.0" + minimatch "9.0.3" + semver "^7.5.4" + ts-api-utils "^1.0.1" -"@typescript-eslint/utils@^6.0.0 || ^7.0.0": - version "7.8.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.8.0.tgz#57a79f9c0c0740ead2f622e444cfaeeb9fd047cd" - integrity sha512-L0yFqOCflVqXxiZyXrDr80lnahQfSOfc9ELAAZ75sqicqp2i36kEZZGuUymHNFoYOqxRT05up760b4iGsl02nQ== +"@typescript-eslint/utils@^6.0.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.21.0.tgz#4714e7a6b39e773c1c8e97ec587f520840cd8134" + integrity sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ== dependencies: "@eslint-community/eslint-utils" "^4.4.0" - "@types/json-schema" "^7.0.15" - "@types/semver" "^7.5.8" - "@typescript-eslint/scope-manager" "7.8.0" - "@typescript-eslint/types" "7.8.0" - "@typescript-eslint/typescript-estree" "7.8.0" - semver "^7.6.0" + "@types/json-schema" "^7.0.12" + "@types/semver" "^7.5.0" + "@typescript-eslint/scope-manager" "6.21.0" + "@typescript-eslint/types" "6.21.0" + "@typescript-eslint/typescript-estree" "6.21.0" + semver "^7.5.4" -"@typescript-eslint/visitor-keys@7.8.0": - version "7.8.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.8.0.tgz#7285aab991da8bee411a42edbd5db760d22fdd91" - integrity sha512-q4/gibTNBQNA0lGyYQCmWRS5D15n8rXh4QjK3KV+MBPlTYHpfBUT3D3PaPR/HeNiI9W6R7FvlkcGhNyAoP+caA== +"@typescript-eslint/visitor-keys@6.21.0": + version "6.21.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz#87a99d077aa507e20e238b11d56cc26ade45fe47" + integrity sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A== dependencies: - "@typescript-eslint/types" "7.8.0" - eslint-visitor-keys "^3.4.3" - -"@ungap/structured-clone@^1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" - integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== + "@typescript-eslint/types" "6.21.0" + eslint-visitor-keys "^3.4.1" "@vue/compiler-core@3.4.27": version "3.4.27" @@ -2661,7 +2666,7 @@ acorn-walk@^8.0.0, acorn-walk@^8.0.2: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa" integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A== -acorn@^8.0.4, acorn@^8.1.0, acorn@^8.5.0, acorn@^8.7.1, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0: +acorn@^8.0.4, acorn@^8.1.0, acorn@^8.11.3, acorn@^8.5.0, acorn@^8.7.1, acorn@^8.8.1, acorn@^8.8.2, acorn@^8.9.0: version "8.11.3" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== @@ -4124,13 +4129,6 @@ doctrine@^2.1.0: dependencies: esutils "^2.0.2" -doctrine@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" - integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== - dependencies: - esutils "^2.0.2" - doiuse@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/doiuse/-/doiuse-6.0.2.tgz#0161e68a0bbc9525d3cebdfcbe5adb90023793e2" @@ -4589,13 +4587,6 @@ eslint-module-utils@^2.8.0: dependencies: debug "^3.2.7" -eslint-plugin-amd@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-amd/-/eslint-plugin-amd-1.1.0.tgz#ad65b3a54b6dc1fd06a64ca93266ac32766e416d" - integrity sha512-hzgIKeBNktx90EX7kkB87Z596N5M4tpYSawA6Gqlp0GQ0QGMADnF9N/WxizUFrjOZfdKol4GOJMYyacqsI+PHw== - dependencies: - requireindex "~1.1.0" - eslint-plugin-compat@4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/eslint-plugin-compat/-/eslint-plugin-compat-4.2.0.tgz#eeaf80daa1afe495c88a47e9281295acae45c0aa" @@ -4641,26 +4632,12 @@ eslint-plugin-import@2.29.1: semver "^6.3.1" tsconfig-paths "^3.15.0" -eslint-plugin-jest@28.5.0: - version "28.5.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-28.5.0.tgz#b497b795de37f671eaccd38bd83030186ff5dc8d" - integrity sha512-6np6DGdmNq/eBbA7HOUNV8fkfL86PYwBfwyb8n23FXgJNTR8+ot3smRHjza9LGsBBZRypK3qyF79vMjohIL8eQ== +eslint-plugin-jest@28.2.0: + version "28.2.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jest/-/eslint-plugin-jest-28.2.0.tgz#863e2b2bda95eb41981ba9bcf4c44f57dce40a73" + integrity sha512-yRDti/a+f+SMSmNTiT9/M/MzXGkitl8CfzUxnpoQcTyfq8gUrXMriVcWU36W1X6BZSUoyUCJrDAWWUA2N4hE5g== dependencies: - "@typescript-eslint/utils" "^6.0.0 || ^7.0.0" - -eslint-plugin-jsdoc@48.2.7: - version "48.2.7" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-48.2.7.tgz#2610b6fa1a9ba45c8296c2f335e0360bbd238772" - integrity sha512-fYj3roTnkFL9OFFTB129rico8lerC5G8Vp2ZW9SjO9RNWG0exVvI+i/Y8Bpm1ufjR0uvT38xtoab/U0Hp8Ybog== - dependencies: - "@es-joy/jsdoccomment" "~0.43.1" - are-docs-informative "^0.0.2" - comment-parser "1.4.1" - debug "^4.3.4" - escape-string-regexp "^4.0.0" - esquery "^1.5.0" - semver "^7.6.2" - spdx-expression-parse "^4.0.0" + "@typescript-eslint/utils" "^6.0.0" eslint-plugin-jsdoc@^48.2.3: version "48.2.3" @@ -4677,10 +4654,10 @@ eslint-plugin-jsdoc@^48.2.3: semver "^7.6.0" spdx-expression-parse "^4.0.0" -eslint-plugin-json@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-json/-/eslint-plugin-json-4.0.0.tgz#0969f2a80823369e8414125a98c91cc98016ec7a" - integrity sha512-l/P3WTzl2HI8PbwsbDIrZ+6jvwQI4TGuz20ReJkG3Y+gZS5ZurTgx+gBmuLpOgiqMyDJWyJ7+GCjevWtNYQcUg== +eslint-plugin-json@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-json/-/eslint-plugin-json-3.1.0.tgz#251108ba1681c332e0a442ef9513bd293619de67" + integrity sha512-MrlG2ynFEHe7wDGwbUuFPsaT2b1uhuEFhJ+W1f1u+1C2EkXmTYJp4B1aAdQQ8M+CC3t//N/oRKiIVw14L2HR1g== dependencies: lodash "^4.17.21" vscode-json-languageservice "^4.1.6" @@ -4795,7 +4772,7 @@ eslint-scope@5.1.1: esrecurse "^4.3.0" estraverse "^4.1.1" -eslint-scope@^7.1.1, eslint-scope@^7.2.2: +eslint-scope@^7.1.1: version "7.2.2" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== @@ -4803,16 +4780,29 @@ eslint-scope@^7.1.1, eslint-scope@^7.2.2: esrecurse "^4.3.0" estraverse "^5.2.0" +eslint-scope@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-8.0.1.tgz#a9601e4b81a0b9171657c343fb13111688963cfc" + integrity sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + eslint-visitor-keys@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== -eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4.3: +eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1: version "3.4.3" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== +eslint-visitor-keys@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-4.0.0.tgz#e3adc021aa038a2a8e0b2f8b0ce8f66b9483b1fb" + integrity sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw== + eslint-webpack-plugin@4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/eslint-webpack-plugin/-/eslint-webpack-plugin-4.2.0.tgz#41f54b25379908eb9eca8645bc997c90cfdbd34e" @@ -4824,41 +4814,37 @@ eslint-webpack-plugin@4.2.0: normalize-path "^3.0.0" schema-utils "^4.2.0" -eslint@8.57.0: - version "8.57.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" - integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== +eslint@9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.0.0.tgz#6270548758e390343f78c8afd030566d86927d40" + integrity sha512-IMryZ5SudxzQvuod6rUdIUz29qFItWx281VhtFVc2Psy/ZhlCeD/5DT6lBIJ4H3G+iamGJoTln1v+QSuPw0p7Q== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/regexpp" "^4.6.1" - "@eslint/eslintrc" "^2.1.4" - "@eslint/js" "8.57.0" - "@humanwhocodes/config-array" "^0.11.14" + "@eslint/eslintrc" "^3.0.2" + "@eslint/js" "9.0.0" + "@humanwhocodes/config-array" "^0.12.3" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" - "@ungap/structured-clone" "^1.2.0" ajv "^6.12.4" chalk "^4.0.0" cross-spawn "^7.0.2" debug "^4.3.2" - doctrine "^3.0.0" escape-string-regexp "^4.0.0" - eslint-scope "^7.2.2" - eslint-visitor-keys "^3.4.3" - espree "^9.6.1" + eslint-scope "^8.0.1" + eslint-visitor-keys "^4.0.0" + espree "^10.0.1" esquery "^1.4.2" esutils "^2.0.2" fast-deep-equal "^3.1.3" - file-entry-cache "^6.0.1" + file-entry-cache "^8.0.0" find-up "^5.0.0" glob-parent "^6.0.2" - globals "^13.19.0" graphemer "^1.4.0" ignore "^5.2.0" imurmurhash "^0.1.4" is-glob "^4.0.0" is-path-inside "^3.0.3" - js-yaml "^4.1.0" json-stable-stringify-without-jsonify "^1.0.1" levn "^0.4.1" lodash.merge "^4.6.2" @@ -4868,7 +4854,16 @@ eslint@8.57.0: strip-ansi "^6.0.1" text-table "^0.2.0" -espree@^9.0.0, espree@^9.3.1, espree@^9.6.0, espree@^9.6.1: +espree@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-10.0.1.tgz#600e60404157412751ba4a6f3a2ee1a42433139f" + integrity sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww== + dependencies: + acorn "^8.11.3" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^4.0.0" + +espree@^9.0.0, espree@^9.3.1, espree@^9.6.0: version "9.6.1" resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== @@ -5080,12 +5075,12 @@ figures@^3.2.0: dependencies: escape-string-regexp "^1.0.5" -file-entry-cache@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" - integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== +file-entry-cache@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-8.0.0.tgz#7787bddcf1131bffb92636c69457bbc0edd6d81f" + integrity sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ== dependencies: - flat-cache "^3.0.4" + flat-cache "^4.0.0" file-entry-cache@^9.0.0: version "9.0.0" @@ -5163,14 +5158,14 @@ find-up@^6.3.0: locate-path "^7.1.0" path-exists "^5.0.0" -flat-cache@^3.0.4: - version "3.2.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" - integrity sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw== +flat-cache@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.0.tgz#d12437636f83bb8a12b8f300c36fd1614e1c7224" + integrity sha512-EryKbCE/wxpxKniQlyas6PY1I9vwtF3uCBweX+N8KYTCn3Y12RTGtQAJ/bd5pl7kxUAc8v/R3Ake/N17OZiFqA== dependencies: flatted "^3.2.9" - keyv "^4.5.3" - rimraf "^3.0.2" + keyv "^4.5.4" + rimraf "^5.0.5" flat-cache@^5.0.0: version "5.0.0" @@ -5443,6 +5438,11 @@ global-prefix@^3.0.0: kind-of "^6.0.2" which "^1.3.1" +globals@15.0.0, globals@^15.0.0: + version "15.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-15.0.0.tgz#9c6cd4e54327ceaab563b4c17ee5e9d181c03fd2" + integrity sha512-m/C/yR4mjO6pXDTm9/R/SpYTAIyaUB4EOzcaaMEl7mds7Mshct9GfejiJNQGjHHbdMPey13Kpu4TMbYi9ex1pw== + globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" @@ -5455,10 +5455,10 @@ globals@^13.19.0, globals@^13.24.0: dependencies: type-fest "^0.20.2" -globals@^15.0.0: - version "15.0.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-15.0.0.tgz#9c6cd4e54327ceaab563b4c17ee5e9d181c03fd2" - integrity sha512-m/C/yR4mjO6pXDTm9/R/SpYTAIyaUB4EOzcaaMEl7mds7Mshct9GfejiJNQGjHHbdMPey13Kpu4TMbYi9ex1pw== +globals@^14.0.0: + version "14.0.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-14.0.0.tgz#898d7413c29babcf6bafe56fcadded858ada724e" + integrity sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ== globalthis@^1.0.3: version "1.0.3" @@ -6909,7 +6909,7 @@ jsonpointer@5.0.1, jsonpointer@^5.0.0: resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559" integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ== -keyv@^4.5.3, keyv@^4.5.4: +keyv@^4.5.4: version "4.5.4" resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93" integrity sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw== @@ -7322,6 +7322,13 @@ minimatch@9.0.1: dependencies: brace-expansion "^2.0.1" +minimatch@9.0.3, minimatch@^9.0.0, minimatch@^9.0.1: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -7336,13 +7343,6 @@ minimatch@^5.0.1: dependencies: brace-expansion "^2.0.1" -minimatch@^9.0.0, minimatch@^9.0.1: - version "9.0.3" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" - integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== - dependencies: - brace-expansion "^2.0.1" - minimatch@^9.0.4, minimatch@~9.0.4: version "9.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" @@ -8934,13 +8934,6 @@ rimraf@^2.6.3: dependencies: glob "^7.1.3" -rimraf@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" - integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== - dependencies: - glob "^7.1.3" - rimraf@^5.0.5: version "5.0.5" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.5.tgz#9be65d2d6e683447d2e9013da2bf451139a61ccf" @@ -9097,11 +9090,6 @@ semver@^7.0.0, semver@^7.3.5, semver@^7.3.6, semver@^7.5.2, semver@^7.5.3, semve dependencies: lru-cache "^6.0.0" -semver@^7.6.2: - version "7.6.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" - integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== - send@0.18.0: version "0.18.0" resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" @@ -9971,7 +9959,7 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== -ts-api-utils@^1.3.0: +ts-api-utils@^1.0.1: version "1.3.0" resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== From 8aafe7c5b3f74a4468cb86498c1aa92ac0c04ae0 Mon Sep 17 00:00:00 2001 From: Yves Lavoie Date: Wed, 10 Apr 2024 19:15:33 -0400 Subject: [PATCH 02/17] Lint config files --- UI/js-src/webpack-compile-markdown.js | 89 ++++++------ UI/webpack.config.js | 186 +++++++++++++------------- 2 files changed, 139 insertions(+), 136 deletions(-) diff --git a/UI/js-src/webpack-compile-markdown.js b/UI/js-src/webpack-compile-markdown.js index 4e309eea13..1a0f00f072 100644 --- a/UI/js-src/webpack-compile-markdown.js +++ b/UI/js-src/webpack-compile-markdown.js @@ -1,15 +1,14 @@ /** @format */ -const MarkdownInclude = require("markdown-include"); - -const browserslist = require("browserslist"); -const lite = require("caniuse-lite"); -const packageJson = require("../package.json"); -const timestamp = require("unix-timestamp"); +const MarkdownInclude = require("markdown-include"), + browserslist = require("browserslist"), + lite = require("caniuse-lite"), + packageJson = require("../package.json"), + timestamp = require("unix-timestamp"); function _isNextVersion(v1, v2) { - let p1 = v1.match(/(\d+)(\.(\d+))?/); - let p2 = v2.match(/(\d+)(\.(\d+))?/); + let p1 = v1.match(/(\d+)(\.(\d+))?/), + p2 = v2.match(/(\d+)(\.(\d+))?/); return ( v2 && ((+p1[1] === +p2[1] + 1 && !p1[3] && !p2[3]) || @@ -27,6 +26,7 @@ MarkdownInclude.registerPlugin({ .sort() .forEach(function (b) { let [browser, version] = b.split(/\s+/); + // eslint-disable-next-line one-var let category = browser.match( /^(\w+_\w+|android|baidu|bb|kaios|samsung)$/ ) @@ -45,6 +45,7 @@ MarkdownInclude.registerPlugin({ lite.agents[browser].browser; earliest[category][browser].versions = []; } + // eslint-disable-next-line one-var let time = lite.agents[browser].release_date[version]; if (time !== null) { @@ -56,17 +57,16 @@ MarkdownInclude.registerPlugin({ earliest[category][browser].version = version; if (time) { - let ts = timestamp.toDate(time); - let month = "00" + (ts.getMonth() + 1); - let year = - 1900 + - ts.getYear() + - "-" + - month.substr(month.length - 2); + let ts = timestamp.toDate(time), + month = "00" + (ts.getMonth() + 1), + year = + 1900 + + ts.getYear() + + "-" + + month.substr(month.length - 2); earliest[category][browser].year = year; earliest[category][browser].time = time; - } - else { + } else { earliest[category][browser].year = ""; } } @@ -93,15 +93,18 @@ MarkdownInclude.registerPlugin({ ":|:" + "---".padEnd(43, "-") + " |\n"; + // eslint-disable-next-line one-var for (var browser in earliest[c]) { + // eslint-disable-next-line one-var var entry = earliest[c][browser]; - let versions = []; - let v1 = ""; - let v2 = ""; - // Pack versions - let vs = entry.versions.sort((a, b) => - a.localeCompare(b, undefined, { numeric: true }) - ); + let versions = [], + v1 = "", + v2 = "", + // Pack versions + vs = entry.versions.sort((a, b) => + a.localeCompare(b, undefined, { numeric: true }) + ); + // eslint-disable-next-line one-var var v; /* eslint no-cond-assign:0 */ while ((v = vs.shift()) || v1) { @@ -137,13 +140,14 @@ MarkdownInclude.registerPlugin({ v1 = ""; v2 = ""; } - var l = ""; - let line = - "| " + - entry.name.padEnd(19, " ") + - " | " + - entry.year.padEnd(8, " ") + - " | "; + // eslint-disable-next-line one-var + var l = "", + line = + "| " + + entry.name.padEnd(19, " ") + + " | " + + entry.year.padEnd(8, " ") + + " | "; while (versions.length) { while ( versions.length && @@ -177,21 +181,26 @@ MarkdownInclude.registerPlugin({ }); // do something with compiled files -var tmp = require('tmp'); -var fs = require('fs'); +var tmp = require("tmp"), + fs = require("fs"); tmp.file( { - prefix: 'markdown-', - postfix: '.json', + prefix: "markdown-", + postfix: ".json", keep: false }, function (err, path) { - if (err) {throw err;} - fs.writeFileSync(path, `{ - "build" : "../README.md", - "files" : ["../doc/sources/_README.md"] - }`); + if (err) { + throw err; + } + fs.writeFileSync( + path, + `{ + "build" : "../README.md", + "files" : ["../doc/sources/_README.md"] + }` + ); MarkdownInclude.compileFiles(path); } ); diff --git a/UI/webpack.config.js b/UI/webpack.config.js index e8ce4be326..a58eaf0402 100644 --- a/UI/webpack.config.js +++ b/UI/webpack.config.js @@ -1,39 +1,38 @@ /** @format */ -/* eslint global-require:0, no-param-reassign:0, no-unused-vars:0, no-inner-declarations:0 */ +/* eslint global-require:0, no-param-reassign:0, no-unused-vars:0 */ /* global getConfig */ const TARGET = process.env.npm_lifecycle_event; if (TARGET !== "readme") { - const fs = require("fs"); - const glob = require("glob"); - const path = require("path"); - const webpack = require("webpack"); - - const BundleAnalyzerPlugin = - require("webpack-bundle-analyzer").BundleAnalyzerPlugin; - const { CleanWebpackPlugin } = require("clean-webpack-plugin"); // installed via npm - const CompressionPlugin = require("compression-webpack-plugin"); - const CopyWebpackPlugin = require("copy-webpack-plugin"); - const CssMinimizerPlugin = require("css-minimizer-webpack-plugin"); - const DojoWebpackPlugin = require("dojo-webpack-plugin"); - const HtmlWebpackPlugin = require("html-webpack-plugin"); - const MiniCssExtractPlugin = require("mini-css-extract-plugin"); - const StylelintPlugin = require("stylelint-webpack-plugin"); - const UnusedWebpackPlugin = require("unused-webpack-plugin"); - const VirtualModulesPlugin = require("webpack-virtual-modules"); - const { VueLoaderPlugin } = require("vue-loader"); - const { WebpackDeduplicationPlugin } = require("webpack-deduplication-plugin"); - - const argv = require("yargs").argv; - const prodMode = + const fs = require("fs"), + glob = require("glob"), + path = require("path"), + webpack = require("webpack"), + BundleAnalyzerPlugin = + require("webpack-bundle-analyzer").BundleAnalyzerPlugin, + { CleanWebpackPlugin } = require("clean-webpack-plugin"), // installed via npm + CompressionPlugin = require("compression-webpack-plugin"), + CopyWebpackPlugin = require("copy-webpack-plugin"), + CssMinimizerPlugin = require("css-minimizer-webpack-plugin"), + DojoWebpackPlugin = require("dojo-webpack-plugin"), + HtmlWebpackPlugin = require("html-webpack-plugin"), + MiniCssExtractPlugin = require("mini-css-extract-plugin"), + StylelintPlugin = require("stylelint-webpack-plugin"), + UnusedWebpackPlugin = require("unused-webpack-plugin"), + VirtualModulesPlugin = require("webpack-virtual-modules"), + { VueLoaderPlugin } = require("vue-loader"), + // eslint-disable-next-line + { WebpackDeduplicationPlugin } = require("webpack-deduplication-plugin"), + argv = require("yargs").argv, + prodMode = process.env.NODE_ENV === "production" || argv.p || - argv.mode === "production"; + argv.mode === "production", + parallelJobs = process.env.CI ? 2 : true; // Make sure all modules follow desired mode process.env.NODE_ENV = prodMode ? "production" : "development"; - const parallelJobs = process.env.CI ? 2 : true; /* FUNCTIONS */ var includedRequires = []; @@ -66,9 +65,11 @@ if (TARGET !== "readme") { let entries = {}; for (var i = 0; i < files.length; i++) { - const entry = files[i]; - const dirName = path.dirname(entry).replace(/\.\/css\/?/,""); - const keyName = (dirName ? dirName + "/" : "" ) + path.basename(entry, path.extname(entry)); + const entry = files[i], + dirName = path.dirname(entry).replace(/\.\/css\/?/, ""), + keyName = + (dirName ? dirName + "/" : "") + + path.basename(entry, path.extname(entry)); entries[keyName] = path.join(__dirname, entry); } return entries; @@ -76,7 +77,7 @@ if (TARGET !== "readme") { // Compute used data-dojo-type glob.sync("**/*.html", { - ignore: ["lib/ui-header.html", "js/**", "node_modules/**"], + ignore: ["lib/ui-header.html", "js/**", "node_modules/**"] // cwd: "." }).map(function (filename) { const requires = findDataDojoTypes(filename); @@ -120,9 +121,8 @@ if (TARGET !== "readme") { exclude: (file) => { return /node_modules/.test(file) || /_scripts/.test(file); } - }; - - const vue = { + }, + vue = { test: /\.vue$/, loader: "vue-loader", options: { @@ -130,20 +130,16 @@ if (TARGET !== "readme") { isCustomElement: (tag) => tag.startsWith("lsmb-") } } - }; - - - const css = { + }, + css = { test: /\.css$/i, use: [MiniCssExtractPlugin.loader, "css-loader"] - }; - - const images = { + }, + images = { test: /\.(png|jpe?g|gif)$/i, type: "asset" - }; - - const html = { + }, + html = { test: /\.html$/, use: [ { @@ -153,61 +149,59 @@ if (TARGET !== "readme") { } } ] - }; - - const svg = { + }, + svg = { test: /\.svg$/, type: "asset/resource" - }; - + }, /* PLUGINS */ - const CleanWebpackPluginOptions = { + CleanWebpackPluginOptions = { dry: false, verbose: false - }; // delete all files in the js directory without deleting this folder - - const StylelintPluginOptions = { + }, // delete all files in the js directory without deleting this folder + StylelintPluginOptions = { files: "**/*.css" - }; - + }, // Copy non-packed resources needed by the app to the release directory - const CopyWebpackPluginOptions = { + CopyWebpackPluginOptions = { patterns: [ { context: "node_modules", from: "dijit/icons/**/*", to: "." }, { context: "node_modules", from: "dijit/nls/**/*", to: "." }, { context: "node_modules", from: "dojo/nls/**/*", to: "." }, - { context: "node_modules", from: "dojo/resources/**/*", to: "." } + { + context: "node_modules", + from: "dojo/resources/**/*", + to: "." + } ], options: { concurrency: 100 } - }; - - const DojoWebpackPluginOptions = { + }, + DojoWebpackPluginOptions = { loaderConfig: require("./js-src/lsmb/webpack.loaderConfig.js"), environment: { dojoRoot: "js" }, // used at run time for non-packed resources (e.g. blank.gif) buildEnvironment: { dojoRoot: "node_modules" }, // used at build time locales: getPOFilenames("src/locales", ".json"), noConsole: true - }; - + }, // dojo/domReady (only works if the DOM is ready when invoked) - const NormalModuleReplacementPluginOptionsDomReady = function (data) { + NormalModuleReplacementPluginOptionsDomReady = function (data) { const match = /^dojo\/domReady!(.*)$/.exec(data.request); + data.request = "dojo/loaderProxy?loader=dojo/domReady!" + match[1]; - }; + }, + NormalModuleReplacementPluginOptionsSVG = function (data) { + var match = /^svg!(.*)$/.exec(data.request); - const NormalModuleReplacementPluginOptionsSVG = function (data) { - var match = /^svg!(.*)$/.exec(data.request); data.request = "dojo/loaderProxy?loader=svg&deps=dojo/text%21" + match[1] + "!" + match[1]; - }; - - const UnusedWebpackPluginOptions = { + }, + UnusedWebpackPluginOptions = { // Source directories directories: [ path.join(__dirname, "js-src/lsmb"), @@ -217,17 +211,15 @@ if (TARGET !== "readme") { exclude: ["*.test.js", "webpack.loaderConfig.js"], // Root directory (optional) root: __dirname - }; - + }, // Generate entries from file pattern - const mapFilenamesToEntries = (pattern) => + mapFilenamesToEntries = (pattern) => glob.sync(pattern).reduce((entries, filename) => { const [, name] = filename.match(/([^/]+)\.css$/); return { ...entries, [name]: filename }; - }, {}); - - const _dijitThemes = "+(claro|nihilo|soria|tundra)"; - const lsmbCSS = { + }, {}), + _dijitThemes = "+(claro|nihilo|soria|tundra)", + lsmbCSS = { ...mapFilenamesToEntries(path.resolve("css/*.css")), ...mapFilenamesToEntries( path.resolve( @@ -238,11 +230,11 @@ if (TARGET !== "readme") { ".css" ) ) - }; - + }, // Compile bootstrap module as a virtual one - const VirtualModulesPluginOptions = { + VirtualModulesPluginOptions = { "./bootstrap.js": + `/* eslint-disable */\n` + `define(["dojo/parser","dojo/ready","` + includedRequires.join('","') + `"], function(parser, ready) {\n` + @@ -252,6 +244,7 @@ if (TARGET !== "readme") { `});` }; + // eslint-disable-next-line one-var var pluginsCommon = [ // Lint the sources new StylelintPlugin(StylelintPluginOptions), @@ -296,11 +289,14 @@ if (TARGET !== "readme") { // Handle HTML new HtmlWebpackPlugin({ - inject: 'body', // Tags are injected manually in the content below + inject: "body", // Tags are injected manually in the content below minify: false, // Adjust t/16-schema-upgrade-html.t if prodMode is used, filename: "ui-header.html", mode: prodMode ? "production" : "development", - excludeChunks: [...Object.keys(lsmbCSS),...Object.keys(globCssEntries("./css/**/*.css"))], + excludeChunks: [ + ...Object.keys(lsmbCSS), + ...Object.keys(globCssEntries("./css/**/*.css")) + ], template: "lib/ui-header.html" }), @@ -336,19 +332,16 @@ if (TARGET !== "readme") { ), __VUE_PROD_DEVTOOLS__: true }) - ]; - - var pluginsProd = [ + ], + pluginsProd = [ ...pluginsCommon, // Statics from build. new webpack.DefinePlugin({ __VUE_PROD_DEVTOOLS__: true }) - ]; - - - var pluginsDev = [ + ], + pluginsDev = [ ...pluginsCommon, new UnusedWebpackPlugin(UnusedWebpackPluginOptions), @@ -360,9 +353,8 @@ if (TARGET !== "readme") { __VUE_OPTIONS_API__: true, __VUE_PROD_DEVTOOLS__: true }) - ]; - - var pluginsList = prodMode + ], + pluginsList = prodMode ? [ // Clean js before building (must be first) new CleanWebpackPlugin(CleanWebpackPluginOptions), @@ -372,6 +364,7 @@ if (TARGET !== "readme") { /* OPTIMIZATIONS */ + // eslint-disable-next-line one-var const optimizationList = { chunkIds: "named", // Keep names to load only 1 theme emitOnErrors: false, @@ -386,7 +379,7 @@ if (TARGET !== "readme") { runtimeChunk: "multiple", splitChunks: { cacheGroups: { - node_modules: { + nodeModules: { test(module) { // `module.resource` contains the absolute path of the file on disk. // Note the usage of `path.sep` instead of / or \, for cross-platform compatibility. @@ -408,11 +401,10 @@ if (TARGET !== "readme") { } } } - }; - + }, /* WEBPACK CONFIG */ - const webpackConfigs = { + webpackConfigs = { experiments: { topLevelAwait: true }, @@ -465,7 +457,9 @@ if (TARGET !== "readme") { performance: { hints: prodMode ? false : "warning", maxAssetSize: prodMode ? 250000 /* the default */ : 10000000, - maxEntrypointSize: prodMode ? 250000 /* the default */ : 10000000 + maxEntrypointSize: prodMode + ? 250000 /* the default */ + : 10000000 }, devtool: prodMode ? "hidden-source-map" : "source-map", @@ -513,11 +507,11 @@ if (TARGET !== "readme") { static: [ { directory: __dirname, - publicPath: '/' + publicPath: "/" }, { directory: __dirname, - publicPath: '/app' + publicPath: "/app" } ], watchFiles: [ From becc7f65dfca0d2b8bfdce8c49610552ee936e74 Mon Sep 17 00:00:00 2001 From: Yves Lavoie Date: Wed, 10 Apr 2024 20:14:21 -0400 Subject: [PATCH 03/17] Lint Dojo files --- UI/js-src/lsmb/parts/PartDescription.js | 3 +-- UI/js-src/lsmb/payments/PostPrintButton.js | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/UI/js-src/lsmb/parts/PartDescription.js b/UI/js-src/lsmb/parts/PartDescription.js index 8c1f555189..4ab69c56ab 100644 --- a/UI/js-src/lsmb/parts/PartDescription.js +++ b/UI/js-src/lsmb/parts/PartDescription.js @@ -1,7 +1,5 @@ /** @format */ -/* eslint no-template-curly-in-string:0 */ - define([ "dijit/form/TextBox", "dijit/_HasDropDown", @@ -30,6 +28,7 @@ define([ channel: null, height: null, store: partRestStore, + // eslint-disable-next-line no-template-curly-in-string queryExpr: "*${0}*", autoComplete: false, highlightMatch: "all", diff --git a/UI/js-src/lsmb/payments/PostPrintButton.js b/UI/js-src/lsmb/payments/PostPrintButton.js index e97ccf710b..9084c77d53 100644 --- a/UI/js-src/lsmb/payments/PostPrintButton.js +++ b/UI/js-src/lsmb/payments/PostPrintButton.js @@ -15,7 +15,7 @@ define([ let base = window.location.pathname.replace(/[^/]*$/, ""); let r = await fetch(base + domattr.get(f, "action"), { method: "POST", - body: domform.toQuery(f), + body: domform.toQuery(f) }); if (r.ok) { From 448f83a42a399aa433ebb03aed8a2a45b9a1e1fb Mon Sep 17 00:00:00 2001 From: Yves Lavoie Date: Wed, 10 Apr 2024 20:29:55 -0400 Subject: [PATCH 04/17] Lint Javascript files --- UI/src/components/ConfigTable.machines.js | 5 +- UI/src/components/ImportCSV-Base.machines.js | 81 ++++++++++---------- UI/src/components/ServerUI.js | 34 ++++---- UI/src/elements/lsmb-base-input.js | 1 + UI/src/elements/lsmb-button.js | 1 + UI/src/elements/lsmb-date.js | 1 + UI/src/elements/lsmb-dijit.js | 2 + UI/src/elements/lsmb-password.js | 1 + UI/src/elements/lsmb-text.js | 1 + UI/src/i18n.js | 4 +- UI/src/main-vue.js | 1 + UI/src/store/configTemplate.js | 4 +- UI/src/store/countries.js | 4 +- UI/src/store/languages.js | 2 +- UI/src/views/LoginPage.machines.js | 81 ++++++++++++-------- 15 files changed, 125 insertions(+), 98 deletions(-) diff --git a/UI/src/components/ConfigTable.machines.js b/UI/src/components/ConfigTable.machines.js index c164e520b3..31670b7a5b 100644 --- a/UI/src/components/ConfigTable.machines.js +++ b/UI/src/components/ConfigTable.machines.js @@ -11,10 +11,7 @@ import { state, transition } from "@/robot-vue"; -import { - progressNotify, - notify -} from "@/machine-helpers.js"; +import { progressNotify, notify } from "@/machine-helpers.js"; function handleError(ctx, error) { return { ...ctx, error }; diff --git a/UI/src/components/ImportCSV-Base.machines.js b/UI/src/components/ImportCSV-Base.machines.js index ffab4e5eb4..01a20f5770 100644 --- a/UI/src/components/ImportCSV-Base.machines.js +++ b/UI/src/components/ImportCSV-Base.machines.js @@ -35,51 +35,50 @@ function submitUpload(ctx) { function createImportMachine(initialContext) { return interpret( - createMachine({ - invalid: state( - transitionFormValid('input','ready'), - ), - ready: state( - transitionFormInvalid('input', 'invalid'), - transition('submit', 'submitting'), - ), - submitting: invoke( - progressNotify(submitUpload), - transition( - 'error', 'ready', - action(notify("submitError"))), - transition( - 'done', 'submitted', - reduce((ctx, e) => ({ ...ctx, response: e.data})), + createMachine( + { + invalid: state(transitionFormValid("input", "ready")), + ready: state( + transitionFormInvalid("input", "invalid"), + transition("submit", "submitting") ), - ), - submitted: state( - immediate('parsing'), - ), - parsing: invoke( - ctx => ctx.response.json(), - transition( - 'done', 'failed', - guard(testNot(testResponseOkFn())), - action(notify("processingError")), + submitting: invoke( + progressNotify(submitUpload), + transition("error", "ready", action(notify("submitError"))), + transition( + "done", + "submitted", + reduce((ctx, e) => ({ ...ctx, response: e.data })) + ) ), - transition( - 'done', 'final', - action(notify("success")), + submitted: state(immediate("parsing")), + parsing: invoke( + (ctx) => ctx.response.json(), + transition( + "done", + "failed", + guard(testNot(testResponseOkFn())), + action(notify("processingError")) + ), + transition("done", "final", action(notify("success"))), + transition( + "error", + "error", + reduce(notify("responseError")) + ) ), - transition( - 'error', 'error', - reduce(notify("responseError"))), - ), - failed: state( - transitionFormValid('input', 'ready'), - transitionFormInvalid('input', 'invalid'), - ), - final: state(), - error: state(), - }, initialCtx => initialCtx), + failed: state( + transitionFormValid("input", "ready"), + transitionFormInvalid("input", "invalid") + ), + final: state(), + error: state() + }, + (initialCtx) => initialCtx + ), () => {}, - initialContext); + initialContext + ); } export { createImportMachine }; diff --git a/UI/src/components/ServerUI.js b/UI/src/components/ServerUI.js index 08777bf54a..d20cb29757 100644 --- a/UI/src/components/ServerUI.js +++ b/UI/src/components/ServerUI.js @@ -1,6 +1,5 @@ /** @format */ - import { h, inject, ref } from "vue"; import { useI18n } from "vue-i18n"; @@ -52,7 +51,8 @@ export default { .removeAttribute("data-lsmb-done"); // chop off the leading '/' to use relative paths let base = window.location.pathname.replace(/[^/]*$/, ""); - let relTgt = (tgt.substring(0, 1) === '/') ? tgt.substring(1) : tgt; + let relTgt = + tgt.substring(0, 1) === "/" ? tgt.substring(1) : tgt; let r = await fetch(base + relTgt, { method: options.method, body: options.data, @@ -77,12 +77,16 @@ export default { let maindiv = document.getElementById("maindiv"); parser.parse(maindiv).then( () => { - registry.findWidgets(maindiv).forEach((child) => { + registry + .findWidgets(maindiv) + .forEach((child) => { this._recursively_resize(child); }); maindiv .querySelectorAll("a") - .forEach((node) => this._interceptClick(node)); + .forEach((node) => + this._interceptClick(node) + ); if (dismiss) { dismiss(); } @@ -92,7 +96,8 @@ export default { }, (e) => { this._report_error(e); - }); + } + ); }); } else { this._report_error(r); @@ -106,10 +111,9 @@ export default { } }, _setFormFocus() { - [ ...document.forms ].forEach( - (form) => { - if (form.hasAttribute('data-lsmb-focus')) { - let focus = form.getAttribute('data-lsmb-focus'); + [...document.forms].forEach((form) => { + if (form.hasAttribute("data-lsmb-focus")) { + let focus = form.getAttribute("data-lsmb-focus"); let elm = document.getElementById(focus); if (elm) { elm.select(); @@ -146,7 +150,7 @@ export default { d.show(); }, _interceptClick(dnode) { - let href = dnode.getAttribute('href'); + let href = dnode.getAttribute("href"); if (dnode.target || !href) { return; } @@ -160,7 +164,7 @@ export default { }); let anode = dnode; - anode.href = '#' + href; + anode.href = "#" + href; }, _cleanWidgets() { try { @@ -176,6 +180,7 @@ export default { // the widgets. (it may take a bit for the new content to overwrite the old // content...) query("*", document.getElementById("maindiv")).forEach( + // eslint-disable no-param-reassign (n) => delete n._cssState ); } catch (e) { @@ -191,10 +196,9 @@ export default { .getElementById("maindiv") .setAttribute("data-lsmb-done", "true"); this.$nextTick(() => this.updateContent(this.uiURL)); - window.__lsmbSubmitForm = - (req) => this.updateContent(req.url, req.options); - window.__lsmbReportError = - (err) => this._report_error(err); + window.__lsmbSubmitForm = (req) => + this.updateContent(req.url, req.options); + window.__lsmbReportError = (err) => this._report_error(err); }, render() { let body = this.content.match(/]*>([\s\S]*)(<\/body>)?/i); diff --git a/UI/src/elements/lsmb-base-input.js b/UI/src/elements/lsmb-base-input.js index 6010556a22..c1f2df52f1 100644 --- a/UI/src/elements/lsmb-base-input.js +++ b/UI/src/elements/lsmb-base-input.js @@ -1,4 +1,5 @@ /** @format */ +// eslint-disable class-methods-use-this import { LsmbDijit } from "@/elements/lsmb-dijit"; diff --git a/UI/src/elements/lsmb-button.js b/UI/src/elements/lsmb-button.js index c9148dee53..c1e9456fcd 100644 --- a/UI/src/elements/lsmb-button.js +++ b/UI/src/elements/lsmb-button.js @@ -1,4 +1,5 @@ /** @format */ +// eslint-disable class-methods-use-this import { LsmbDijit } from "@/elements/lsmb-dijit"; diff --git a/UI/src/elements/lsmb-date.js b/UI/src/elements/lsmb-date.js index b4a669454f..688a20e50e 100644 --- a/UI/src/elements/lsmb-date.js +++ b/UI/src/elements/lsmb-date.js @@ -1,4 +1,5 @@ /** @format */ +// eslint-disable class-methods-use-this, max-classes-per-file import { LsmbBaseInput } from "@/elements/lsmb-base-input"; diff --git a/UI/src/elements/lsmb-dijit.js b/UI/src/elements/lsmb-dijit.js index 07f364bcd5..03a3b8af6a 100644 --- a/UI/src/elements/lsmb-dijit.js +++ b/UI/src/elements/lsmb-dijit.js @@ -1,4 +1,5 @@ /** @format */ +// eslint-disable class-methods-use-this export class LsmbDijit extends HTMLElement { dojoWidget = null; @@ -20,6 +21,7 @@ export class LsmbDijit extends HTMLElement { } _collectProps() { + // eslint-disable-next-line no-eval let extra = this.hasAttribute("dojo-props") ? eval("({" + this.getAttribute("dojo-props") + "})") : {}; diff --git a/UI/src/elements/lsmb-password.js b/UI/src/elements/lsmb-password.js index 04cf6e72a6..6d2ef65560 100644 --- a/UI/src/elements/lsmb-password.js +++ b/UI/src/elements/lsmb-password.js @@ -1,4 +1,5 @@ /** @format */ +// eslint-disable class-methods-use-this import { LsmbText } from "@/elements/lsmb-text"; diff --git a/UI/src/elements/lsmb-text.js b/UI/src/elements/lsmb-text.js index d98106a231..428168f49d 100644 --- a/UI/src/elements/lsmb-text.js +++ b/UI/src/elements/lsmb-text.js @@ -1,4 +1,5 @@ /** @format */ +// eslint-disable class-methods-use-this, max-classes-per-file import { LsmbBaseInput } from "@/elements/lsmb-base-input"; diff --git a/UI/src/i18n.js b/UI/src/i18n.js index 477217a88d..a461150505 100644 --- a/UI/src/i18n.js +++ b/UI/src/i18n.js @@ -35,14 +35,14 @@ export async function setI18nLanguage(lang) { const _messages = await import(/* webpackChunkName: "lang-[request]" */ `@/locales/${locale}.json`); i18n.global.setLocaleMessage(locale, _messages.default); } - catch { + catch (e) { const strippedLocale = locale.replace(/_[a-z]+/i, ''); try { const _messages = await import(/* webpackChunkName: "lang-[request]" */ `@/locales/${strippedLocale}.json`); i18n.global.setLocaleMessage(strippedLocale, _messages.default); locale = strippedLocale; } - catch { + catch (f) { locale = "en"; } } diff --git a/UI/src/main-vue.js b/UI/src/main-vue.js index df69f259e1..d2acd8b77c 100644 --- a/UI/src/main-vue.js +++ b/UI/src/main-vue.js @@ -18,6 +18,7 @@ let appName; let lsmbDirective = { beforeMount(el, binding /* , vnode */) { let handler = (event) => { + // eslint-disable no-param-reassign binding.instance[binding.arg] = event.target.value; }; el.addEventListener("input", handler); diff --git a/UI/src/store/configTemplate.js b/UI/src/store/configTemplate.js index fbd74439bf..d3b4c13841 100644 --- a/UI/src/store/configTemplate.js +++ b/UI/src/store/configTemplate.js @@ -66,7 +66,7 @@ export const configStoreTemplate = { }, async get(id) { let index = this.items.findIndex((w) => w[this.id] === id); - if ( index === -1 ) { + if (index === -1) { index = this.items.length; } const warehouse = this.items[index]; @@ -117,7 +117,7 @@ export const configStoreTemplate = { newData._meta = { ETag: response.headers.get("ETag") }; - this.items[index] = newData; + this.items[index] = newData; } else { throw new Error(`HTTP Error: ${response.status}`); } diff --git a/UI/src/store/countries.js b/UI/src/store/countries.js index 13ccd6b85d..d8f9e9bc9d 100644 --- a/UI/src/store/countries.js +++ b/UI/src/store/countries.js @@ -9,7 +9,7 @@ export const useCountriesStore = defineStore("countries", { ...configStoreTemplate, getters: { ...configGetters, - default: (state) => state.items.find((elm) => elm.default), + default: (state) => state.items.find((elm) => elm.default) }, actions: { ...configActions, @@ -28,7 +28,7 @@ export const useCountriesStore = defineStore("countries", { }, state: () => { return { - fields: [ "_meta", "code", "default", "name"], + fields: ["_meta", "code", "default", "name"], id: "code", items: [], _links: [], diff --git a/UI/src/store/languages.js b/UI/src/store/languages.js index 0d2bbf831e..835cc45ecd 100644 --- a/UI/src/store/languages.js +++ b/UI/src/store/languages.js @@ -9,7 +9,7 @@ export const useLanguagesStore = defineStore("languages", { ...configStoreTemplate, getters: { ...configGetters, - default: (state) => state.items.find((elm) => elm.default), + default: (state) => state.items.find((elm) => elm.default) }, actions: { ...configActions, diff --git a/UI/src/views/LoginPage.machines.js b/UI/src/views/LoginPage.machines.js index 22a525fd33..207ceb194d 100644 --- a/UI/src/views/LoginPage.machines.js +++ b/UI/src/views/LoginPage.machines.js @@ -20,7 +20,9 @@ import { } from "@/machine-helpers"; function submitLogin(ctx) { - return fetch("login.pl?action=authenticate&company=" + encodeURI(ctx.company.value), { + return fetch( + "login.pl?action=authenticate&company=" + encodeURI(ctx.company.value), + { method: "POST", body: JSON.stringify({ company: ctx.company.value, @@ -31,73 +33,90 @@ function submitLogin(ctx) { "X-Requested-With": "XMLHttpRequest", "Content-Type": "application/json" }) - }); + } + ); } function createLoginMachine(initialContext) { return interpret( - createMachine({ - invalid: state( - transitionFormValid("input", "ready"), - ), + createMachine( + { + invalid: state(transitionFormValid("input", "ready")), ready: state( transitionFormInvalid("input", "invalid"), - transition('submit', 'submitting'), + transition("submit", "submitting") ), submitting: invoke( submitLogin, transition( - 'error', 'ready', - action((ctx, e) => { alert(e.error); }) + "error", + "ready", + action((ctx, e) => { + // eslint-disable-next-line no-alert + alert(e.error); + }) ), transition( - 'done', 'submitted', - reduce((ctx, e) => ({ ...ctx, response: e.data})), - ), + "done", + "submitted", + reduce((ctx, e) => ({ ...ctx, response: e.data })) + ) ), submitted: state( immediate( - 'failed', + "failed", guard(testResponseStatusFn(401)), action((ctx) => { - ctx.errorText.value = ctx.t("Access denied: Bad username or password"); - }), + ctx.errorText.value = ctx.t( + "Access denied: Bad username or password" + ); + }) ), immediate( - 'failed', + "failed", guard(testResponseStatusFn(521)), action((ctx) => { - ctx.errorText.value = ctx.t("Database version mismatch"); - }), + ctx.errorText.value = ctx.t( + "Database version mismatch" + ); + }) ), immediate( - 'ready', + "ready", guard(testNot(testResponseOkFn())), action((ctx) => { - alert(ctx.t("Unknown error preventing login")); - }), + alert(ctx.t("Unknown error preventing login")); // eslint-disable-line no-alert + }) ), - immediate('parsing'), + immediate("parsing") ), parsing: invoke( - ctx => ctx.response.json(), + (ctx) => ctx.response.json(), transition( - 'done', 'final', - action((ctx, e) => { window.location.assign(e.data.target); }), + "done", + "final", + action((ctx, e) => { + window.location.assign(e.data.target); + }) ), transition( - 'error', 'error', - reduce((ctx, e) => ({ ...ctx, error: e.data }))), + "error", + "error", + reduce((ctx, e) => ({ ...ctx, error: e.data })) + ) ), failed: state( transitionFormValid("input", "ready"), - transitionFormInvalid("input", "invalid"), + transitionFormInvalid("input", "invalid") ), final: state(), - error: state(), - }, initialCtx => initialCtx), + error: state() + }, + (initialCtx) => initialCtx + ), () => {}, - initialContext); + initialContext + ); } export { createLoginMachine }; From 4ed1fd9df3cea15a831fe413899f9323ee79bae8 Mon Sep 17 00:00:00 2001 From: Yves Lavoie Date: Mon, 15 Apr 2024 00:33:55 -0400 Subject: [PATCH 05/17] Lint Javascript test files --- UI/tests/common/jest-setup.js | 2 +- UI/tests/common/mocks/lsmb_elements.js | 3 + .../mocks/store_sessionUser_handlers.js | 6 +- UI/tests/specs/LoginPage.spec.js | 29 +-- .../API-contacts-business_types.spec.js | 51 ++++-- .../specs/openapi/API-contacts-sic.spec.js | 81 ++++----- UI/tests/specs/openapi/API-country.spec.js | 20 ++- UI/tests/specs/openapi/API-gifi.spec.js | 50 +++--- UI/tests/specs/openapi/API-invoices.spec.js | 166 +++++++++--------- UI/tests/specs/openapi/API-languages.spec.js | 23 +-- UI/tests/specs/openapi/API-orders.spec.js | 136 +++++++------- .../openapi/API-products-pricegroups.spec.js | 107 +++++------ .../openapi/API-products-warehouses.spec.js | 99 ++++++----- UI/tests/specs/stores/business-types.spec.js | 65 +++++-- UI/tests/specs/stores/countries.spec.js | 53 ++++-- UI/tests/specs/stores/gifis.spec.js | 36 +++- UI/tests/specs/stores/languages.spec.js | 58 ++++-- UI/tests/specs/stores/pricegroups.spec.js | 44 +++-- UI/tests/specs/stores/sessionUser.spec.js | 10 +- UI/tests/specs/stores/sics.spec.js | 52 ++++-- UI/tests/specs/stores/warehouses.spec.js | 59 +++++-- UI/tests/specs/views/BusinessTypes.spec.js | 43 +++-- UI/tests/specs/views/Countries.spec.js | 84 +++++---- UI/tests/specs/views/GIFI.spec.js | 33 ++-- UI/tests/specs/views/Languages.spec.js | 151 +++++++++------- UI/tests/specs/views/Pricegroups.spec.js | 37 ++-- UI/tests/specs/views/SIC.spec.js | 36 ++-- UI/tests/specs/views/Warehouses.spec.js | 45 ++--- .../views/__snapshots__/GIFI.spec.js.snap | 2 - UI/tests/specs/views/factory.js | 6 +- 30 files changed, 929 insertions(+), 658 deletions(-) diff --git a/UI/tests/common/jest-setup.js b/UI/tests/common/jest-setup.js index e0862da558..309740a312 100644 --- a/UI/tests/common/jest-setup.js +++ b/UI/tests/common/jest-setup.js @@ -69,7 +69,7 @@ afterEach(() => { }); // Helper function to wait for DOM updates -/* eslint no-unused-expressions: ["error", { "allowTernary": true }] */ +// eslint no-unused-expressions: ["error", { "allowTernary": true }] export const retry = (assertion, { interval = 20, timeout = 1000 } = {}) => { return new Promise((resolve, reject) => { const startTime = Date.now(); diff --git a/UI/tests/common/mocks/lsmb_elements.js b/UI/tests/common/mocks/lsmb_elements.js index 5e0f31c34b..de754e6c5d 100644 --- a/UI/tests/common/mocks/lsmb_elements.js +++ b/UI/tests/common/mocks/lsmb_elements.js @@ -1,4 +1,7 @@ /** @format */ +// eslint-disable vue/component-definition-name-casing +// eslint-disable vue/require-prop-types, vue/one-component-per-file +// eslint-disable global-require import { config } from "@vue/test-utils"; import { defineComponent } from "vue"; diff --git a/UI/tests/common/mocks/store_sessionUser_handlers.js b/UI/tests/common/mocks/store_sessionUser_handlers.js index 7e3c7c8d53..26852ae814 100644 --- a/UI/tests/common/mocks/store_sessionUser_handlers.js +++ b/UI/tests/common/mocks/store_sessionUser_handlers.js @@ -2,7 +2,7 @@ import { http, HttpResponse } from 'msw'; export const sessionUserHandlers = [ - http.get('/erp/api/v0/session', () => { + http.get('/erp/api/v0/session', ({ request }) => { return HttpResponse.json( { @@ -22,7 +22,7 @@ export const sessionUserHandlers = [ } }, { status: 200 } - ); + ) }) -]; +] diff --git a/UI/tests/specs/LoginPage.spec.js b/UI/tests/specs/LoginPage.spec.js index d27415d142..f6d05c6281 100644 --- a/UI/tests/specs/LoginPage.spec.js +++ b/UI/tests/specs/LoginPage.spec.js @@ -55,9 +55,11 @@ describe("LoginPage", () => { await wrapper.get("#login").trigger("click"); - await retry(() => expect(wrapper.get("#errorText").text()).toBe( - "Access denied: Bad username or password" - )); + await retry(() => + expect(wrapper.get("#errorText").text()).toBe( + "Access denied: Bad username or password" + ) + ); window.alert = jsdomAlert; // restore the jsdom alert }); @@ -73,9 +75,11 @@ describe("LoginPage", () => { await wrapper.get("#login").trigger("click"); - await retry (() => expect(wrapper.get("#errorText").text()).toBe( - "Database version mismatch" - )); + await retry(() => + expect(wrapper.get("#errorText").text()).toBe( + "Database version mismatch" + ) + ); window.alert = jsdomAlert; // restore the jsdom alert }); @@ -93,7 +97,7 @@ describe("LoginPage", () => { await retry(() => expect(window.alert).toHaveBeenCalledTimes(1)); expect(window.alert).toHaveBeenCalledWith( - "Unknown error preventing login", + "Unknown error preventing login" ); window.alert = jsdomAlert; // restore the jsdom alert }); @@ -107,12 +111,15 @@ describe("LoginPage", () => { await wrapper.get("#login").trigger("click"); - expect(wrapper.get(".v-enter-active").text()) - .toBe("Logging in... Please wait."); + expect(wrapper.get(".v-enter-active").text()).toBe( + "Logging in... Please wait." + ); - await retry(() => expect(window.location.assign).toHaveBeenCalledTimes(1)); + await retry(() => + expect(window.location.assign).toHaveBeenCalledTimes(1) + ); expect(window.location.assign).toHaveBeenCalledWith( - 'http://lsmb/erp.pl?action=root', + "http://lsmb/erp.pl?action=root" ); }); }); diff --git a/UI/tests/specs/openapi/API-contacts-business_types.spec.js b/UI/tests/specs/openapi/API-contacts-business_types.spec.js index 2ad9957b09..062a9bd989 100644 --- a/UI/tests/specs/openapi/API-contacts-business_types.spec.js +++ b/UI/tests/specs/openapi/API-contacts-business_types.spec.js @@ -4,14 +4,14 @@ import jestOpenAPI from "jest-openapi"; import { StatusCodes } from "http-status-codes"; import { create_database, drop_database } from "./database"; -import { server } from '../../common/mocks/server.js' +import { server } from "../../common/mocks/server.js"; // Load an OpenAPI file (YAML or JSON) into this plugin -const openapi = process.env.PWD.replace("/UI",""); -jestOpenAPI( openapi + "/openapi/API.yaml"); +const openapi = process.env.PWD.replace("/UI", ""); +jestOpenAPI(openapi + "/openapi/API.yaml"); // Load the API definition -const API_yaml = require (openapi + "/openapi/API.yaml"); +const API_yaml = require(openapi + "/openapi/API.yaml"); // Set API version to use const api = "erp/api/v0"; @@ -32,7 +32,7 @@ beforeAll(() => { // Establish API mocking before all tests. server.listen({ - onUnhandledRequest: 'bypass' + onUnhandledRequest: "bypass" }); }); @@ -40,7 +40,7 @@ afterAll(() => { drop_database(company); }); -const emulateAxiosResponse = async(res) => { +const emulateAxiosResponse = async (res) => { return { data: await res.json(), status: res.status, @@ -48,7 +48,7 @@ const emulateAxiosResponse = async(res) => { headers: res.headers, request: { path: res.url, - method: 'GET' + method: "GET" } }; }; @@ -56,7 +56,9 @@ const emulateAxiosResponse = async(res) => { // Log in before each test beforeEach(async () => { let r = await fetch( - serverUrl + "/login.pl?action=authenticate&company=" + encodeURI(company), + serverUrl + + "/login.pl?action=authenticate&company=" + + encodeURI(company), { method: "POST", body: JSON.stringify({ @@ -108,18 +110,24 @@ describe("Retrieving all Business Types", () => { describe("Retrieving all Business Types with old syntax should fail", () => { it("GET /contacts/business-types/ should fail", async () => { - const res = await fetch(serverUrl + "/" + api + "/contacts/business-types/", { - headers: headers - }); + const res = await fetch( + serverUrl + "/" + api + "/contacts/business-types/", + { + headers: headers + } + ); expect(res.status).toEqual(StatusCodes.NOT_FOUND); }); }); describe("Retrieve non-existant Business Type", () => { it("GET /contacts/business-types/1 should not retrieve our Business Types", async () => { - const res = await fetch(serverUrl + "/" + api + "/contacts/business-types/1", { - headers: headers - }); + const res = await fetch( + serverUrl + "/" + api + "/contacts/business-types/1", + { + headers: headers + } + ); expect(res.status).toEqual(StatusCodes.NOT_FOUND); }); }); @@ -147,13 +155,17 @@ describe("Adding the IT Business Types", () => { describe("Validate against the default Business Type", () => { it("GET /contacts/business-types/1 should validate the new Business Type", async () => { - let res = await fetch(serverUrl + "/" + api + "/contacts/business-types/1", { - headers: headers - }); + let res = await fetch( + serverUrl + "/" + api + "/contacts/business-types/1", + { + headers: headers + } + ); expect(res.status).toEqual(StatusCodes.OK); // Pick the example - const businessTypeExample = API_yaml.components.examples.validBusinessType.value; + const businessTypeExample = + API_yaml.components.examples.validBusinessType.value; // Assert that the response matches the example in the spec res = await emulateAxiosResponse(res); @@ -249,7 +261,8 @@ describe("Not removing the new IT Business Types", () => { const etag = res.headers.get("etag"); expect(etag).toBeDefined(); res = await fetch( - serverUrl + "/" + api + "/contacts/business-types/1", { + serverUrl + "/" + api + "/contacts/business-types/1", + { method: "DELETE", headers: { ...headers, "If-Match": etag } } diff --git a/UI/tests/specs/openapi/API-contacts-sic.spec.js b/UI/tests/specs/openapi/API-contacts-sic.spec.js index da77a7f59e..5c562925be 100644 --- a/UI/tests/specs/openapi/API-contacts-sic.spec.js +++ b/UI/tests/specs/openapi/API-contacts-sic.spec.js @@ -4,14 +4,14 @@ import jestOpenAPI from "jest-openapi"; import { StatusCodes } from "http-status-codes"; import { create_database, drop_database } from "./database"; -import { server } from '../../common/mocks/server.js' +import { server } from "../../common/mocks/server.js"; // Load an OpenAPI file (YAML or JSON) into this plugin -const openapi = process.env.PWD.replace("/UI",""); -jestOpenAPI( openapi + "/openapi/API.yaml"); +const openapi = process.env.PWD.replace("/UI", ""); +jestOpenAPI(openapi + "/openapi/API.yaml"); // Load the API definition -const API_yaml = require (openapi + "/openapi/API.yaml"); +const API_yaml = require(openapi + "/openapi/API.yaml"); // Set API version to use const api = "erp/api/v0"; @@ -32,7 +32,7 @@ beforeAll(() => { // Establish API mocking before all tests. server.listen({ - onUnhandledRequest: 'bypass' + onUnhandledRequest: "bypass" }); }); @@ -40,7 +40,7 @@ afterAll(() => { drop_database(company); }); -const emulateAxiosResponse = async(res) => { +const emulateAxiosResponse = async (res) => { return { data: await res.json(), status: res.status, @@ -48,7 +48,7 @@ const emulateAxiosResponse = async(res) => { headers: res.headers, request: { path: res.url, - method: 'GET' + method: "GET" } }; }; @@ -56,7 +56,9 @@ const emulateAxiosResponse = async(res) => { // Log in before each test beforeEach(async () => { let r = await fetch( - serverUrl + "/login.pl?action=authenticate&company=" + encodeURI(company), + serverUrl + + "/login.pl?action=authenticate&company=" + + encodeURI(company), { method: "POST", body: JSON.stringify({ @@ -123,17 +125,14 @@ describe("Retrieve non-existant SIC", () => { describe("Adding the IT SIC", () => { it("POST /contacts/sic/541510 should allow adding IT SIC", async () => { - let res = await fetch( - serverUrl + "/" + api + "/contacts/sic", - { - method: "POST", - body: JSON.stringify({ - code: "541510", - description: "Design of computer systems" - }), - headers: {...headers, "Content-Type": "application/json" } - } - ); + let res = await fetch(serverUrl + "/" + api + "/contacts/sic", { + method: "POST", + body: JSON.stringify({ + code: "541510", + description: "Design of computer systems" + }), + headers: { ...headers, "Content-Type": "application/json" } + }); expect(res.status).toEqual(StatusCodes.CREATED); // Assert that the HTTP response satisfies the OpenAPI spec @@ -144,12 +143,9 @@ describe("Adding the IT SIC", () => { describe("Validate against the example SIC", () => { it("GET /contacts/sic/541510 should validate IT SIC", async () => { - let res = await fetch( - serverUrl + "/" + api + "/contacts/sic/541510", - { - headers: headers - } - ); + let res = await fetch(serverUrl + "/" + api + "/contacts/sic/541510", { + headers: headers + }); expect(res.status).toEqual(StatusCodes.OK); // Pick the example @@ -169,21 +165,18 @@ describe("Modifying the new IT SIC", () => { expect(res.status).toEqual(StatusCodes.OK); const etag = res.headers.get("etag"); expect(etag).toBeDefined(); - res = await fetch( - serverUrl + "/" + api + "/contacts/sic/541510", - { - method: "PUT", - body: JSON.stringify({ - code: "541510", - description: "Design of computer systems and related services" - }), - headers: { - ...headers, - "content-type": "application/json", - "If-Match": etag - } + res = await fetch(serverUrl + "/" + api + "/contacts/sic/541510", { + method: "PUT", + body: JSON.stringify({ + code: "541510", + description: "Design of computer systems and related services" + }), + headers: { + ...headers, + "content-type": "application/json", + "If-Match": etag } - ); + }); expect(res.status).toEqual(StatusCodes.OK); // Assert that the HTTP response satisfies the OpenAPI spec @@ -241,12 +234,10 @@ describe("Not removing the new IT SIC", () => { const etag = res.headers.get("etag"); expect(etag).toBeDefined(); - res = await fetch( - serverUrl + "/" + api + "/contacts/sic/541510", { - method: "DELETE", - headers: { ...headers, "If-Match": etag } - } - ); + res = await fetch(serverUrl + "/" + api + "/contacts/sic/541510", { + method: "DELETE", + headers: { ...headers, "If-Match": etag } + }); expect(res.status).toEqual(StatusCodes.FORBIDDEN); }); }); diff --git a/UI/tests/specs/openapi/API-country.spec.js b/UI/tests/specs/openapi/API-country.spec.js index 6b76d741be..49df142738 100644 --- a/UI/tests/specs/openapi/API-country.spec.js +++ b/UI/tests/specs/openapi/API-country.spec.js @@ -4,14 +4,14 @@ import jestOpenAPI from "jest-openapi"; import { StatusCodes } from "http-status-codes"; import { create_database, drop_database } from "./database"; -import { server } from '../../common/mocks/server.js' +import { server } from "../../common/mocks/server.js"; // Load an OpenAPI file (YAML or JSON) into this plugin -const openapi = process.env.PWD.replace("/UI",""); -jestOpenAPI( openapi + "/openapi/API.yaml"); +const openapi = process.env.PWD.replace("/UI", ""); +jestOpenAPI(openapi + "/openapi/API.yaml"); // Load the API definition -const API_yaml = require (openapi + "/openapi/API.yaml"); +const API_yaml = require(openapi + "/openapi/API.yaml"); // Set API version to use const api = "erp/api/v0"; @@ -34,7 +34,7 @@ beforeAll(() => { // Establish API mocking before all tests. server.listen({ - onUnhandledRequest: 'bypass' + onUnhandledRequest: "bypass" }); }); @@ -42,7 +42,7 @@ afterAll(() => { drop_database(company); }); -const emulateAxiosResponse = async(res) => { +const emulateAxiosResponse = async (res) => { return { data: await res.json(), status: res.status, @@ -50,7 +50,7 @@ const emulateAxiosResponse = async(res) => { headers: res.headers, request: { path: res.url, - method: 'GET' + method: "GET" } }; }; @@ -58,7 +58,9 @@ const emulateAxiosResponse = async(res) => { // Log in before each test beforeEach(async () => { let r = await fetch( - serverUrl + "/login.pl?action=authenticate&company=" + encodeURI(company), + serverUrl + + "/login.pl?action=authenticate&company=" + + encodeURI(company), { method: "POST", body: JSON.stringify({ @@ -108,7 +110,7 @@ describe("Retrieving all countries", () => { describe("Retrieving all countries with old syntax should fail", () => { it("GET /countries/ should fail", async () => { let res = await fetch(serverUrl + "/" + api + "/countries/", { - headers: headers + headers: headers }); expect(res.status).toEqual(StatusCodes.NOT_FOUND); }); diff --git a/UI/tests/specs/openapi/API-gifi.spec.js b/UI/tests/specs/openapi/API-gifi.spec.js index 2f716938f5..2d77234c00 100644 --- a/UI/tests/specs/openapi/API-gifi.spec.js +++ b/UI/tests/specs/openapi/API-gifi.spec.js @@ -4,14 +4,14 @@ import jestOpenAPI from "jest-openapi"; import { StatusCodes } from "http-status-codes"; import { create_database, drop_database } from "./database"; -import { server } from '../../common/mocks/server.js' +import { server } from "../../common/mocks/server.js"; // Load an OpenAPI file (YAML or JSON) into this plugin -const openapi = process.env.PWD.replace("/UI",""); -jestOpenAPI( openapi + "/openapi/API.yaml"); +const openapi = process.env.PWD.replace("/UI", ""); +jestOpenAPI(openapi + "/openapi/API.yaml"); // Load the API definition -const API_yaml = require (openapi + "/openapi/API.yaml"); +const API_yaml = require(openapi + "/openapi/API.yaml"); // Set API version to use const api = "erp/api/v0"; @@ -34,7 +34,7 @@ beforeAll(() => { // Establish API mocking before all tests. server.listen({ - onUnhandledRequest: 'bypass' + onUnhandledRequest: "bypass" }); }); @@ -42,7 +42,7 @@ afterAll(() => { drop_database(company); }); -const emulateAxiosResponse = async(res) => { +const emulateAxiosResponse = async (res) => { return { data: await res.json(), status: res.status, @@ -50,7 +50,7 @@ const emulateAxiosResponse = async(res) => { headers: res.headers, request: { path: res.url, - method: 'GET' + method: "GET" } }; }; @@ -58,7 +58,9 @@ const emulateAxiosResponse = async(res) => { // Log in before each test beforeEach(async () => { let r = await fetch( - serverUrl + "/login.pl?action=authenticate&company=" + encodeURI(company), + serverUrl + + "/login.pl?action=authenticate&company=" + + encodeURI(company), { method: "POST", body: JSON.stringify({ @@ -107,7 +109,7 @@ describe("Retrieving all gifis", () => { describe("Retrieving all gifis with old syntax should fail", () => { it("GET /gifi/ should fail", async () => { let res = await fetch(serverUrl + "/" + api + "/gl/gifi/", { - headers: headers + headers: headers }); expect(res.status).toEqual(StatusCodes.NOT_FOUND); }); @@ -164,18 +166,17 @@ describe("Modifying the new GIFI 99999", () => { expect(res.status).toEqual(StatusCodes.OK); const etag = res.headers.get("etag"); expect(etag).toBeDefined(); - res = await fetch( - serverUrl + "/" + api + "/gl/gifi/99999",{ - method: "PUT", - body: JSON.stringify({ - accno: "99999", - description: "Test GIFI" - }), - headers: { - ...headers, - "Content-Type": "application/json", - "If-Match": etag - } + res = await fetch(serverUrl + "/" + api + "/gl/gifi/99999", { + method: "PUT", + body: JSON.stringify({ + accno: "99999", + description: "Test GIFI" + }), + headers: { + ...headers, + "Content-Type": "application/json", + "If-Match": etag + } }); expect(res.status).toEqual(StatusCodes.OK); @@ -235,10 +236,9 @@ describe("Not Removing the new GIFI 99999", () => { expect(etag).toBeDefined(); res = await fetch(serverUrl + "/" + api + "/gl/gifi/99999", { - method: "DELETE", - headers: { ...headers, "If-Match": etag } - } - ); + method: "DELETE", + headers: { ...headers, "If-Match": etag } + }); expect(res.status).toEqual(StatusCodes.FORBIDDEN); }); }); diff --git a/UI/tests/specs/openapi/API-invoices.spec.js b/UI/tests/specs/openapi/API-invoices.spec.js index 39a3cced69..4e3190fef8 100644 --- a/UI/tests/specs/openapi/API-invoices.spec.js +++ b/UI/tests/specs/openapi/API-invoices.spec.js @@ -3,15 +3,20 @@ // Import test packages import jestOpenAPI from "jest-openapi"; import { StatusCodes } from "http-status-codes"; -import { create_database, drop_database, load_coa, initialize } from "./database"; -import { server } from '../../common/mocks/server.js' +import { + create_database, + drop_database, + load_coa, + initialize +} from "./database"; +import { server } from "../../common/mocks/server.js"; // Load an OpenAPI file (YAML or JSON) into this plugin -const openapi = process.env.PWD.replace("/UI",""); -jestOpenAPI( openapi + "/openapi/API.yaml"); +const openapi = process.env.PWD.replace("/UI", ""); +jestOpenAPI(openapi + "/openapi/API.yaml"); // Load the API definition -const API_yaml = require (openapi + "/openapi/API.yaml"); +const API_yaml = require(openapi + "/openapi/API.yaml"); // Set API version to use const api = "erp/api/v0"; @@ -30,11 +35,11 @@ let headers = {}; beforeAll(() => { create_database(username, password, company); load_coa(username, password, company, "locale/coa/us/General.xml"); - initialize(company,"UI/tests/specs/data/Invoices.sql"); + initialize(company, "UI/tests/specs/data/Invoices.sql"); // Establish API mocking before all tests. server.listen({ - onUnhandledRequest: 'bypass' + onUnhandledRequest: "bypass" }); }); @@ -42,7 +47,7 @@ afterAll(() => { drop_database(company); }); -const emulateAxiosResponse = async(res) => { +const emulateAxiosResponse = async (res) => { return { data: await res.json(), status: res.status, @@ -50,7 +55,7 @@ const emulateAxiosResponse = async(res) => { headers: res.headers, request: { path: res.url, - method: 'GET' + method: "GET" } }; }; @@ -58,7 +63,9 @@ const emulateAxiosResponse = async(res) => { // Log in before each test beforeEach(async () => { let r = await fetch( - serverUrl + "/login.pl?action=authenticate&company=" + encodeURI(company), + serverUrl + + "/login.pl?action=authenticate&company=" + + encodeURI(company), { method: "POST", body: JSON.stringify({ @@ -103,81 +110,78 @@ describe("Adding the new Invoice", () => { it("POST /invoices should allow adding a new invoice", async () => { let res; try { - res = await fetch( - serverUrl + "/" + api + "/invoices", - { - method: "POST", - body: JSON.stringify({ - eca: { - number: "Customer 1", - type: "customer" // Watch for exact case or watch serverUrl stack dump - }, - account: { - accno: "1200" - }, - currency: "USD", - dates: { - created: "2022-09-01", - due: "2022-10-01", - book: "2022-10-05" - }, - "internal-notes": "Internal notes", - "invoice-number": "2389434", - lines: [ - { - part: { - number: "p1" - }, - price: 56.78, - price_fixated: false, - unit: "lbs", - qty: 1, - taxform: true, - serialnumber: "1234567890", - discount: 12, - discount_type: "%", - delivery_date: "2022-10-27", - description: "A description" - } - ], - notes: "Notes", - "order-number": "order 345", - "po-number": "po 456", - "shipping-point": "shipping from here", - // TODO: Debug ship-to - // "ship-to": "ship to there", - "ship-via": "ship via", - taxes: { - "2150": { - tax: { - category: "2150" - }, - "base-amount": 50, - amount: 6.78, - source: "Part 1", - memo: "tax memo" // Could that be optional? + res = await fetch(serverUrl + "/" + api + "/invoices", { + method: "POST", + body: JSON.stringify({ + eca: { + number: "Customer 1", + type: "customer" // Watch for exact case or watch serverUrl stack dump + }, + account: { + accno: "1200" + }, + currency: "USD", + dates: { + created: "2022-09-01", + due: "2022-10-01", + book: "2022-10-05" + }, + "internal-notes": "Internal notes", + "invoice-number": "2389434", + lines: [ + { + part: { + number: "p1" }, - }, - payments: [ - { - account: { - accno: "5010" - }, - date: "2022-11-05", - amount: 20, - memo: "depot", - source: "visa" - } - ] - }), - headers: { ...headers, "Content-Type": "application/json" }, - } - ) - } catch(e) { + price: 56.78, + price_fixated: false, + unit: "lbs", + qty: 1, + taxform: true, + serialnumber: "1234567890", + discount: 12, + discount_type: "%", + delivery_date: "2022-10-27", + description: "A description" + } + ], + notes: "Notes", + "order-number": "order 345", + "po-number": "po 456", + "shipping-point": "shipping from here", + // TODO: Debug ship-to + // "ship-to": "ship to there", + "ship-via": "ship via", + taxes: { + 2150: { + tax: { + category: "2150" + }, + "base-amount": 50, + amount: 6.78, + source: "Part 1", + memo: "tax memo" // Could that be optional? + } + }, + payments: [ + { + account: { + accno: "5010" + }, + date: "2022-11-05", + amount: 20, + memo: "depot", + source: "visa" + } + ] + }), + headers: { ...headers, "Content-Type": "application/json" } + }); + } catch (e) { console.log(e.response.data); } expect(res.status).toEqual(StatusCodes.CREATED); - expect(res.headers.get('location')).toMatch('./1'); + expect(res.headers.get("location")).toMatch("./1"); }); }); diff --git a/UI/tests/specs/openapi/API-languages.spec.js b/UI/tests/specs/openapi/API-languages.spec.js index 4ec40e855a..70310226fc 100644 --- a/UI/tests/specs/openapi/API-languages.spec.js +++ b/UI/tests/specs/openapi/API-languages.spec.js @@ -4,14 +4,14 @@ import jestOpenAPI from "jest-openapi"; import { StatusCodes } from "http-status-codes"; import { create_database, drop_database } from "./database"; -import { server } from '../../common/mocks/server.js' +import { server } from "../../common/mocks/server.js"; // Load an OpenAPI file (YAML or JSON) into this plugin -const openapi = process.env.PWD.replace("/UI",""); -jestOpenAPI( openapi + "/openapi/API.yaml"); +const openapi = process.env.PWD.replace("/UI", ""); +jestOpenAPI(openapi + "/openapi/API.yaml"); // Load the API definition -const API_yaml = require (openapi + "/openapi/API.yaml"); +const API_yaml = require(openapi + "/openapi/API.yaml"); // Set API version to use const api = "erp/api/v0"; @@ -34,7 +34,7 @@ beforeAll(() => { // Establish API mocking before all tests. server.listen({ - onUnhandledRequest: 'bypass' + onUnhandledRequest: "bypass" }); }); @@ -42,7 +42,7 @@ afterAll(() => { drop_database(company); }); -const emulateAxiosResponse = async(res) => { +const emulateAxiosResponse = async (res) => { return { data: await res.json(), status: res.status, @@ -50,7 +50,7 @@ const emulateAxiosResponse = async(res) => { headers: res.headers, request: { path: res.url, - method: 'GET' + method: "GET" } }; }; @@ -58,7 +58,9 @@ const emulateAxiosResponse = async(res) => { // Log in before each test beforeEach(async () => { let r = await fetch( - serverUrl + "/login.pl?action=authenticate&company=" + encodeURI(company), + serverUrl + + "/login.pl?action=authenticate&company=" + + encodeURI(company), { method: "POST", body: JSON.stringify({ @@ -108,7 +110,7 @@ describe("Retrieving all languages", () => { describe("Retrieving all languages with old syntax should fail", () => { it("GET /languages/ should fail", async () => { let res = await fetch(serverUrl + "/" + api + "/languages/", { - headers: headers + headers: headers }); expect(res.status).toEqual(StatusCodes.NOT_FOUND); }); @@ -138,7 +140,8 @@ describe("Retrieve the French Canadian language", () => { expect(res.status).toEqual(StatusCodes.OK); // Pick the example - const languageExample = API_yaml.components.examples.validLanguage.value; + const languageExample = + API_yaml.components.examples.validLanguage.value; // Assert that the response matches the example in the spec res = await emulateAxiosResponse(res); diff --git a/UI/tests/specs/openapi/API-orders.spec.js b/UI/tests/specs/openapi/API-orders.spec.js index c70ee554e4..00b5fb2ae8 100644 --- a/UI/tests/specs/openapi/API-orders.spec.js +++ b/UI/tests/specs/openapi/API-orders.spec.js @@ -3,15 +3,20 @@ // Import test packages import jestOpenAPI from "jest-openapi"; import { StatusCodes } from "http-status-codes"; -import { create_database, drop_database, load_coa, initialize } from "./database"; -import { server } from '../../common/mocks/server.js'; +import { + create_database, + drop_database, + load_coa, + initialize +} from "./database"; +import { server } from "../../common/mocks/server.js"; // Load an OpenAPI file (YAML or JSON) into this plugin -const openapi = process.env.PWD.replace("/UI",""); -jestOpenAPI( openapi + "/openapi/API.yaml"); +const openapi = process.env.PWD.replace("/UI", ""); +jestOpenAPI(openapi + "/openapi/API.yaml"); // Load the API definition -const API_yaml = require (openapi + "/openapi/API.yaml"); +const API_yaml = require(openapi + "/openapi/API.yaml"); // Set API version to use const api = "erp/api/v0"; @@ -30,11 +35,11 @@ let headers = {}; beforeAll(() => { create_database(username, password, company); load_coa(username, password, company, "locale/coa/us/General.xml"); - initialize(company,"UI/tests/specs/data/Orders.sql"); + initialize(company, "UI/tests/specs/data/Orders.sql"); // Establish API mocking before all tests. server.listen({ - onUnhandledRequest: 'bypass' + onUnhandledRequest: "bypass" }); }); @@ -42,7 +47,7 @@ afterAll(() => { drop_database(company); }); -const emulateAxiosResponse = async(res) => { +const emulateAxiosResponse = async (res) => { return { data: await res.json(), status: res.status, @@ -50,7 +55,7 @@ const emulateAxiosResponse = async(res) => { headers: res.headers, request: { path: res.url, - method: 'GET' + method: "GET" } }; }; @@ -58,7 +63,9 @@ const emulateAxiosResponse = async(res) => { // Log in before each test beforeEach(async () => { let r = await fetch( - serverUrl + "/login.pl?action=authenticate&company=" + encodeURI(company), + serverUrl + + "/login.pl?action=authenticate&company=" + + encodeURI(company), { method: "POST", body: JSON.stringify({ @@ -75,7 +82,7 @@ beforeEach(async () => { if (r.status === StatusCodes.OK) { await r.json(); headers = { - cookie: r.headers.get("set-cookie"), + cookie: r.headers.get("set-cookie") }; } }); @@ -101,65 +108,62 @@ describe("Adding the new Order", () => { it("POST /orders should allow adding a new order", async () => { let res; try { - res = await fetch( - serverUrl + "/" + api + "/orders", - { - method: "POST", - body: JSON.stringify({ - eca: { - number: "Customer 1", - type: "customer" // Watch for exact case or watch serverUrl stack dump - }, - currency: "USD", - dates: { - order: "2022-09-01", - "required-by": "2022-10-01" - }, - "internal-notes": "Internal notes", - lines: [ - { - part: { - number: "p1" - }, - price: 56.78, - price_fixated: false, - unit: "lbs", - qty: 1, - taxform: true, - serialnumber: "1234567890", - discount: 12, - discount_type: "%", - "required-by": "2022-10-27", - description: "A description" - } - ], - notes: "Notes", - "order-number": "order 345", - "po-number": "po 456", - "shipping-point": "shipping from here", - // TODO: Debug ship-to - // "ship-to": "ship to there", - "ship-via": "ship via", - taxes: { - "2150": { - tax: { - category: "2150" - }, - "base-amount": 50, - amount: 6.78, - source: "Part 1", - memo: "tax memo" // Could that be optional? + res = await fetch(serverUrl + "/" + api + "/orders", { + method: "POST", + body: JSON.stringify({ + eca: { + number: "Customer 1", + type: "customer" // Watch for exact case or watch serverUrl stack dump + }, + currency: "USD", + dates: { + order: "2022-09-01", + "required-by": "2022-10-01" + }, + "internal-notes": "Internal notes", + lines: [ + { + part: { + number: "p1" }, - }, - }), - headers: { ...headers, "Content-Type": "application/json" }, - } - ); - } catch(e) { + price: 56.78, + price_fixated: false, + unit: "lbs", + qty: 1, + taxform: true, + serialnumber: "1234567890", + discount: 12, + discount_type: "%", + "required-by": "2022-10-27", + description: "A description" + } + ], + notes: "Notes", + "order-number": "order 345", + "po-number": "po 456", + "shipping-point": "shipping from here", + // TODO: Debug ship-to + // "ship-to": "ship to there", + "ship-via": "ship via", + taxes: { + 2150: { + tax: { + category: "2150" + }, + "base-amount": 50, + amount: 6.78, + source: "Part 1", + memo: "tax memo" // Could that be optional? + } + } + }), + headers: { ...headers, "Content-Type": "application/json" } + }); + } catch (e) { console.log(e.response.data); } expect(res.status).toEqual(StatusCodes.CREATED); - expect(res.headers.get('location')).toMatch('./1'); + expect(res.headers.get("location")).toMatch("./1"); }); }); diff --git a/UI/tests/specs/openapi/API-products-pricegroups.spec.js b/UI/tests/specs/openapi/API-products-pricegroups.spec.js index 8a5bf8f379..11d20ba62a 100644 --- a/UI/tests/specs/openapi/API-products-pricegroups.spec.js +++ b/UI/tests/specs/openapi/API-products-pricegroups.spec.js @@ -4,14 +4,14 @@ import jestOpenAPI from "jest-openapi"; import { StatusCodes } from "http-status-codes"; import { create_database, drop_database } from "./database"; -import { server } from '../../common/mocks/server.js' +import { server } from "../../common/mocks/server.js"; // Load an OpenAPI file (YAML or JSON) into this plugin -const openapi = process.env.PWD.replace("/UI",""); -jestOpenAPI( openapi + "/openapi/API.yaml"); +const openapi = process.env.PWD.replace("/UI", ""); +jestOpenAPI(openapi + "/openapi/API.yaml"); // Load the API definition -const API_yaml = require (openapi + "/openapi/API.yaml"); +const API_yaml = require(openapi + "/openapi/API.yaml"); // Set API version to use const api = "erp/api/v0"; @@ -32,7 +32,7 @@ beforeAll(() => { // Establish API mocking before all tests. server.listen({ - onUnhandledRequest: 'bypass' + onUnhandledRequest: "bypass" }); }); @@ -40,7 +40,7 @@ afterAll(() => { drop_database(company); }); -const emulateAxiosResponse = async(res) => { +const emulateAxiosResponse = async (res) => { return { data: await res.json(), status: res.status, @@ -48,7 +48,7 @@ const emulateAxiosResponse = async(res) => { headers: res.headers, request: { path: res.url, - method: 'GET' + method: "GET" } }; }; @@ -56,7 +56,9 @@ const emulateAxiosResponse = async(res) => { // Log in before each test beforeEach(async () => { let r = await fetch( - serverUrl + "/login.pl?action=authenticate&company=" + encodeURI(company), + serverUrl + + "/login.pl?action=authenticate&company=" + + encodeURI(company), { method: "POST", body: JSON.stringify({ @@ -92,12 +94,9 @@ afterEach(async () => { describe("Retrieving all products/pricegroups", () => { it("GET /products/pricegroups should satisfy OpenAPI spec", async () => { // Get an HTTP response from your serverUrl - let res = await fetch( - serverUrl + "/" + api + "/products/pricegroups", - { - headers: headers - } - ); + let res = await fetch(serverUrl + "/" + api + "/products/pricegroups", { + headers: headers + }); expect(res.status).toEqual(StatusCodes.OK); // Assert that the HTTP response satisfies the OpenAPI spec @@ -108,39 +107,42 @@ describe("Retrieving all products/pricegroups", () => { describe("Retrieving all products/pricegroups with old syntax should fail", () => { it("GET /products/pricegroups/ should fail", async () => { - let res = await fetch(serverUrl + "/" + api + "/products/pricegroups/", { - headers: headers - }); + let res = await fetch( + serverUrl + "/" + api + "/products/pricegroups/", + { + headers: headers + } + ); expect(res.status).toEqual(StatusCodes.NOT_FOUND); }); }); describe("Retrieve non-existant Pricegroup1", () => { it("GET /products/pricegroups/nv should not retrieve Pricegroup1", async () => { - let res = await fetch(serverUrl + "/" + api + "/products/pricegroups/1", { - headers: headers - }); + let res = await fetch( + serverUrl + "/" + api + "/products/pricegroups/1", + { + headers: headers + } + ); expect(res.status).toEqual(StatusCodes.NOT_FOUND); }); }); describe("Adding the new Price Group", () => { it("POST /products/pricegroups/Pricegroup1 should allow adding Pricegroup1", async () => { - let res = await fetch( - serverUrl + "/" + api + "/products/pricegroups", - { - method: "POST", - body: JSON.stringify({ - name: "Pricegroup1", - description: "Pricegroup1" - }), - headers: { - "X-Requested-With": "XMLHttpRequest", - "Content-Type": "application/json", - ...headers - } + let res = await fetch(serverUrl + "/" + api + "/products/pricegroups", { + method: "POST", + body: JSON.stringify({ + name: "Pricegroup1", + description: "Pricegroup1" + }), + headers: { + "X-Requested-With": "XMLHttpRequest", + "Content-Type": "application/json", + ...headers } - ); + }); expect(res.status).toEqual(StatusCodes.CREATED); // Assert that the HTTP response satisfies the OpenAPI spec @@ -151,13 +153,17 @@ describe("Adding the new Price Group", () => { describe("Validate against the example Pricegroup", () => { it("GET /products/pricegroups/1", async () => { - let res = await fetch(serverUrl + "/" + api + "/products/pricegroups/1", { - headers: headers - }); + let res = await fetch( + serverUrl + "/" + api + "/products/pricegroups/1", + { + headers: headers + } + ); expect(res.status).toEqual(StatusCodes.OK); // Pick the example - const pricegroupExample = API_yaml.components.examples.validPricegroup.value; + const pricegroupExample = + API_yaml.components.examples.validPricegroup.value; // Assert that the response matches the example in the spec res = await emulateAxiosResponse(res); @@ -176,21 +182,18 @@ describe("Modifying the new Price Group", () => { expect(res.status).toEqual(StatusCodes.OK); const etag = res.headers.get("etag"); expect(etag).toBeDefined(); - res = await fetch( - serverUrl + "/" + api + "/products/pricegroups/1", - { - method: "PUT", - body: JSON.stringify({ - id: 1, - description: "PriceGroup1" - }), - headers: { - ...headers, - "content-type": "application/json", - "If-Match": etag - } + res = await fetch(serverUrl + "/" + api + "/products/pricegroups/1", { + method: "PUT", + body: JSON.stringify({ + id: 1, + description: "PriceGroup1" + }), + headers: { + ...headers, + "content-type": "application/json", + "If-Match": etag } - ); + }); expect(res.status).toEqual(StatusCodes.OK); // Assert that the HTTP response satisfies the OpenAPI spec diff --git a/UI/tests/specs/openapi/API-products-warehouses.spec.js b/UI/tests/specs/openapi/API-products-warehouses.spec.js index 7ae7829bf8..ed3a01ae0d 100644 --- a/UI/tests/specs/openapi/API-products-warehouses.spec.js +++ b/UI/tests/specs/openapi/API-products-warehouses.spec.js @@ -4,14 +4,14 @@ import jestOpenAPI from "jest-openapi"; import { StatusCodes } from "http-status-codes"; import { create_database, drop_database } from "./database"; -import { server } from '../../common/mocks/server.js' +import { server } from "../../common/mocks/server.js"; // Load an OpenAPI file (YAML or JSON) into this plugin -const openapi = process.env.PWD.replace("/UI",""); -jestOpenAPI( openapi + "/openapi/API.yaml"); +const openapi = process.env.PWD.replace("/UI", ""); +jestOpenAPI(openapi + "/openapi/API.yaml"); // Load the API definition -const API_yaml = require (openapi + "/openapi/API.yaml"); +const API_yaml = require(openapi + "/openapi/API.yaml"); // Set API version to use const api = "erp/api/v0"; @@ -32,7 +32,7 @@ beforeAll(() => { // Establish API mocking before all tests. server.listen({ - onUnhandledRequest: 'bypass' + onUnhandledRequest: "bypass" }); }); @@ -40,7 +40,7 @@ afterAll(() => { drop_database(company); }); -const emulateAxiosResponse = async(res) => { +const emulateAxiosResponse = async (res) => { return { data: await res.json(), status: res.status, @@ -48,7 +48,7 @@ const emulateAxiosResponse = async(res) => { headers: res.headers, request: { path: res.url, - method: 'GET' + method: "GET" } }; }; @@ -56,7 +56,9 @@ const emulateAxiosResponse = async(res) => { // Log in before each test beforeEach(async () => { let r = await fetch( - serverUrl + "/login.pl?action=authenticate&company=" + encodeURI(company), + serverUrl + + "/login.pl?action=authenticate&company=" + + encodeURI(company), { method: "POST", body: JSON.stringify({ @@ -105,38 +107,41 @@ describe("Retrieving all products/warehouses", () => { describe("Retrieving all products/warehouses with old syntax should fail", () => { it("GET /products/warehouses/ should fail", async () => { - const res = await fetch(serverUrl + "/" + api + "/products/warehouses/", { - headers: headers - }); + const res = await fetch( + serverUrl + "/" + api + "/products/warehouses/", + { + headers: headers + } + ); expect(res.status).toEqual(StatusCodes.NOT_FOUND); }); }); describe("Retrieve non-existant Warehouse1", () => { it("GET /products/warehouses/nv should not retrieve Warehouse1", async () => { - const res = await fetch(serverUrl + "/" + api + "/products/warehouses/1", { - headers: headers - }); + const res = await fetch( + serverUrl + "/" + api + "/products/warehouses/1", + { + headers: headers + } + ); expect(res.status).toEqual(StatusCodes.NOT_FOUND); }); }); describe("Adding the new Warehouse", () => { it("POST /products/warehouses/Warehouse1 should allow adding Warehouse1", async () => { - let res = await fetch( - serverUrl + "/" + api + "/products/warehouses", - { - method: "POST", - body: JSON.stringify({ - description: "Warehouse1" - }), - headers: { - "X-Requested-With": "XMLHttpRequest", - "Content-Type": "application/json", - ...headers - }, + let res = await fetch(serverUrl + "/" + api + "/products/warehouses", { + method: "POST", + body: JSON.stringify({ + description: "Warehouse1" + }), + headers: { + "X-Requested-With": "XMLHttpRequest", + "Content-Type": "application/json", + ...headers } - ); + }); expect(res.status).toEqual(StatusCodes.CREATED); // Assert that the HTTP response satisfies the OpenAPI spec @@ -147,13 +152,17 @@ describe("Adding the new Warehouse", () => { describe("Validate against the example Warehouse", () => { it("GET /products/warehouses/1", async () => { - let res = await fetch(serverUrl + "/" + api + "/products/warehouses/1", { - headers: headers - }); + let res = await fetch( + serverUrl + "/" + api + "/products/warehouses/1", + { + headers: headers + } + ); expect(res.status).toEqual(StatusCodes.OK); // Pick the example - const warehouseExample = API_yaml.components.examples.validWarehouse.value; + const warehouseExample = + API_yaml.components.examples.validWarehouse.value; // Assert that the response matches the example in the spec res = await emulateAxiosResponse(res); @@ -172,21 +181,18 @@ describe("Modifying the new Warehouse", () => { expect(res.status).toEqual(StatusCodes.OK); const etag = res.headers.get("etag"); expect(etag).toBeDefined(); - res = await fetch( - serverUrl + "/" + api + "/products/warehouses/1", - { - method: "PUT", - body: JSON.stringify({ - id: 1, - description: "PriceGroup1" - }), - headers: { - ...headers, - "content-type": "application/json", - "If-Match": etag - } + res = await fetch(serverUrl + "/" + api + "/products/warehouses/1", { + method: "PUT", + body: JSON.stringify({ + id: 1, + description: "PriceGroup1" + }), + headers: { + ...headers, + "content-type": "application/json", + "If-Match": etag } - ); + }); expect(res.status).toEqual(StatusCodes.OK); // Assert that the HTTP response satisfies the OpenAPI spec @@ -237,7 +243,8 @@ describe("Updating the new Warehouse1", () => { describe("Not removing the new Warehouse", () => { it("DELETE /products/warehouses/PriceGroup1 should allow deleting Warehouse1", async () => { let res = await fetch( - serverUrl + "/" + api + "/products/warehouses/1", { + serverUrl + "/" + api + "/products/warehouses/1", + { headers: headers } ); diff --git a/UI/tests/specs/stores/business-types.spec.js b/UI/tests/specs/stores/business-types.spec.js index 9627fce224..4da4825181 100644 --- a/UI/tests/specs/stores/business-types.spec.js +++ b/UI/tests/specs/stores/business-types.spec.js @@ -15,16 +15,32 @@ beforeEach(() => { describe("Business Types Store", () => { it("initialize", async () => { await businessTypes.initialize(); - expect(businessTypes.fields).toStrictEqual(["id", "description", "discount"]); + expect(businessTypes.fields).toStrictEqual([ + "id", + "description", + "discount" + ]); expect(businessTypes.items).toStrictEqual([ - { id: "1", description: "Big customer", discount: 0.05, _meta: { ETag: "1234567890" }}, - { id: "2", description: "Bigger customer", discount: 0.15, _meta: { ETag: "1234567890" }} + { + id: "1", + description: "Big customer", + discount: 0.05, + _meta: { ETag: "1234567890" } + }, + { + id: "2", + description: "Bigger customer", + discount: 0.15, + _meta: { ETag: "1234567890" } + } + ]); + expect(businessTypes._links).toStrictEqual([ + { + title: "HTML", + rel: "download", + href: "?format=HTML" + } ]); - expect(businessTypes._links).toStrictEqual([{ - title : "HTML", - rel : "download", - href : "?format=HTML" - }]); }); it("get Business Type #2", async () => { @@ -41,22 +57,43 @@ describe("Business Types Store", () => { it("update Business Type #2", async () => { await businessTypes.initialize(); await businessTypes.get("2"); - await businessTypes.save("2", { description: "Bigger customer", discount: 0.25 }); + await businessTypes.save("2", { + description: "Bigger customer", + discount: 0.25 + }); expect(businessTypes.items).toStrictEqual([ - { id: "1", description: "Big customer", discount: 0.05, _meta: { ETag: "1234567890" }}, - { id: "2", description: "Bigger customer", discount: 0.25, _meta: { ETag: "1234567891" }} + { + id: "1", + description: "Big customer", + discount: 0.05, + _meta: { ETag: "1234567890" } + }, + { + id: "2", + description: "Bigger customer", + discount: 0.25, + _meta: { ETag: "1234567891" } + } ]); }); it("get Invalid Business Type #3", async () => { await businessTypes.initialize(); - await expect(async () => {await businessTypes.get("3")}).rejects.toThrow("HTTP Error: 404"); + await expect(async () => { + await businessTypes.get("3"); + }).rejects.toThrow("HTTP Error: 404"); }); it("add Business Type #3", async () => { await businessTypes.initialize(); - await businessTypes.add({ id: "3", description: "Great customer", discount: 0.22 }); - expect(businessTypes.items[businessTypes.items.length-1]).toStrictEqual({ + await businessTypes.add({ + id: "3", + description: "Great customer", + discount: 0.22 + }); + expect( + businessTypes.items[businessTypes.items.length - 1] + ).toStrictEqual({ _meta: { ETag: "1234567891" }, id: "3", description: "Great customer", diff --git a/UI/tests/specs/stores/countries.spec.js b/UI/tests/specs/stores/countries.spec.js index 697d783d67..cfd6a3fffd 100644 --- a/UI/tests/specs/stores/countries.spec.js +++ b/UI/tests/specs/stores/countries.spec.js @@ -15,16 +15,33 @@ beforeEach(() => { describe("Country Store", () => { it("initialize", async () => { await countries.initialize(); - expect(countries.fields).toStrictEqual(["_meta", "code", "default", "name"]); + expect(countries.fields).toStrictEqual([ + "_meta", + "code", + "default", + "name" + ]); expect(countries.items).toStrictEqual([ - { code: "ca", default: false, name: "Canada", _meta: { ETag: "2345678901" }}, - { code: "us", default: false, name: "United States", _meta: { ETag: "1234567890" }} + { + code: "ca", + default: false, + name: "Canada", + _meta: { ETag: "2345678901" } + }, + { + code: "us", + default: false, + name: "United States", + _meta: { ETag: "1234567890" } + } + ]); + expect(countries._links).toStrictEqual([ + { + title: "HTML", + rel: "download", + href: "?format=HTML" + } ]); - expect(countries._links).toStrictEqual([{ - title : "HTML", - rel : "download", - href : "?format=HTML" - }]); }); it("get United States country us", async () => { @@ -43,20 +60,32 @@ describe("Country Store", () => { await countries.get("us"); await countries.save("us", { code: "us", name: "America" }); expect(countries.items).toStrictEqual([ - { code: "ca", default: false, name: "Canada", _meta: { ETag: "2345678901" }}, - { code: "us", default: false, name: "America", _meta: { ETag: "1234567891" }} + { + code: "ca", + default: false, + name: "Canada", + _meta: { ETag: "2345678901" } + }, + { + code: "us", + default: false, + name: "America", + _meta: { ETag: "1234567891" } + } ]); }); it("get Invalid country zz", async () => { await countries.initialize(); - await expect(async () => {await countries.get("zz")}).rejects.toThrow("HTTP Error: 404"); + await expect(async () => { + await countries.get("zz"); + }).rejects.toThrow("HTTP Error: 404"); }); it("add Atlantida country zz", async () => { await countries.initialize(); await countries.add({ code: "zz", name: "Atlantida" }); - expect(countries.items[countries.items.length-1]).toStrictEqual({ + expect(countries.items[countries.items.length - 1]).toStrictEqual({ _meta: { ETag: "1234567891" }, code: "zz", name: "Atlantida" diff --git a/UI/tests/specs/stores/gifis.spec.js b/UI/tests/specs/stores/gifis.spec.js index f186a70aa3..8bc1bc43bb 100644 --- a/UI/tests/specs/stores/gifis.spec.js +++ b/UI/tests/specs/stores/gifis.spec.js @@ -12,14 +12,21 @@ beforeEach(() => { gifies = useGIFIsStore(pinia); }); - describe("GIFI Store", () => { it("initialize", async () => { await gifies.initialize(); expect(gifies.fields).toStrictEqual(["accno", "description"]); expect(await gifies.items).toStrictEqual([ - { accno: "0000", description: "Dummy account", _meta: { ETag: "1234567890" } }, - { accno: "0001", description: "Dummy account 1", _meta: { ETag: "1234567889" } } + { + accno: "0000", + description: "Dummy account", + _meta: { ETag: "1234567890" } + }, + { + accno: "0001", + description: "Dummy account 1", + _meta: { ETag: "1234567889" } + } ]); }); @@ -36,22 +43,35 @@ describe("GIFI Store", () => { it("save Funny account 0000", async () => { await gifies.initialize(); await gifies.get("0000"); - await gifies.save("0000", { accno: "0000", description: "Funny account" }); + await gifies.save("0000", { + accno: "0000", + description: "Funny account" + }); expect(gifies.items).toStrictEqual([ - { accno: "0000", description: "Funny account", _meta: { ETag: "1234567891" } }, - { accno: "0001", description: "Dummy account 1", _meta: { ETag: "1234567889" } } + { + accno: "0000", + description: "Funny account", + _meta: { ETag: "1234567891" } + }, + { + accno: "0001", + description: "Dummy account 1", + _meta: { ETag: "1234567889" } + } ]); }); it("get Invalid GIFI 0002", async () => { await gifies.initialize(); - await expect(async () => {await gifies.get("0002")}).rejects.toThrow("HTTP Error: 404"); + await expect(async () => { + await gifies.get("0002"); + }).rejects.toThrow("HTTP Error: 404"); }); it("add Dummy account 0002", async () => { await gifies.initialize(); await gifies.add({ accno: "0002", description: "Dummy account 2" }); - expect(gifies.items[gifies.items.length-1]).toStrictEqual({ + expect(gifies.items[gifies.items.length - 1]).toStrictEqual({ _meta: { ETag: "1234567891" }, accno: "0002", description: "Dummy account 2" diff --git a/UI/tests/specs/stores/languages.spec.js b/UI/tests/specs/stores/languages.spec.js index 473cb897b2..947d2001f5 100644 --- a/UI/tests/specs/stores/languages.spec.js +++ b/UI/tests/specs/stores/languages.spec.js @@ -15,16 +15,33 @@ beforeEach(() => { describe("Language Store", () => { it("initialize", async () => { await languages.initialize(); - expect(languages.fields).toStrictEqual(["_meta", "code", "default", "description"]); + expect(languages.fields).toStrictEqual([ + "_meta", + "code", + "default", + "description" + ]); expect(languages.items).toStrictEqual([ - { code: "en", default: false, description: "English", _meta: { ETag: '1234567890' } }, - { code: "fr", default: false, description: "Français", _meta: { ETag: '2345678901' } } + { + code: "en", + default: false, + description: "English", + _meta: { ETag: "1234567890" } + }, + { + code: "fr", + default: false, + description: "Français", + _meta: { ETag: "2345678901" } + } + ]); + expect(languages._links).toStrictEqual([ + { + title: "HTML", + rel: "download", + href: "?format=HTML" + } ]); - expect(languages._links).toStrictEqual([{ - title : "HTML", - rel : "download", - href : "?format=HTML" - }]); }); it("get English languages en", async () => { @@ -41,22 +58,37 @@ describe("Language Store", () => { it("save English american language en", async () => { await languages.initialize(); await languages.get("en"); - await languages.save("en", { code: "en", description: "English (american)" }); + await languages.save("en", { + code: "en", + description: "English (american)" + }); expect(languages.items).toStrictEqual([ - { code: "en", default: false, description: "English (american)", _meta: { ETag: '1234567891' } }, - { code: "fr", default: false, description: "Français", _meta: { ETag: '2345678901' } } + { + code: "en", + default: false, + description: "English (american)", + _meta: { ETag: "1234567891" } + }, + { + code: "fr", + default: false, + description: "Français", + _meta: { ETag: "2345678901" } + } ]); }); it("get Invalid language zz", async () => { await languages.initialize(); - await expect(async () => {await languages.get("zz")}).rejects.toThrow("HTTP Error: 404"); + await expect(async () => { + await languages.get("zz"); + }).rejects.toThrow("HTTP Error: 404"); }); it("add Mayan language my", async () => { await languages.initialize(); await languages.add({ code: "my", description: "Mayan" }); - expect(languages.items[languages.items.length-1]).toStrictEqual({ + expect(languages.items[languages.items.length - 1]).toStrictEqual({ _meta: { ETag: "1234567891" }, code: "my", description: "Mayan" diff --git a/UI/tests/specs/stores/pricegroups.spec.js b/UI/tests/specs/stores/pricegroups.spec.js index 1c8de188e1..f7dbe6f71d 100644 --- a/UI/tests/specs/stores/pricegroups.spec.js +++ b/UI/tests/specs/stores/pricegroups.spec.js @@ -17,14 +17,24 @@ describe("Pricegroup Store", () => { await pricegroups.initialize(); expect(pricegroups.fields).toStrictEqual(["id", "description"]); expect(pricegroups.items).toStrictEqual([ - { id: "1", description: "Price group 1", _meta: { ETag: "1234567890" } }, - { id: "2", description: "Price group 2", _meta: { ETag: "1234567889" } } - ]); - expect(pricegroups._links).toStrictEqual([{ - title : "HTML", - rel : "download", - href : "?format=HTML" - }]); + { + id: "1", + description: "Price group 1", + _meta: { ETag: "1234567890" } + }, + { + id: "2", + description: "Price group 2", + _meta: { ETag: "1234567889" } + } + ]); + expect(pricegroups._links).toStrictEqual([ + { + title: "HTML", + rel: "download", + href: "?format=HTML" + } + ]); }); it("get Price Group 1", async () => { @@ -42,20 +52,30 @@ describe("Pricegroup Store", () => { await pricegroups.get("1"); await pricegroups.save("1", { id: "1", description: "Price Group #1" }); expect(pricegroups.items).toStrictEqual([ - { id: "1", description: "Price Group #1", _meta: { ETag: "1234567891" } }, - { id: "2", description: "Price group 2", _meta: { ETag: "1234567889" } } + { + id: "1", + description: "Price Group #1", + _meta: { ETag: "1234567891" } + }, + { + id: "2", + description: "Price group 2", + _meta: { ETag: "1234567889" } + } ]); }); it("get Invalid Price Group 3", async () => { await pricegroups.initialize(); - await expect(async () => {await pricegroups.get("3")}).rejects.toThrow("HTTP Error: 404"); + await expect(async () => { + await pricegroups.get("3"); + }).rejects.toThrow("HTTP Error: 404"); }); it("add Price Group 3", async () => { await pricegroups.initialize(); await pricegroups.add({ id: "3", description: "Price Group #3" }); - expect(pricegroups.items[pricegroups.items.length-1]).toStrictEqual({ + expect(pricegroups.items[pricegroups.items.length - 1]).toStrictEqual({ _meta: { ETag: "1234567891" }, id: "3", description: "Price Group #3" diff --git a/UI/tests/specs/stores/sessionUser.spec.js b/UI/tests/specs/stores/sessionUser.spec.js index 825631b0da..949b31e2fd 100644 --- a/UI/tests/specs/stores/sessionUser.spec.js +++ b/UI/tests/specs/stores/sessionUser.spec.js @@ -23,11 +23,11 @@ describe("Session Store", () => { "gl_all" ]); expect(session.preferences).toStrictEqual({ - "numberformat" : "1000.00", - "printer" : null, - "stylesheet" : "ledgersmb.css", - "dateformat" : "yyyy-mm-dd", - "language" : null + numberformat: "1000.00", + printer: null, + stylesheet: "ledgersmb.css", + dateformat: "yyyy-mm-dd", + language: null }); expect(session.hasRole("cash_all")).toBe(true); expect(session.hasRole("invalid role")).toBe(false); diff --git a/UI/tests/specs/stores/sics.spec.js b/UI/tests/specs/stores/sics.spec.js index edc6b059ad..21cd033d93 100644 --- a/UI/tests/specs/stores/sics.spec.js +++ b/UI/tests/specs/stores/sics.spec.js @@ -17,14 +17,24 @@ describe("Sic Store", () => { await sics.initialize(); expect(sics.fields).toStrictEqual(["code", "sictype", "description"]); expect(sics.items).toStrictEqual([ - { code: "541330", description: "Engineering service", _meta: { ETag: "1234567890" } }, - { code: "611430", description: "Professional and management development training", _meta: { ETag: "1234567889" } } + { + code: "541330", + description: "Engineering service", + _meta: { ETag: "1234567890" } + }, + { + code: "611430", + description: "Professional and management development training", + _meta: { ETag: "1234567889" } + } + ]); + expect(sics._links).toStrictEqual([ + { + title: "HTML", + rel: "download", + href: "?format=HTML" + } ]); - expect(sics._links).toStrictEqual([{ - title : "HTML", - rel : "download", - href : "?format=HTML" - }]); }); it("get Computer systems integrators sics 541330", async () => { @@ -40,22 +50,38 @@ describe("Sic Store", () => { it("save Computer Systems Design and Related Services sic 541330", async () => { await sics.initialize(); await sics.get("541330"); - await sics.save("541330", { code: "541330", description: "Engineering services" }); + await sics.save("541330", { + code: "541330", + description: "Engineering services" + }); expect(sics.items).toStrictEqual([ - { code: "541330", description: "Engineering services", _meta: { ETag: "1234567891" } }, - { code: "611430", description: "Professional and management development training", _meta: { ETag: "1234567889" } } + { + code: "541330", + description: "Engineering services", + _meta: { ETag: "1234567891" } + }, + { + code: "611430", + description: "Professional and management development training", + _meta: { ETag: "1234567889" } + } ]); }); it("get Invalid sic 541510", async () => { await sics.initialize(); - await expect(async () => {await sics.get("541510")}).rejects.toThrow("HTTP Error: 404"); + await expect(async () => { + await sics.get("541510"); + }).rejects.toThrow("HTTP Error: 404"); }); it("add Design of computer systems sic 541510", async () => { await sics.initialize(); - await sics.add({ code: "541510", description: "Design of computer systems" }); - expect(sics.items[sics.items.length-1]).toStrictEqual({ + await sics.add({ + code: "541510", + description: "Design of computer systems" + }); + expect(sics.items[sics.items.length - 1]).toStrictEqual({ _meta: { ETag: "1234567891" }, code: "541510", description: "Design of computer systems" diff --git a/UI/tests/specs/stores/warehouses.spec.js b/UI/tests/specs/stores/warehouses.spec.js index affb4525aa..c0e9fef0bc 100644 --- a/UI/tests/specs/stores/warehouses.spec.js +++ b/UI/tests/specs/stores/warehouses.spec.js @@ -17,15 +17,29 @@ describe("Warehouses Store", () => { await warehouses.initialize(); expect(warehouses.fields).toStrictEqual(["id", "description"]); expect(warehouses.items).toStrictEqual([ - { id: "1", description: "Modern warehouse", _meta: { ETag: "1234567892" } }, - { id: "2", description: "Huge warehouse", _meta: { ETag: "1234567890" } }, - { id: "3", description: "Moon warehouse", _meta: { ETag: "1234567893" } } + { + id: "1", + description: "Modern warehouse", + _meta: { ETag: "1234567892" } + }, + { + id: "2", + description: "Huge warehouse", + _meta: { ETag: "1234567890" } + }, + { + id: "3", + description: "Moon warehouse", + _meta: { ETag: "1234567893" } + } + ]); + expect(warehouses._links).toStrictEqual([ + { + title: "HTML", + rel: "download", + href: "?format=HTML" + } ]); - expect(warehouses._links).toStrictEqual([{ - title : "HTML", - rel : "download", - href : "?format=HTML" - }]); }); it("get warehouse #2", async () => { @@ -41,23 +55,40 @@ describe("Warehouses Store", () => { it("update warehouse #2", async () => { await warehouses.initialize(); await warehouses.get("2"); - await warehouses.save("2", { id: "2", description: "Biggest warehouse" }); + await warehouses.save("2", { + id: "2", + description: "Biggest warehouse" + }); expect(warehouses.items).toStrictEqual([ - { id: "1", description: "Modern warehouse", _meta: { ETag: "1234567892" } }, - { id: "2", description: "Biggest warehouse", _meta: { ETag: "1234567891" } }, - { id: "3", description: "Moon warehouse", _meta: { ETag: "1234567893" } } + { + id: "1", + description: "Modern warehouse", + _meta: { ETag: "1234567892" } + }, + { + id: "2", + description: "Biggest warehouse", + _meta: { ETag: "1234567891" } + }, + { + id: "3", + description: "Moon warehouse", + _meta: { ETag: "1234567893" } + } ]); }); it("get Invalid warehouse #4", async () => { await warehouses.initialize(); - await expect(async () => {await warehouses.get("4")}).rejects.toThrow("HTTP Error: 404"); + await expect(async () => { + await warehouses.get("4"); + }).rejects.toThrow("HTTP Error: 404"); }); it("add Mars warehouse", async () => { await warehouses.initialize(); await warehouses.add({ id: "4", description: "Mars warehouse" }); - expect(warehouses.items[warehouses.items.length-1]).toStrictEqual({ + expect(warehouses.items[warehouses.items.length - 1]).toStrictEqual({ _meta: { ETag: "1234567891" }, id: "4", description: "Mars warehouse" diff --git a/UI/tests/specs/views/BusinessTypes.spec.js b/UI/tests/specs/views/BusinessTypes.spec.js index ffdf8874e5..212b01c44b 100644 --- a/UI/tests/specs/views/BusinessTypes.spec.js +++ b/UI/tests/specs/views/BusinessTypes.spec.js @@ -1,4 +1,8 @@ -/* global retry */ +/** + * global retry + * + * @format + */ import BusinessTypes from "@/views/BusinessTypes.vue"; import { useSessionUserStore } from "@/store/sessionUser"; @@ -8,7 +12,6 @@ let wrapper; let sessionUser; describe("BusinessTypes - register as a component", () => { - beforeEach(() => { wrapper = factory(BusinessTypes); sessionUser = useSessionUserStore(); @@ -18,28 +21,29 @@ describe("BusinessTypes - register as a component", () => { }); it("should show dialog", async () => { - expect(wrapper.exists()).toBeTruthy(); // Check loading expect(wrapper.get(".dynatableLoading").text()).toBe("Loading..."); // Wait until loading done - await retry(() => expect(wrapper.find(".dynatableData").isVisible()).toBe(true)); + await retry(() => + expect(wrapper.find(".dynatableData").isVisible()).toBe(true) + ); // Validate against snapshot expect(wrapper.element).toMatchSnapshot(); - const businessType_items = wrapper.findAll('.data-row'); + const businessType_items = wrapper.findAll(".data-row"); expect(businessType_items).toHaveLength(2); // Validate data displayed let data = businessType_items.map((rows) => { - return rows.findAll('.input-box').map(row => row.element.value) + return rows.findAll(".input-box").map((row) => row.element.value); }); expect(data).toEqual([ - [ "Big customer", "0.05"], - [ "Bigger customer", "0.15"] + ["Big customer", "0.05"], + ["Bigger customer", "0.15"] ]); // TODO: Test links @@ -47,10 +51,9 @@ describe("BusinessTypes - register as a component", () => { // what was returned by the API }); - it("should show dialog with editable data", async () => { - + it("should show dialog with editable data", async () => { // Give user edition capability - sessionUser.$patch({roles: ["business_type_edit"]}); + sessionUser.$patch({ roles: ["business_type_edit"] }); expect(wrapper.exists()).toBeTruthy(); @@ -58,30 +61,32 @@ describe("BusinessTypes - register as a component", () => { expect(wrapper.get(".dynatableLoading").text()).toBe("Loading..."); // Wait until loading done - await retry(() => expect(wrapper.find(".dynatableData").isVisible()).toBe(true)); + await retry(() => + expect(wrapper.find(".dynatableData").isVisible()).toBe(true) + ); // Validate against snapshot expect(wrapper.element).toMatchSnapshot(); - const businessType_items = wrapper.findAll('.data-row'); + const businessType_items = wrapper.findAll(".data-row"); expect(businessType_items).toHaveLength(2); // Validate data displayed let data = businessType_items.map((rows) => { - return rows.findAll('.input-box').map(row => row.element.value) + return rows.findAll(".input-box").map((row) => row.element.value); }); expect(data).toEqual([ - [ "Big customer", "0.05"], - [ "Bigger customer", "0.15"] + ["Big customer", "0.05"], + ["Bigger customer", "0.15"] ]); // Validate the buttons const buttons = businessType_items.map((rows) => { - return rows.findAll('button').map(row => row.element.name) + return rows.findAll("button").map((row) => row.element.name); }); expect(buttons).toEqual([ - [ 'modify', 'save', 'cancel' ], - [ 'modify', 'save', 'cancel' ] + ["modify", "save", "cancel"], + ["modify", "save", "cancel"] ]); }); }); diff --git a/UI/tests/specs/views/Countries.spec.js b/UI/tests/specs/views/Countries.spec.js index 03be9c1f37..36b20eaf47 100644 --- a/UI/tests/specs/views/Countries.spec.js +++ b/UI/tests/specs/views/Countries.spec.js @@ -1,4 +1,8 @@ -/* global retry */ +/** + * global retry + * + * @format + */ import Countries from "@/views/Countries.vue"; import { useSessionUserStore } from "@/store/sessionUser"; @@ -8,31 +12,31 @@ let wrapper; let sessionUser; describe("Countries - register as a component", () => { - beforeEach(() => { wrapper = factory(Countries); sessionUser = useSessionUserStore(); }); it("should show dialog", async () => { - expect(wrapper.exists()).toBeTruthy(); // Check loading expect(wrapper.get(".dynatableLoading").text()).toBe("Loading..."); // Wait until loading done - await retry(() => expect(wrapper.find(".dynatableData").isVisible()).toBe(true)); + await retry(() => + expect(wrapper.find(".dynatableData").isVisible()).toBe(true) + ); // Validate against snapshot expect(wrapper.element).toMatchSnapshot(); - const country_items = wrapper.findAll('.data-row'); + const country_items = wrapper.findAll(".data-row"); expect(country_items).toHaveLength(2); // Validate data displayed let data = country_items.map((rows) => { - return rows.findAll('.input-box').map(row => row.element.value) + return rows.findAll(".input-box").map((row) => row.element.value); }); expect(data).toEqual([ ["ca", "Canada"], @@ -45,9 +49,8 @@ describe("Countries - register as a component", () => { }); it("should show dialog with editable data", async () => { - // Give user edition capability - sessionUser.$patch({roles: ["country_edit"]}); + sessionUser.$patch({ roles: ["country_edit"] }); expect(wrapper.exists()).toBeTruthy(); @@ -55,14 +58,16 @@ describe("Countries - register as a component", () => { expect(wrapper.get(".dynatableLoading").text()).toBe("Loading..."); // Wait until loading done - await retry(() => expect(wrapper.find(".dynatableData").isVisible()).toBe(true)); + await retry(() => + expect(wrapper.find(".dynatableData").isVisible()).toBe(true) + ); - const country_items = wrapper.findAll('.data-row'); + const country_items = wrapper.findAll(".data-row"); expect(country_items).toHaveLength(2); // Validate data displayed let data = country_items.map((rows) => { - return rows.findAll('.input-box').map(row => row.element.value) + return rows.findAll(".input-box").map((row) => row.element.value); }); expect(data).toEqual([ ["ca", "Canada"], @@ -70,66 +75,73 @@ describe("Countries - register as a component", () => { ]); const defaults = country_items.map((rows) => { - return rows.findAll('input[name="default"]').map(row => row.element.checked).at(0) + return rows + .findAll('input[name="default"]') + .map((row) => row.element.checked) + .at(0); }); - expect(defaults).toEqual([ - false, false - ]); + expect(defaults).toEqual([false, false]); // Validate the buttons const buttons = country_items.map((rows) => { - return rows.findAll('button').map(row => row.element.name) + return rows.findAll("button").map((row) => row.element.name); }); expect(buttons).toEqual([ - [ 'change-default', 'modify', 'save', 'cancel' ], - [ 'change-default', 'modify', 'save', 'cancel' ] + ["change-default", "modify", "save", "cancel"], + ["change-default", "modify", "save", "cancel"] ]); }); it("should allow setting a default country", async () => { - // Give user edition capability - sessionUser.$patch({roles: ["country_edit"]}); + sessionUser.$patch({ roles: ["country_edit"] }); // Check loading expect(wrapper.get(".dynatableLoading").text()).toBe("Loading..."); // Wait until loading done - await retry(() => expect(wrapper.find(".dynatableData").isVisible()).toBe(true)); + await retry(() => + expect(wrapper.find(".dynatableData").isVisible()).toBe(true) + ); - let country_items = wrapper.findAll('.data-row'); + let country_items = wrapper.findAll(".data-row"); let defaults = country_items.map((rows) => { - return rows.findAll('input[name="default"]').map(row => row.element.checked).at(0) + return rows + .findAll('input[name="default"]') + .map((row) => row.element.checked) + .at(0); }); // No country selected - expect(defaults).toEqual([ - false, false - ]); + expect(defaults).toEqual([false, false]); // Validate the buttons const buttons = country_items.map((rows) => { return rows.find("button[name='change-default']"); }); // Set the default - await buttons[0].trigger('click'); + await buttons[0].trigger("click"); await retry(() => expect(buttons[0].isVisible()).toBe(false)); - country_items = wrapper.findAll('.data-row'); + country_items = wrapper.findAll(".data-row"); - expect(country_items.map((rows) => { - return rows.findAll('.input-box').map(row => row.element.value) - })).toEqual([ + expect( + country_items.map((rows) => { + return rows + .findAll(".input-box") + .map((row) => row.element.value); + }) + ).toEqual([ ["ca", "Canada"], ["us", "United States"] ]); defaults = country_items.map((rows) => { - return rows.findAll('input[name="default"]').map(row => row.element.checked).at(0) + return rows + .findAll('input[name="default"]') + .map((row) => row.element.checked) + .at(0); }); - expect(defaults).toEqual([ - true, false - ]); - + expect(defaults).toEqual([true, false]); }); }); diff --git a/UI/tests/specs/views/GIFI.spec.js b/UI/tests/specs/views/GIFI.spec.js index a17c1023fb..e6f7f1e538 100644 --- a/UI/tests/specs/views/GIFI.spec.js +++ b/UI/tests/specs/views/GIFI.spec.js @@ -1,4 +1,8 @@ -/* global retry */ +/** + * global retry + * + * @format + */ import GIFI from "@/views/GIFI.vue"; import { useSessionUserStore } from "@/store/sessionUser"; @@ -8,7 +12,6 @@ let wrapper; let sessionUser; describe("GIFI - register as a component", () => { - beforeEach(() => { wrapper = factory(GIFI); sessionUser = useSessionUserStore(); @@ -18,24 +21,25 @@ describe("GIFI - register as a component", () => { }); it("should show dialog", async () => { - expect(wrapper.exists()).toBeTruthy(); // Check loading expect(wrapper.get(".dynatableLoading").text()).toBe("Loading..."); // Wait until loading done - await retry(() => expect(wrapper.find(".dynatableData").isVisible()).toBe(true)); + await retry(() => + expect(wrapper.find(".dynatableData").isVisible()).toBe(true) + ); // Validate against snapshot expect(wrapper.element).toMatchSnapshot(); - const gifi_items = wrapper.findAll('.data-row'); + const gifi_items = wrapper.findAll(".data-row"); expect(gifi_items).toHaveLength(2); // Validate data displayed let data = gifi_items.map((rows) => { - return rows.findAll('.input-box').map(row => row.element.value) + return rows.findAll(".input-box").map((row) => row.element.value); }); expect(data).toEqual([ ["0000", "Dummy account"], @@ -48,9 +52,8 @@ describe("GIFI - register as a component", () => { }); it("should show dialog with editable data", async () => { - // Give user edition capability - sessionUser.$patch({roles: ["gifi_edit"]}); + sessionUser.$patch({ roles: ["gifi_edit"] }); expect(wrapper.exists()).toBeTruthy(); @@ -58,17 +61,19 @@ describe("GIFI - register as a component", () => { expect(wrapper.get(".dynatableLoading").text()).toBe("Loading..."); // Wait until loading done - await retry(() => expect(wrapper.find(".dynatableData").isVisible()).toBe(true)); + await retry(() => + expect(wrapper.find(".dynatableData").isVisible()).toBe(true) + ); // Validate against snapshot expect(wrapper.element).toMatchSnapshot(); - const gifi_items = wrapper.findAll('.data-row'); + const gifi_items = wrapper.findAll(".data-row"); expect(gifi_items).toHaveLength(2); // Validate data displayed let data = gifi_items.map((rows) => { - return rows.findAll('.input-box').map(row => row.element.value) + return rows.findAll(".input-box").map((row) => row.element.value); }); expect(data).toEqual([ ["0000", "Dummy account"], @@ -77,11 +82,11 @@ describe("GIFI - register as a component", () => { // Validate the buttons const buttons = gifi_items.map((rows) => { - return rows.findAll('button').map(row => row.element.name) + return rows.findAll("button").map((row) => row.element.name); }); expect(buttons).toEqual([ - [ 'modify', 'save', 'cancel' ], - [ 'modify', 'save', 'cancel' ] + ["modify", "save", "cancel"], + ["modify", "save", "cancel"] ]); }); }); diff --git a/UI/tests/specs/views/Languages.spec.js b/UI/tests/specs/views/Languages.spec.js index be184d26c0..4c93352f67 100644 --- a/UI/tests/specs/views/Languages.spec.js +++ b/UI/tests/specs/views/Languages.spec.js @@ -1,4 +1,8 @@ -/* global retry */ +/** + * global retry + * + * @format + */ import Languages from "@/views/Languages.vue"; import { useSessionUserStore } from "@/store/sessionUser"; @@ -8,31 +12,31 @@ let wrapper; let sessionUser; describe("Languages", () => { - beforeEach(() => { wrapper = factory(Languages); sessionUser = useSessionUserStore(); }); it("should show dialog", async () => { - expect(wrapper.exists()).toBeTruthy(); // Check loading expect(wrapper.get(".dynatableLoading").text()).toBe("Loading..."); // Wait until loading done - await retry(() => expect(wrapper.find(".dynatableData").isVisible()).toBe(true)); + await retry(() => + expect(wrapper.find(".dynatableData").isVisible()).toBe(true) + ); // Validate against snapshot expect(wrapper.element).toMatchSnapshot(); - const language_items = wrapper.findAll('.data-row'); + const language_items = wrapper.findAll(".data-row"); expect(language_items).toHaveLength(2); // Validate data displayed let data = language_items.map((rows) => { - return rows.findAll('.input-box').map(row => row.element.value) + return rows.findAll(".input-box").map((row) => row.element.value); }); expect(data).toEqual([ ["en", "English"], @@ -45,9 +49,8 @@ describe("Languages", () => { }); it("should show dialog with editable data", async () => { - // Give user edition capability - sessionUser.$patch({roles: ["language_edit"]}); + sessionUser.$patch({ roles: ["language_edit"] }); expect(wrapper.exists()).toBeTruthy(); @@ -55,46 +58,50 @@ describe("Languages", () => { expect(wrapper.get(".dynatableLoading").text()).toBe("Loading..."); // Wait until loading done - await retry(() => expect(wrapper.find(".dynatableData").isVisible()).toBe(true)); + await retry(() => + expect(wrapper.find(".dynatableData").isVisible()).toBe(true) + ); - const language_items = wrapper.findAll('.data-row'); + const language_items = wrapper.findAll(".data-row"); expect(language_items).toHaveLength(2); // Validate data displayed let data = language_items.map((rows) => { - return rows.findAll('.input-box').map(row => row.element.value) + return rows.findAll(".input-box").map((row) => row.element.value); }); expect(data).toEqual([ ["en", "English"], ["fr", "Français"] ]); const defaults = language_items.map((rows) => { - return rows.findAll('input[name="default"]').map(row => row.element.checked).at(0) + return rows + .findAll('input[name="default"]') + .map((row) => row.element.checked) + .at(0); }); - expect(defaults).toEqual([ - false, false - ]); + expect(defaults).toEqual([false, false]); // Validate the buttons const buttons = language_items.map((rows) => { - return rows.findAll('button').map(row => row.element.name) + return rows.findAll("button").map((row) => row.element.name); }); expect(buttons).toEqual([ - [ 'change-default', 'modify', 'save', 'cancel' ], - [ 'change-default', 'modify', 'save', 'cancel' ] + ["change-default", "modify", "save", "cancel"], + ["change-default", "modify", "save", "cancel"] ]); }); it("should edit a language and save data", async () => { - // Give user edition capability - sessionUser.$patch({roles: ["language_edit"]}); + sessionUser.$patch({ roles: ["language_edit"] }); // Wait until loading done - await retry(() => expect(wrapper.find(".dynatableData").isVisible()).toBe(true)); + await retry(() => + expect(wrapper.find(".dynatableData").isVisible()).toBe(true) + ); // Find 1st item - const language_item = wrapper.findAll('.data-row').at(0); + const language_item = wrapper.findAll(".data-row").at(0); const code = language_item.find('[name="code"]'); const description = language_item.find('[name="description"]'); const modify = language_item.find('[name="modify"]'); @@ -108,7 +115,7 @@ describe("Languages", () => { expect(save.element.disabled).toBe(true); expect(cancel.element.disabled).toBe(true); - await modify.trigger('click'); + await modify.trigger("click"); // Proper buttons enabled? await retry(() => expect(modify.element.disabled).toBe(true)); @@ -116,42 +123,44 @@ describe("Languages", () => { expect(cancel.element.disabled).toBe(false); description.setValue("English (american)"); - await save.trigger('click'); + await save.trigger("click"); await retry(() => expect(modify.element.disabled).toBe(false)); - const language_items = wrapper.findAll('.data-row'); + const language_items = wrapper.findAll(".data-row"); const data = language_items.map((rows) => { - return rows.findAll('.input-box').map(row => row.element.value) + return rows.findAll(".input-box").map((row) => row.element.value); }); expect(data).toEqual([ ["en", "English (american)"], ["fr", "Français"] ]); const defaults = language_items.map((rows) => { - return rows.findAll('input[name="default"]').map(row => row.element.checked).at(0) + return rows + .findAll('input[name="default"]') + .map((row) => row.element.checked) + .at(0); }); - expect(defaults).toEqual([ - false, false - ]); + expect(defaults).toEqual([false, false]); expect(modify.element.disabled).toBe(false); expect(save.element.disabled).toBe(true); expect(cancel.element.disabled).toBe(true); }); it("should allow adding a new language and save data", async () => { - // Give user edition capability - sessionUser.$patch({roles: ["language_create", "language_edit"]}); + sessionUser.$patch({ roles: ["language_create", "language_edit"] }); // Wait until loading done - await retry(() => expect(wrapper.find(".dynatableData").isVisible()).toBe(true)); + await retry(() => + expect(wrapper.find(".dynatableData").isVisible()).toBe(true) + ); - let language_items = wrapper.findAll('.data-row'); + let language_items = wrapper.findAll(".data-row"); expect(language_items).toHaveLength(3); // Validate data displayed let data = language_items.map((rows) => { - return rows.findAll('.input-box').map(row => row.element.value) + return rows.findAll(".input-box").map((row) => row.element.value); }); expect(data).toEqual([ ["en", "English"], @@ -159,14 +168,15 @@ describe("Languages", () => { ["", ""] ]); let defaults = language_items.map((rows) => { - return rows.findAll('input[name="default"]').map(row => row.element.checked).at(0) + return rows + .findAll('input[name="default"]') + .map((row) => row.element.checked) + .at(0); }); - expect(defaults).toEqual([ - false, false - ]); + expect(defaults).toEqual([false, false]); // Find 3rd item - let language_item = wrapper.findAll('.data-row').at(2); + let language_item = wrapper.findAll(".data-row").at(2); let code = language_item.find('[name="code"]'); let description = language_item.find('[name="description"]'); let add = language_item.find('[name="add"]'); @@ -185,16 +195,16 @@ describe("Languages", () => { // Add new entry code.setValue("my"); description.setValue("Mayan"); - await add.trigger('click'); + await add.trigger("click"); // Proper buttons enabled? - await retry(() => expect(wrapper.findAll('.data-row')).toHaveLength(4)); + await retry(() => expect(wrapper.findAll(".data-row")).toHaveLength(4)); - language_items = wrapper.findAll('.data-row'); + language_items = wrapper.findAll(".data-row"); // Validate data displayed data = language_items.map((rows) => { - return rows.findAll('.input-box').map(row => row.element.value) + return rows.findAll(".input-box").map((row) => row.element.value); }); expect(data).toEqual([ ["en", "English"], @@ -203,59 +213,64 @@ describe("Languages", () => { ["", ""] ]); defaults = language_items.map((rows) => { - return rows.findAll('input[name="default"]').map(row => row.element.checked).at(0) + return rows + .findAll('input[name="default"]') + .map((row) => row.element.checked) + .at(0); }); - expect(defaults).toEqual([ - false, false, false - ]); - + expect(defaults).toEqual([false, false, false]); }); it("should allow setting a default language", async () => { - // Give user edition capability - sessionUser.$patch({roles: ["language_edit"]}); + sessionUser.$patch({ roles: ["language_edit"] }); // Check loading expect(wrapper.get(".dynatableLoading").text()).toBe("Loading..."); // Wait until loading done - await retry(() => expect(wrapper.find(".dynatableData").isVisible()).toBe(true)); + await retry(() => + expect(wrapper.find(".dynatableData").isVisible()).toBe(true) + ); - let language_items = wrapper.findAll('.data-row'); + let language_items = wrapper.findAll(".data-row"); let defaults = language_items.map((rows) => { - return rows.findAll('input[name="default"]').map(row => row.element.checked).at(0) + return rows + .findAll('input[name="default"]') + .map((row) => row.element.checked) + .at(0); }); // No language selected - expect(defaults).toEqual([ - false, false - ]); + expect(defaults).toEqual([false, false]); // Validate the buttons const buttons = language_items.map((rows) => { return rows.find("button[name='change-default']"); }); // Set the default - await buttons[1].trigger('click'); + await buttons[1].trigger("click"); await retry(() => expect(buttons[1].isVisible()).toBe(false)); - language_items = wrapper.findAll('.data-row'); + language_items = wrapper.findAll(".data-row"); - expect(language_items.map((rows) => { - return rows.findAll('.input-box').map(row => row.element.value) - })).toEqual([ + expect( + language_items.map((rows) => { + return rows + .findAll(".input-box") + .map((row) => row.element.value); + }) + ).toEqual([ ["en", "English"], ["fr", "Français"] ]); defaults = language_items.map((rows) => { - return rows.findAll('input[name="default"]').map(row => row.element.checked).at(0) + return rows + .findAll('input[name="default"]') + .map((row) => row.element.checked) + .at(0); }); - expect(defaults).toEqual([ - false, true - ]); - + expect(defaults).toEqual([false, true]); }); - }); diff --git a/UI/tests/specs/views/Pricegroups.spec.js b/UI/tests/specs/views/Pricegroups.spec.js index 68db9a5f10..5a34012ee4 100644 --- a/UI/tests/specs/views/Pricegroups.spec.js +++ b/UI/tests/specs/views/Pricegroups.spec.js @@ -1,3 +1,4 @@ +/** @format */ /* global retry */ import Pricegroups from "@/views/Pricegroups.vue"; @@ -8,7 +9,6 @@ let wrapper; let sessionUser; describe("Pricegroups - register as a component", () => { - beforeEach(() => { wrapper = factory(Pricegroups); sessionUser = useSessionUserStore(); @@ -25,22 +25,21 @@ describe("Pricegroups - register as a component", () => { expect(wrapper.get(".dynatableLoading").text()).toBe("Loading..."); // Wait until loading done - await retry(() => expect(wrapper.find(".dynatableData").isVisible()).toBe(true)); + await retry(() => + expect(wrapper.find(".dynatableData").isVisible()).toBe(true) + ); // Validate against snapshot expect(wrapper.element).toMatchSnapshot(); - const pricegroup_items = wrapper.findAll('.data-row'); + const pricegroup_items = wrapper.findAll(".data-row"); expect(pricegroup_items).toHaveLength(2); // Validate data displayed let data = pricegroup_items.map((rows) => { - return rows.findAll('.input-box').map(row => row.element.value) + return rows.findAll(".input-box").map((row) => row.element.value); }); - expect(data).toEqual([ - [ "Price group 1" ], - [ "Price group 2" ] - ]); + expect(data).toEqual([["Price group 1"], ["Price group 2"]]); // TODO: Test links // expect that the links displayed match @@ -48,9 +47,8 @@ describe("Pricegroups - register as a component", () => { }); it("should show dialog with editable data", async () => { - // Give user edition capability - sessionUser.$patch({roles: ["pricegroup_edit"]}); + sessionUser.$patch({ roles: ["pricegroup_edit"] }); expect(wrapper.exists()).toBeTruthy(); @@ -58,30 +56,29 @@ describe("Pricegroups - register as a component", () => { expect(wrapper.get(".dynatableLoading").text()).toBe("Loading..."); // Wait until loading done - await retry(() => expect(wrapper.find(".dynatableData").isVisible()).toBe(true)); + await retry(() => + expect(wrapper.find(".dynatableData").isVisible()).toBe(true) + ); // Validate against snapshot expect(wrapper.element).toMatchSnapshot(); - const pricegroup_items = wrapper.findAll('.data-row'); + const pricegroup_items = wrapper.findAll(".data-row"); expect(pricegroup_items).toHaveLength(2); // Validate data displayed let data = pricegroup_items.map((rows) => { - return rows.findAll('.input-box').map(row => row.element.value) + return rows.findAll(".input-box").map((row) => row.element.value); }); - expect(data).toEqual([ - [ "Price group 1" ], - [ "Price group 2" ] - ]); + expect(data).toEqual([["Price group 1"], ["Price group 2"]]); // Validate the buttons const buttons = pricegroup_items.map((rows) => { - return rows.findAll('button').map(row => row.element.name) + return rows.findAll("button").map((row) => row.element.name); }); expect(buttons).toEqual([ - [ 'modify', 'save', 'cancel' ], - [ 'modify', 'save', 'cancel' ] + ["modify", "save", "cancel"], + ["modify", "save", "cancel"] ]); }); }); diff --git a/UI/tests/specs/views/SIC.spec.js b/UI/tests/specs/views/SIC.spec.js index f058b40f31..4c031296d7 100644 --- a/UI/tests/specs/views/SIC.spec.js +++ b/UI/tests/specs/views/SIC.spec.js @@ -1,3 +1,4 @@ +/** @format */ /* global retry */ import SIC from "@/views/SIC.vue"; @@ -8,7 +9,6 @@ let wrapper; let sessionUser; describe("SIC - register as a component", () => { - beforeEach(() => { wrapper = factory(SIC); sessionUser = useSessionUserStore(); @@ -18,28 +18,29 @@ describe("SIC - register as a component", () => { }); it("should show dialog", async () => { - expect(wrapper.exists()).toBeTruthy(); // Check loading expect(wrapper.get(".dynatableLoading").text()).toBe("Loading..."); // Wait until loading done - await retry(() => expect(wrapper.find(".dynatableData").isVisible()).toBe(true)); + await retry(() => + expect(wrapper.find(".dynatableData").isVisible()).toBe(true) + ); // Validate against snapshot expect(wrapper.element).toMatchSnapshot(); - const sic_items = wrapper.findAll('.data-row'); + const sic_items = wrapper.findAll(".data-row"); expect(sic_items).toHaveLength(2); // Validate data displayed let data = sic_items.map((rows) => { - return rows.findAll('.input-box').map(row => row.element.value) + return rows.findAll(".input-box").map((row) => row.element.value); }); expect(data).toEqual([ - [ "541330", "Engineering service" ], - [ "611430", "Professional and management development training" ] + ["541330", "Engineering service"], + ["611430", "Professional and management development training"] ]); // TODO: Test links @@ -48,9 +49,8 @@ describe("SIC - register as a component", () => { }); it("should show dialog with editable data", async () => { - // Give user edition capability - sessionUser.$patch({roles: ["sic_edit"]}); + sessionUser.$patch({ roles: ["sic_edit"] }); expect(wrapper.exists()).toBeTruthy(); @@ -58,30 +58,32 @@ describe("SIC - register as a component", () => { expect(wrapper.get(".dynatableLoading").text()).toBe("Loading..."); // Wait until loading done - await retry(() => expect(wrapper.find(".dynatableData").isVisible()).toBe(true)); + await retry(() => + expect(wrapper.find(".dynatableData").isVisible()).toBe(true) + ); // Validate against snapshot expect(wrapper.element).toMatchSnapshot(); - const sic_items = wrapper.findAll('.data-row'); + const sic_items = wrapper.findAll(".data-row"); expect(sic_items).toHaveLength(2); // Validate data displayed let data = sic_items.map((rows) => { - return rows.findAll('.input-box').map(row => row.element.value) + return rows.findAll(".input-box").map((row) => row.element.value); }); expect(data).toEqual([ - [ "541330", "Engineering service" ], - [ "611430", "Professional and management development training" ] + ["541330", "Engineering service"], + ["611430", "Professional and management development training"] ]); // Validate the buttons const buttons = sic_items.map((rows) => { - return rows.findAll('button').map(row => row.element.name) + return rows.findAll("button").map((row) => row.element.name); }); expect(buttons).toEqual([ - [ 'modify', 'save', 'cancel' ], - [ 'modify', 'save', 'cancel' ] + ["modify", "save", "cancel"], + ["modify", "save", "cancel"] ]); }); }); diff --git a/UI/tests/specs/views/Warehouses.spec.js b/UI/tests/specs/views/Warehouses.spec.js index a094dce0ca..83945f766b 100644 --- a/UI/tests/specs/views/Warehouses.spec.js +++ b/UI/tests/specs/views/Warehouses.spec.js @@ -1,3 +1,4 @@ +/** @format */ /* global retry */ import Warehouses from "@/views/Warehouses.vue"; @@ -17,30 +18,31 @@ describe("Warehouses - register as a component", () => { }); it("should show dialog", async () => { - expect(wrapper.exists()).toBeTruthy(); // Check loading expect(wrapper.get(".dynatableLoading").text()).toBe("Loading..."); // Wait until loading done - await retry(() => expect(wrapper.find(".dynatableData").isVisible()).toBe(true)); + await retry(() => + expect(wrapper.find(".dynatableData").isVisible()).toBe(true) + ); // Validate against snapshot expect(wrapper.element).toMatchSnapshot(); - const warehouse_items = wrapper.findAll('.data-row'); + const warehouse_items = wrapper.findAll(".data-row"); expect(warehouse_items).toHaveLength(3); // Validate data displayed let data = warehouse_items.map((rows) => { - return rows.findAll('.input-box').map(row => row.element.value) + return rows.findAll(".input-box").map((row) => row.element.value); }); expect(data).toEqual([ - [ "Modern warehouse" ], - [ "Huge warehouse" ], - [ "Moon warehouse" ], - ]); + ["Modern warehouse"], + ["Huge warehouse"], + ["Moon warehouse"] + ]); // TODO: Test links // expect that the links displayed match @@ -48,9 +50,8 @@ describe("Warehouses - register as a component", () => { }); it("should show dialog with editable data", async () => { - // Give user edition capability - sessionUser.$patch({roles: ["warehouse_edit"]}); + sessionUser.$patch({ roles: ["warehouse_edit"] }); expect(wrapper.exists()).toBeTruthy(); @@ -58,32 +59,34 @@ describe("Warehouses - register as a component", () => { expect(wrapper.get(".dynatableLoading").text()).toBe("Loading..."); // Wait until loading done - await retry(() => expect(wrapper.find(".dynatableData").isVisible()).toBe(true)); + await retry(() => + expect(wrapper.find(".dynatableData").isVisible()).toBe(true) + ); // Validate against snapshot expect(wrapper.element).toMatchSnapshot(); - const warehouse_items = wrapper.findAll('.data-row'); + const warehouse_items = wrapper.findAll(".data-row"); expect(warehouse_items).toHaveLength(3); // Validate data displayed let data = warehouse_items.map((rows) => { - return rows.findAll('.input-box').map(row => row.element.value) + return rows.findAll(".input-box").map((row) => row.element.value); }); expect(data).toEqual([ - [ "Modern warehouse" ], - [ "Huge warehouse" ], - [ "Moon warehouse" ], - ]); + ["Modern warehouse"], + ["Huge warehouse"], + ["Moon warehouse"] + ]); // Validate the buttons const buttons = warehouse_items.map((rows) => { - return rows.findAll('button').map(row => row.element.name) + return rows.findAll("button").map((row) => row.element.name); }); expect(buttons).toEqual([ - [ 'modify', 'save', 'cancel' ], - [ 'modify', 'save', 'cancel' ], - [ 'modify', 'save', 'cancel' ] + ["modify", "save", "cancel"], + ["modify", "save", "cancel"], + ["modify", "save", "cancel"] ]); }); }); diff --git a/UI/tests/specs/views/__snapshots__/GIFI.spec.js.snap b/UI/tests/specs/views/__snapshots__/GIFI.spec.js.snap index ea20cf3038..c391cc894f 100644 --- a/UI/tests/specs/views/__snapshots__/GIFI.spec.js.snap +++ b/UI/tests/specs/views/__snapshots__/GIFI.spec.js.snap @@ -5,7 +5,6 @@ exports[`GIFI - register as a component should show dialog 1`] = ` data-v-app="" > -

@@ -209,7 +208,6 @@ exports[`GIFI - register as a component should show dialog with editable data 1` data-v-app="" > -

diff --git a/UI/tests/specs/views/factory.js b/UI/tests/specs/views/factory.js index 65146cf581..0e48a813f3 100644 --- a/UI/tests/specs/views/factory.js +++ b/UI/tests/specs/views/factory.js @@ -1,3 +1,5 @@ +/** @format */ + import { mount } from "@vue/test-utils"; import { createPinia } from "pinia"; @@ -24,6 +26,6 @@ function factory(view) { } }); return wrapper; -}; +} -export { factory }; \ No newline at end of file +export { factory }; From b63d4206e2a339571f7f9c66c83dd86538d0349a Mon Sep 17 00:00:00 2001 From: Yves Lavoie Date: Mon, 15 Apr 2024 00:42:39 -0400 Subject: [PATCH 06/17] Lint Markdown compile files --- UI/js-src/webpack-compile-markdown.js | 58 +++++++++++++-------------- 1 file changed, 28 insertions(+), 30 deletions(-) diff --git a/UI/js-src/webpack-compile-markdown.js b/UI/js-src/webpack-compile-markdown.js index 1a0f00f072..7aaa4f9e2b 100644 --- a/UI/js-src/webpack-compile-markdown.js +++ b/UI/js-src/webpack-compile-markdown.js @@ -1,14 +1,14 @@ /** @format */ -const MarkdownInclude = require("markdown-include"), - browserslist = require("browserslist"), - lite = require("caniuse-lite"), - packageJson = require("../package.json"), - timestamp = require("unix-timestamp"); +const MarkdownInclude = require("markdown-include"); +const browserslist = require("browserslist"); +const lite = require("caniuse-lite"); +const packageJson = require("../package.json"); +const timestamp = require("unix-timestamp"); function _isNextVersion(v1, v2) { - let p1 = v1.match(/(\d+)(\.(\d+))?/), - p2 = v2.match(/(\d+)(\.(\d+))?/); + let p1 = v1.match(/(\d+)(\.(\d+))?/); + let p2 = v2.match(/(\d+)(\.(\d+))?/); return ( v2 && ((+p1[1] === +p2[1] + 1 && !p1[3] && !p2[3]) || @@ -26,7 +26,6 @@ MarkdownInclude.registerPlugin({ .sort() .forEach(function (b) { let [browser, version] = b.split(/\s+/); - // eslint-disable-next-line one-var let category = browser.match( /^(\w+_\w+|android|baidu|bb|kaios|samsung)$/ ) @@ -45,7 +44,6 @@ MarkdownInclude.registerPlugin({ lite.agents[browser].browser; earliest[category][browser].versions = []; } - // eslint-disable-next-line one-var let time = lite.agents[browser].release_date[version]; if (time !== null) { @@ -57,13 +55,13 @@ MarkdownInclude.registerPlugin({ earliest[category][browser].version = version; if (time) { - let ts = timestamp.toDate(time), - month = "00" + (ts.getMonth() + 1), - year = - 1900 + - ts.getYear() + - "-" + - month.substr(month.length - 2); + let ts = timestamp.toDate(time); + let month = "00" + (ts.getMonth() + 1); + let year = + 1900 + + ts.getYear() + + "-" + + month.substr(month.length - 2); earliest[category][browser].year = year; earliest[category][browser].time = time; } else { @@ -74,7 +72,7 @@ MarkdownInclude.registerPlugin({ } }); let markdown = ""; - /* eslint guard-for-in:0 */ + // eslint guard-for-in:0 for (const c of ["Desktop", "Mobile"]) { markdown += "\n### " + c + "\n\n"; markdown += @@ -93,20 +91,20 @@ MarkdownInclude.registerPlugin({ ":|:" + "---".padEnd(43, "-") + " |\n"; - // eslint-disable-next-line one-var + + // eslint-disable-next-line guard-for-in for (var browser in earliest[c]) { - // eslint-disable-next-line one-var var entry = earliest[c][browser]; - let versions = [], - v1 = "", - v2 = "", - // Pack versions - vs = entry.versions.sort((a, b) => - a.localeCompare(b, undefined, { numeric: true }) - ); - // eslint-disable-next-line one-var + let versions = []; + let v1 = ""; + let v2 = ""; + // Pack versions + let vs = entry.versions.sort((a, b) => + a.localeCompare(b, undefined, { numeric: true }) + ); + var v; - /* eslint no-cond-assign:0 */ + // eslint no-cond-assign:0 while ((v = vs.shift()) || v1) { if (v && v.includes("-")) { let [v01, v02] = v.split("-"); @@ -181,8 +179,8 @@ MarkdownInclude.registerPlugin({ }); // do something with compiled files -var tmp = require("tmp"), - fs = require("fs"); +var tmp = require("tmp"); +var fs = require("fs"); tmp.file( { From cd27b517552baf3b7d8afc6f30d7f50081cb918d Mon Sep 17 00:00:00 2001 From: Yves Lavoie Date: Mon, 15 Apr 2024 21:17:02 -0400 Subject: [PATCH 07/17] Lint Javascript files --- UI/js-src/lsmb/Form.js | 6 ++++-- UI/js-src/lsmb/JumpScreenButton.js | 5 +---- UI/js-src/lsmb/PrintButton.js | 5 ++--- UI/js-src/lsmb/SetupLoginButton.js | 3 ++- UI/js-src/lsmb/ToggleIncludeButton.js | 12 ++++++------ UI/js-src/webpack-compile-markdown.js | 7 +++---- 6 files changed, 18 insertions(+), 20 deletions(-) diff --git a/UI/js-src/lsmb/Form.js b/UI/js-src/lsmb/Form.js index 58619cabd7..4a871ad763 100644 --- a/UI/js-src/lsmb/Form.js +++ b/UI/js-src/lsmb/Form.js @@ -13,7 +13,8 @@ define([ clickedAction: null, onSubmit: function (evt) { event.stop(evt); - this.clickedAction = evt.submitter; /* ought to be the same as this.domNode.__action */ + this.clickedAction = + evt.submitter; /* ought to be the same as this.domNode.__action */ this.submit(); }, submit: function () { @@ -25,7 +26,8 @@ define([ const options = { handleAs: "text" }; const method = typeof this.method === "undefined" ? "GET" : this.method; - let url = this.action; /* relative; this.domNode.action is absolute */ + let url = + this.action; /* relative; this.domNode.action is absolute */ options.doing = widget["data-lsmb-doing"]; options.done = widget["data-lsmb-done"]; diff --git a/UI/js-src/lsmb/JumpScreenButton.js b/UI/js-src/lsmb/JumpScreenButton.js index 0b0936ed4f..cc1c14b9f3 100644 --- a/UI/js-src/lsmb/JumpScreenButton.js +++ b/UI/js-src/lsmb/JumpScreenButton.js @@ -1,9 +1,6 @@ /** @format */ -define(["dojo/_base/declare", "dijit/form/Button"], function ( - declare, - button -) { +define(["dojo/_base/declare", "dijit/form/Button"], function (declare, button) { return declare("lsmb/payments/JumpScreenButton", [button], { url: null, onClick: function () { diff --git a/UI/js-src/lsmb/PrintButton.js b/UI/js-src/lsmb/PrintButton.js index 2ee7db69bc..ef38154156 100644 --- a/UI/js-src/lsmb/PrintButton.js +++ b/UI/js-src/lsmb/PrintButton.js @@ -86,10 +86,9 @@ define([ } } else { window.__lsmbReportError(r); - }; + } }); - } - else { + } else { this.inherited(arguments); } } diff --git a/UI/js-src/lsmb/SetupLoginButton.js b/UI/js-src/lsmb/SetupLoginButton.js index 6fc7e3683a..d7ad1d0fec 100644 --- a/UI/js-src/lsmb/SetupLoginButton.js +++ b/UI/js-src/lsmb/SetupLoginButton.js @@ -30,7 +30,8 @@ define([ "&database=" + company + "&csrf_token=" + - token); + token + ); }, function (err) { var status = err.response.status; diff --git a/UI/js-src/lsmb/ToggleIncludeButton.js b/UI/js-src/lsmb/ToggleIncludeButton.js index f237c18810..7d7dff7f26 100644 --- a/UI/js-src/lsmb/ToggleIncludeButton.js +++ b/UI/js-src/lsmb/ToggleIncludeButton.js @@ -5,12 +5,12 @@ define(["dojo/_base/declare", "dijit/form/Button"], function (declare, button) { return declare("lsmb/payments/ToggleIncludeButton", [button], { query: null, onClick: function () { - dojo.query(this.query, this.valueNode.form).forEach(function ( - node - ) { - var n = dijit.getEnclosingWidget(node); - n.set("checked", !n.get("checked")); - }); + dojo.query(this.query, this.valueNode.form).forEach( + function (node) { + var n = dijit.getEnclosingWidget(node); + n.set("checked", !n.get("checked")); + } + ); } }); }); diff --git a/UI/js-src/webpack-compile-markdown.js b/UI/js-src/webpack-compile-markdown.js index 7aaa4f9e2b..cf991cfc8b 100644 --- a/UI/js-src/webpack-compile-markdown.js +++ b/UI/js-src/webpack-compile-markdown.js @@ -72,7 +72,7 @@ MarkdownInclude.registerPlugin({ } }); let markdown = ""; - // eslint guard-for-in:0 + /* eslint guard-for-in:0 */ for (const c of ["Desktop", "Mobile"]) { markdown += "\n### " + c + "\n\n"; markdown += @@ -92,7 +92,6 @@ MarkdownInclude.registerPlugin({ "---".padEnd(43, "-") + " |\n"; - // eslint-disable-next-line guard-for-in for (var browser in earliest[c]) { var entry = earliest[c][browser]; let versions = []; @@ -104,7 +103,7 @@ MarkdownInclude.registerPlugin({ ); var v; - // eslint no-cond-assign:0 + /* eslint no-cond-assign:0 */ while ((v = vs.shift()) || v1) { if (v && v.includes("-")) { let [v01, v02] = v.split("-"); @@ -138,7 +137,7 @@ MarkdownInclude.registerPlugin({ v1 = ""; v2 = ""; } - // eslint-disable-next-line one-var + /* eslint-disable-next-line one-var */ var l = "", line = "| " + From f07f07567d53d92ff80f3ea386ba9136c1af711c Mon Sep 17 00:00:00 2001 From: Yves Lavoie Date: Tue, 16 Apr 2024 02:34:08 -0400 Subject: [PATCH 08/17] Lint VUE files --- UI/eslint.config.mjs | 71 ++- UI/js-src/lsmb/users/ChangePassword.js | 6 +- UI/js-src/lsmb/webpack.loaderConfig.js | 2 +- UI/package.json | 33 +- UI/src/components/ConfigTable.vue | 22 +- UI/src/components/ConfigTableRow.vue | 127 ++-- UI/src/components/ImportCSV-Base.vue | 131 +++-- UI/src/components/ServerUI.js | 15 +- UI/src/components/Toast.vue | 45 +- UI/src/components/Toaster.vue | 35 +- UI/src/elements/lsmb-base-input.js | 1 - UI/src/elements/lsmb-button.js | 1 - UI/src/elements/lsmb-date.js | 1 - UI/src/elements/lsmb-dijit.js | 3 +- UI/src/elements/lsmb-password.js | 1 - UI/src/elements/lsmb-text.js | 1 - UI/src/i18n.js | 24 +- UI/src/machine-helpers.js | 31 +- UI/src/main-vue.js | 10 +- UI/src/robot-vue.js | 10 +- UI/src/views/BusinessTypes.vue | 11 +- UI/src/views/Countries.vue | 11 +- UI/src/views/GIFI.vue | 14 +- UI/src/views/Home.vue | 55 +- UI/src/views/ImportCSV-AA-Batch.vue | 107 ++-- UI/src/views/ImportCSV-CoA.vue | 81 ++- UI/src/views/ImportCSV-GIFI.vue | 40 +- UI/src/views/ImportCSV-GL-Batch.vue | 94 +-- UI/src/views/ImportCSV-GL.vue | 118 ++-- UI/src/views/ImportCSV-GSO.vue | 169 +++--- UI/src/views/ImportCSV-Inventory.vue | 67 ++- UI/src/views/ImportCSV-SIC.vue | 42 +- UI/src/views/ImportCSV-Timecard.vue | 96 +-- UI/src/views/Languages.vue | 7 +- UI/src/views/LoginPage.machines.js | 91 +-- UI/src/views/LoginPage.vue | 150 ++--- UI/src/views/Pricegroups.vue | 8 +- UI/src/views/SIC.vue | 9 +- UI/src/views/Warehouses.vue | 11 +- UI/tests/common/i18n.js | 1 + UI/tests/common/mocks/lsmb_elements.js | 6 +- UI/tests/specs/openapi/database.js | 4 +- UI/tests/specs/views/BusinessTypes.spec.js | 7 +- UI/tests/specs/views/Countries.spec.js | 7 +- UI/tests/specs/views/GIFI.spec.js | 7 +- UI/tests/specs/views/Languages.spec.js | 7 +- UI/webpack.config.js | 650 ++++++++++----------- UI/yarn.lock | 473 +++++---------- 48 files changed, 1458 insertions(+), 1455 deletions(-) diff --git a/UI/eslint.config.mjs b/UI/eslint.config.mjs index 5bf6e86bd8..eb8fb46663 100644 --- a/UI/eslint.config.mjs +++ b/UI/eslint.config.mjs @@ -2,26 +2,26 @@ import globals from "globals"; import babelParser from "@babel/eslint-parser"; -// import compatPlugin from "eslint-plugin-compat"; +import compatPlugin from "eslint-plugin-compat"; import eslintConfigESLint from "eslint-config-eslint"; import eslintPluginPrettierRecommended from "eslint-plugin-prettier/recommended"; -// import importPlugin from "eslint-plugin-import"; +import eslintImportX from "eslint-plugin-import-x"; import js from "@eslint/js"; import jest from "eslint-plugin-jest"; import packageJson from "eslint-plugin-package-json/configs/recommended"; import pluginVue from "eslint-plugin-vue"; export default [ - js.configs.recommended, - eslintPluginPrettierRecommended, - ...pluginVue.configs["flat/recommended"], // Why global? - // compatPlugin.configs["flat/recommended"], - // importPlugin.configs["flat/recommended"], - // Global config { - ignores: ["{js,node_modules,__mocks__}/**/*.js"] + ignores: ["{js,node_modules,__mocks__}/**/*"] }, + + js.configs.recommended, + eslintPluginPrettierRecommended, + ...pluginVue.configs["flat/recommended"], + compatPlugin.configs["flat/recommended"], + // Config files { ...eslintConfigESLint, @@ -43,6 +43,11 @@ export default [ parser: babelParser, parserOptions: { requireConfigFile: false, + babelOptions: { + babelrc: false, + configFile: false, + presets: ["@babel/preset-env"] + }, templateSettings: { evaluate: ["[%", "%]"], interpolate: ["[%", "%]"], @@ -51,13 +56,19 @@ export default [ } }, plugins: { - // "compat", // Not yet compatible with eslint 9 - // "import", // Not yet compatible with eslint 9 + "import-x": eslintImportX + }, + settings: { + "import-x/resolver": "webpack", + "import-x/parsers": { + "@babel/eslint-parser": [".js", ".jsx"], + "@typescript-eslint/parser": [".ts", ".tsx"] + } }, rules: { ...js.configs.recommended.rules, camelcase: "off", - // "compat/compat": "warn", // Not yet compatible with eslint 9 + "compat/compat": "warn", "consistent-return": "error", curly: ["error", "all"], "dot-notation": "error", @@ -65,11 +76,22 @@ export default [ "func-names": 0, "global-require": "error", "guard-for-in": "error", + "import-x/export": "error", + "import-x/no-unresolved": "error", + "import-x/named": "error", + "import-x/namespace": "error", + "import-x/default": "error", + "import-x/no-absolute-path": "error", + "import-x/no-dynamic-require": "error", + "import-x/no-named-as-default": "warn", + "import-x/no-named-as-default-member": "warn", + "import-x/no-duplicates": "warn", "new-cap": 0, "no-alert": "error", - "no-console": "error", + "no-console": "off", "no-continue": 0, "no-else-return": "error", + "no-eval": "error", "no-lonely-if": "error", "no-multi-assign": "error", "no-multi-spaces": "off", @@ -103,7 +125,7 @@ export default [ } } ], - "vars-on-top": 0, + "vars-on-top": "off", yoda: "error", "no-restricted-syntax": ["error", "SequenceExpression"] } @@ -209,10 +231,29 @@ export default [ } ], "vue/first-attribute-linebreak": "off", + "vue/html-closing-bracket-newline": "off", "vue/html-indent": ["error", 4], + "vue/max-attributes-per-line": [ + "error", + { + singleline: 3, + multiline: 3 + } + ], "vue/multi-word-component-names": "off", + "vue/multiline-html-element-content-newline": "off", "vue/no-setup-props-reactivity-loss": "off", - "vue/require-prop-types": "off" + "vue/require-prop-types": "off", + "vue/singleline-html-element-content-newline": [ + "error", + { + ignoreWhenNoAttributes: true, + ignoreWhenEmpty: true, + ignores: ["pre", "textarea", "template"], + externalIgnores: [] + } + ], + "vue/v-on-event-hyphenation": "off" } } ]; diff --git a/UI/js-src/lsmb/users/ChangePassword.js b/UI/js-src/lsmb/users/ChangePassword.js index f1741761da..d70dc3f006 100644 --- a/UI/js-src/lsmb/users/ChangePassword.js +++ b/UI/js-src/lsmb/users/ChangePassword.js @@ -105,6 +105,7 @@ define([ nonWords: /\W/.test(pass) }; var variationCount = 0; + // eslint-disable-next-line guard-for-in for (var check in variations) { variationCount += variations[check] === true ? 1 : 0; } @@ -135,7 +136,10 @@ define([ return; } if (newPassword !== confirmedPassword) { - this.setFeedback(false, this.text("Confirmation did not match")); + this.setFeedback( + false, + this.text("Confirmation did not match") + ); return; } r("user.pl", { diff --git a/UI/js-src/lsmb/webpack.loaderConfig.js b/UI/js-src/lsmb/webpack.loaderConfig.js index a6e7f5a8e5..95cbaaa814 100644 --- a/UI/js-src/lsmb/webpack.loaderConfig.js +++ b/UI/js-src/lsmb/webpack.loaderConfig.js @@ -17,7 +17,7 @@ */ const path = require("path"); -function getConfig( /* env */ ) { +function getConfig(/* env */) { // env is set by the 'buildEnvironment' and/or 'environment' plugin options // (see webpack.config.js), // or by the code at the end of this file if using without webpack diff --git a/UI/package.json b/UI/package.json index 628aca168c..9396c95545 100644 --- a/UI/package.json +++ b/UI/package.json @@ -52,15 +52,15 @@ "tapable": "2.2.1", "vue": "3.4.27", "vue-i18n": "9.13.1", - "vue-router": "^4.3.2" + "vue-router": "4.3.2" }, "devDependencies": { "@babel/core": "7.24.6", "@babel/eslint-parser": "7.24.6", "@babel/plugin-proposal-object-rest-spread": "7.20.7", "@babel/preset-env": "7.24.6", - "@eslint/js": "9.0.0", - "@eslint/eslintrc":"3.0.2", + "@eslint/js": "9.3.0", + "@eslint/eslintrc":"3.1.0", "@pinia/testing": "0.1.3", "@redocly/cli": "1.14.0", "@vue/test-utils": "2.4.6", @@ -81,24 +81,21 @@ "dojo-util": "1.17.3", "dojo-webpack-plugin": "3.0.6", "ejs-loader": "0.5.0", - "eslint": "9.0.0", + "eslint": "9.3.0", "eslint-config-eslint": "10.0.0", "eslint-config-prettier": "9.1.0", "eslint-import-resolver-webpack": "0.13.8", - "eslint-plugin-compat": "4.2.0", - "eslint-plugin-import": "2.29.1", - "eslint-plugin-jest": "28.2.0", - "eslint-plugin-json": "3.1.0", + "eslint-plugin-compat": "5.0.0-2", + "eslint-plugin-import-x": "0.5.1", + "eslint-plugin-jest": "28.5.0", + "eslint-plugin-json": "4.0.0", "eslint-plugin-n": "17.7.0", "eslint-plugin-package-json": "0.14.0", "eslint-plugin-prettier": "5.1.3", - "eslint-plugin-promise": "6.2.0", - "eslint-plugin-snakecasejs": "2.2.0", - "eslint-plugin-sort-dojo-dependency": "0.0.1", "eslint-plugin-vue": "9.26.0", "eslint-webpack-plugin": "4.2.0", "flush-promises": "1.0.2", - "globals": "15.0.0", + "globals": "15.3.0", "html-webpack-plugin": "5.6.0", "http-status-codes": "2.3.0", "i18next-conv": "15.0.0", @@ -114,7 +111,7 @@ "mini-css-extract-plugin": "2.9.0", "msw": "2.3.0", "npm-run-all2": "6.2.0", - "openapi-merge-cli": "^1.3.1", + "openapi-merge-cli": "1.3.1", "path-browserify": "1.0.1", "postcss": "8.4.38", "prettier": "3.2.5", @@ -149,12 +146,12 @@ "build": "webpack --mode=production --stats errors-warnings", "build:dev": "webpack --progress --mode=development --stats errors-warnings", "lint": "yarn run lint:css && yarn run lint:js && yarn run lint:markdown && yarn run lint:vue", - "lint:css": "stylelint css/*.css", - "lint:js": "eslint ./{src,js-src}/**/*.js", - "lint:js:fix": "eslint --fix ./{src,js-src}/**/*.js", + "lint:css": "stylelint css/**/*.css", + "lint:js": "eslint {src,js-src}/**/*.js", + "lint:js:fix": "eslint --fix {src,js-src}/**/*.js", "lint:markdown": "markdownlint --config ../.markdownlint.json --ignore ./node_modules --ignore ./js .", - "lint:vue": "eslint ./src/**/*.vue", - "lint:vue:fix": "eslint --fix ./src/**/*.vue", + "lint:vue": "eslint src/**/*.vue", + "lint:vue:fix": "eslint --fix src/**/*.vue", "profile": "webpack --progress=profile --json > logs/stats.json", "readme": "webpack --mode production --stats errors-warnings", "serve": "webpack serve --mode development", diff --git a/UI/src/components/ConfigTable.vue b/UI/src/components/ConfigTable.vue index 6d5973ffa7..bb06cf9be1 100644 --- a/UI/src/components/ConfigTable.vue +++ b/UI/src/components/ConfigTable.vue @@ -1,5 +1,6 @@ -