From abf80820528ce888b45606ca09ec42f394b95fdd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 3 Jan 2025 10:19:42 +0000 Subject: [PATCH 1/4] chore(deps): update appium-related packages (#1879) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package-lock.json | 109 ++++++++++++++++++++++++++++++++++++---------- package.json | 6 +-- 2 files changed, 88 insertions(+), 27 deletions(-) diff --git a/package-lock.json b/package-lock.json index 10224141b..f7c1033c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -39,10 +39,10 @@ "electron": "node_modules/.bin/electron" }, "devDependencies": { - "@appium/docutils": "1.0.26", + "@appium/docutils": "1.0.27", "@appium/eslint-config-appium-ts": "0.3.3", - "@appium/fake-driver": "5.5.7", - "@appium/support": "6.0.0", + "@appium/fake-driver": "5.6.0", + "@appium/support": "6.0.1", "@eslint/compat": "1.1.1", "@eslint/eslintrc": "3.2.0", "@eslint/js": "9.17.0", @@ -193,18 +193,18 @@ } }, "node_modules/@appium/docutils": { - "version": "1.0.26", - "resolved": "https://registry.npmjs.org/@appium/docutils/-/docutils-1.0.26.tgz", - "integrity": "sha512-pLuazPsWZu/OJuCdOBAylcShCI39IGIDXUvuJXpzKuPETmcfwPusV2ipf2te16fHvTz2xnXajNM6QwnO9SwUUg==", + "version": "1.0.27", + "resolved": "https://registry.npmjs.org/@appium/docutils/-/docutils-1.0.27.tgz", + "integrity": "sha512-iT+UOzOJpwTaPJgOIVs3Esl4uJG1iRc2KVkpX95QlbIjoGjDo+Z4nLG59m1NLPctJ0X5kUGlkZ/xWd38SN/7/A==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@appium/support": "^6.0.0", + "@appium/support": "^6.0.1", "@appium/tsconfig": "^0.3.3", "@sliphua/lilconfig-ts-loader": "3.2.2", "@types/which": "3.0.4", "chalk": "4.1.2", - "consola": "3.2.3", + "consola": "3.3.3", "diff": "7.0.0", "json5": "2.2.3", "lilconfig": "3.1.3", @@ -214,9 +214,9 @@ "semver": "7.6.3", "source-map-support": "0.5.21", "teen_process": "2.2.2", - "type-fest": "4.30.0", + "type-fest": "4.31.0", "typescript": "5.7.2", - "yaml": "2.6.1", + "yaml": "2.7.0", "yargs": "17.7.2", "yargs-parser": "21.1.1" }, @@ -228,6 +228,32 @@ "npm": ">=8" } }, + "node_modules/@appium/docutils/node_modules/type-fest": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.31.0.tgz", + "integrity": "sha512-yCxltHW07Nkhv/1F6wWBr8kz+5BGMfP+RbRSYFnegVb0qV/UMT0G0ElBloPVerqn4M2ZV80Ir1FtCcYv1cT6vQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@appium/docutils/node_modules/yaml": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", + "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/@appium/eslint-config-appium": { "version": "8.0.5", "resolved": "https://registry.npmjs.org/@appium/eslint-config-appium/-/eslint-config-appium-8.0.5.tgz", @@ -270,9 +296,9 @@ } }, "node_modules/@appium/fake-driver": { - "version": "5.5.7", - "resolved": "https://registry.npmjs.org/@appium/fake-driver/-/fake-driver-5.5.7.tgz", - "integrity": "sha512-m1hElTQJyzV2vpWFjGTLm2mBFnXGtQUT27sBP/jza0pBNUtIpsHtETkEkIdG7Cya7eNMq8ue0JgN+IPpy6kCZA==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/@appium/fake-driver/-/fake-driver-5.6.0.tgz", + "integrity": "sha512-ddXnMcvFBtUsWn9tAEK7sKBMfjLdeZ9o35ZzBqhzZFZQV2Os0DRoHIFeXHkj3sYIfLBZcJeRtFICGmL7R8GhZQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -310,9 +336,9 @@ } }, "node_modules/@appium/schema": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/@appium/schema/-/schema-0.7.0.tgz", - "integrity": "sha512-UhozvcSj8aSeZ0oo8JtT8EoowLpjn7V7xahsIN5bRGeir6+XzqRpjxytKASvnKPoPK0Df7oqCdzJOI0iLa62ZA==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/@appium/schema/-/schema-0.7.1.tgz", + "integrity": "sha512-HCK0FqYOe96gYw7xb3mlZf9uIqgUwbrMJUedJnLfynvlrRsUe2/uXhYuBPENMn89mkeoZMThgAEEVarDH0sCaQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -326,15 +352,15 @@ } }, "node_modules/@appium/support": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@appium/support/-/support-6.0.0.tgz", - "integrity": "sha512-zlcTdOFhMSvCaR5j9dcnX3kXh0XAolnJd/MmvS7S7xFAdezX90yMsxNegTgvPnCEu+k2Gjv4Ddk6JC+KK1TZhQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@appium/support/-/support-6.0.1.tgz", + "integrity": "sha512-siAWkbkWbHdvMabPDULMSEmOpvsh9reEqIOKqmxow3dO1C0zziYS7tsqzLNxB5AZRvZoQT209G4lGdN5kqSdww==", "dev": true, "license": "Apache-2.0", "dependencies": { "@appium/logger": "^1.6.1", "@appium/tsconfig": "^0.3.3", - "@appium/types": "^0.22.3", + "@appium/types": "^0.23.0", "@colors/colors": "1.6.0", "@types/archiver": "6.0.3", "@types/base64-stream": "1.0.5", @@ -380,7 +406,7 @@ "source-map-support": "0.5.21", "supports-color": "8.1.1", "teen_process": "2.2.2", - "type-fest": "4.30.0", + "type-fest": "4.31.0", "uuid": "11.0.3", "which": "4.0.0", "yauzl": "3.2.0" @@ -393,6 +419,38 @@ "sharp": "0.33.5" } }, + "node_modules/@appium/support/node_modules/@appium/types": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@appium/types/-/types-0.23.0.tgz", + "integrity": "sha512-0xfCpJuPmhkvamjgO/U3DY7FV/Usu6WYZKUs9BiC9GjzFYffRJO1Gu2z/wscCZ5gTGuELVqNCb/f/c+nofvjrQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@appium/logger": "^1.6.1", + "@appium/schema": "^0.7.1", + "@appium/tsconfig": "^0.3.3", + "@types/express": "5.0.0", + "@types/ws": "8.5.13", + "type-fest": "4.31.0" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0", + "npm": ">=8" + } + }, + "node_modules/@appium/support/node_modules/type-fest": { + "version": "4.31.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.31.0.tgz", + "integrity": "sha512-yCxltHW07Nkhv/1F6wWBr8kz+5BGMfP+RbRSYFnegVb0qV/UMT0G0ElBloPVerqn4M2ZV80Ir1FtCcYv1cT6vQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@appium/tsconfig": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@appium/tsconfig/-/tsconfig-0.3.3.tgz", @@ -413,6 +471,7 @@ "integrity": "sha512-mPAfaPl1poVjDVPLkE18zESVHkAPKKijBnGNtXCmkvcMFXK8k8tNjAAVPm58Cmk5JlCKljArAR2N8jMFl6r/Yw==", "dev": true, "license": "Apache-2.0", + "peer": true, "dependencies": { "@appium/logger": "^1.6.1", "@appium/schema": "^0.7.0", @@ -5901,9 +5960,9 @@ } }, "node_modules/consola": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", - "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.3.3.tgz", + "integrity": "sha512-Qil5KwghMzlqd51UXM0b6fyaGHtOC22scxrwrz4A2882LyUMwQjnvaedN1HAeXzphspQ6CpHkzMAWxBTUruDLg==", "dev": true, "license": "MIT", "engines": { @@ -15664,6 +15723,7 @@ "integrity": "sha512-G6zXWS1dLj6eagy6sVhOMQiLtJdxQBHIA9Z6HFUNLOlr6MFOgzV8wvmidtPONfPtEUv0uZsy77XJNzTAfwPDaA==", "dev": true, "license": "(MIT OR CC0-1.0)", + "peer": true, "engines": { "node": ">=16" }, @@ -16628,6 +16688,7 @@ "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", "dev": true, "license": "ISC", + "peer": true, "bin": { "yaml": "bin.mjs" }, diff --git a/package.json b/package.json index d6de15e06..2603bb4aa 100644 --- a/package.json +++ b/package.json @@ -97,10 +97,10 @@ "vite": "V6: need support in electron-vite" }, "devDependencies": { - "@appium/docutils": "1.0.26", + "@appium/docutils": "1.0.27", "@appium/eslint-config-appium-ts": "0.3.3", - "@appium/fake-driver": "5.5.7", - "@appium/support": "6.0.0", + "@appium/fake-driver": "5.6.0", + "@appium/support": "6.0.1", "@eslint/compat": "1.1.1", "@eslint/eslintrc": "3.2.0", "@eslint/js": "9.17.0", From d97228f4083730d761fcdc956f1f69f3ef9ebf1a Mon Sep 17 00:00:00 2001 From: Kazuaki Matsuo Date: Fri, 3 Jan 2025 11:33:06 -0500 Subject: [PATCH 2/4] feat: enable appium-inspector as an appium plugin (#1878) * Update package.yml * use secrets * apply Prettier * ci: add github token and changes to always * prototype for plugin * update lock * add js * add js * simplify * simplify more * create package.json in plugins * adjust * add comment * remove reps as no usage * revert lock on the top * revert lock on the top * add files * add comment how to run with source=local * add -plugin in the name * make inspector as appium plugin (#1867) * make inspector as appium plugin * added review comments * apply format and lint * update proto-plugin branch (#1871) * apply format and lint * update lock * chore: tweak the path names * docs: add a brief readme * apply prettier * add const * chore: adjust routes and fix root behavior (#1873) * tweak deps version and pluginName * do not return inspector contents for non-/inspector route * remove unused method * apply formatter * rename * updated readme for plugin (#1874) * simplified the build:plugin and add clean:plugin * fix readme format * address review comments - partial Co-authored-by: SrinivasanTarget * remove unnecessary deps and add lint disabler * add dev and license * add version sync script * apply lint and prettier * add release in README and TODO for followup PR * tweak the script * use resolve and fs/promises * simplified a bit * use mjs instead of js * add mjs file * modify readme * sync more basic info * add new line * add node: * address npm run build:plugin as well * remvoe npm installation for now * fix reviews in code * adjust locale with vite base * use trimEnd in lodash * fix wrong key * fix return --------- Co-authored-by: Sai Krishna --- app/web/polyfills.js | 7 +++++- package.json | 3 +++ plugins/README.md | 54 +++++++++++++++++++++++++++++++++++++++++ plugins/index.mjs | 44 +++++++++++++++++++++++++++++++++ plugins/package.json | 47 +++++++++++++++++++++++++++++++++++ scripts/sync-plugin.mjs | 48 ++++++++++++++++++++++++++++++++++++ 6 files changed, 202 insertions(+), 1 deletion(-) create mode 100644 plugins/README.md create mode 100644 plugins/index.mjs create mode 100644 plugins/package.json create mode 100644 scripts/sync-plugin.mjs diff --git a/app/web/polyfills.js b/app/web/polyfills.js index f32ff3a1b..46a323f6e 100644 --- a/app/web/polyfills.js +++ b/app/web/polyfills.js @@ -1,11 +1,16 @@ import i18NextBackend from 'i18next-chained-backend'; import HttpApi from 'i18next-http-backend'; import LocalStorageBackend from 'i18next-localstorage-backend'; +import _ from 'lodash'; + +// Adjust locales path depending on Vite base (web vs plugin) +const viteBase = import.meta.env.BASE_URL; +const vitePath = `${_.trimEnd(viteBase, '/')}/`; const localesPath = process.env.NODE_ENV === 'development' ? '/locales' // 'public' folder contents are served at '/' - : '../locales'; // from 'dist-browser/assets/' + : `..${vitePath}locales`; // from 'dist-browser/assets/' const i18NextBackendOptions = { backends: [LocalStorageBackend, HttpApi], diff --git a/package.json b/package.json index 2603bb4aa..785436625 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "build": "npm run build:browser && npm run build:electron", "build:browser": "vite build", "build:browser:url": "vite build --base $PUBLIC_URL", + "build:plugin": "vite build --base /inspector --outDir ../../plugins/dist-browser", "build:electron": "electron-vite build", "preview:browser": "npm run build:browser && vite preview", "preview:electron": "electron-vite preview", @@ -41,9 +42,11 @@ "clean": "npm run clean:electron && npm run clean:browser && npm run clean:npm", "clean:electron": "rimraf dist/ && rimraf node_modules/.vite/ && rimraf node_modules/.vite-electron-renderer/", "clean:browser": "rimraf dist-browser/ && rimraf node_modules/.vite/", + "clean:plugin": "rimraf plugins/dist-browser", "clean:npm": "rimraf package-lock.json && rimraf node_modules && npm install", "build:docs": "appium-docs build", "dev:docs": "appium-docs build --serve", + "plugin:sync:version": "node ./scripts/sync-plugin.mjs", "publish:docs": "appium-docs build --deploy --push -b docs-site -m 'docs: build docs for appium-inspector@%s' --alias latest", "install-docs-deps": "appium-docs init --no-mkdocs", "postversion": "git pull --tags && git push && git push --tags", diff --git a/plugins/README.md b/plugins/README.md new file mode 100644 index 000000000..a16d3c2a2 --- /dev/null +++ b/plugins/README.md @@ -0,0 +1,54 @@ +# Appium Inspector Plugin + +A plugin that integrates the [Appium Inspector](https://github.com/appium/appium-inspector) directly into your Appium server installation, providing a web-based interface for inspecting and interacting with your application under test. + +## Features + +- Web-based Appium Inspector interface accessible via `/inspector` endpoint with appium server +- Full feature parity with standalone Appium Inspector + +## Installation + +Install the plugin using one of the following methods: + +```bash +# Install from local directory. Then, please run 'npm run build:plugin' as well. +appium plugin install --source=local /path/to/appium-inspector/plugins +``` + +> [!Note] +> Appium 3 will support this plugin as a first-class plugin with `appium plugin install inspector` + +## Usage + +1. Start Appium server with the inspector plugin enabled: + +```bash +appium --use-plugins=inspector --allow-cors +``` + +2. Access the Inspector interface by navigating to: + +``` +http://localhost:4723/inspector +``` + +## Development + +1. `git clone` this repositiry +2. `appium plugin install --source=local /path/to/appium-inspector/plugins` +3. Update the plugin content with `npm run build:plugin` in `/path/to/appium-inspector` +4. Start Appium with `appium --use-plugins=inspector --allow-cors` + +This plugin only needs the `appium` server as a `peerDependencies`. + +## Release + +(TODO: add this release steps in .github/workflows/package.yml later as another PR) + +1. Run `npm run plugin:sync:version` to sync the version with the root project.json +2. Run `npm publish` in `/path/to/appium-inspector/plugins` to publish the module + +## License + +[Apache-2.0](https://github.com/appium/appium-inspector/blob/main/LICENSE) diff --git a/plugins/index.mjs b/plugins/index.mjs new file mode 100644 index 000000000..061bfe79d --- /dev/null +++ b/plugins/index.mjs @@ -0,0 +1,44 @@ +import path from 'node:path'; +import {fileURLToPath} from 'node:url'; + +import {BasePlugin} from 'appium/plugin.js'; +const PLUGIN_ROOT_PATH = '/inspector'; +const INDEX_HTML = 'index.html'; +const ROOT_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), 'dist-browser'); + +/** + * Appium Inspector Plugin class + * @extends {BasePlugin} + */ +export class AppiumInspectorPlugin extends BasePlugin { + /** + * Creates an instance of AppiumInspectorPlugin + * @param {string} name - The name of the plugin + * @param {Record} cliArgs - Command line arguments + */ + constructor(name, cliArgs) { + super(name, cliArgs); + } + + /** + * Handles inspector page requests + * @param {import('express').Request} req - Express request object + * @param {import('express').Response} res - Express response object + * @returns {Promise} + */ + static async openInspector(req, res) { + const reqPath = + req.path === PLUGIN_ROOT_PATH ? INDEX_HTML : req.path.substring(PLUGIN_ROOT_PATH.length); + res.sendFile(reqPath, {root: ROOT_DIR}); + } + + /** + * Updates the Express server configuration + * @param {import('express').Application} expressApp - Express application instance + * @returns {Promise} + */ + static async updateServer(expressApp) { + // Handle both /inspector and /inspector/* paths + expressApp.all(['/inspector', '/inspector/*'], AppiumInspectorPlugin.openInspector); + } +} diff --git a/plugins/package.json b/plugins/package.json new file mode 100644 index 000000000..23cc5eff2 --- /dev/null +++ b/plugins/package.json @@ -0,0 +1,47 @@ +{ + "name": "appium-inspector-plugin", + "version": "2024.12.1", + "description": "An app inspector for use with an Appium server", + "repository": { + "type": "git", + "url": "git+https://github.com/appium/appium-inspector.git" + }, + "author": { + "name": "Appium Developers", + "url": "https://github.com/appium" + }, + "license": "Apache-2.0", + "bugs": { + "url": "https://github.com/appium/appium-inspector/issues" + }, + "keywords": [ + "appium" + ], + "homepage": "https://github.com/appium/appium-inspector", + "main": "index.mjs", + "type": "module", + "exports": { + ".": { + "import": "./index.mjs" + } + }, + "peerDependencies": { + "appium": "^2.0.0" + }, + "files": [ + "index.mjs", + "package.json", + "dist-browser", + "README.md" + ], + "dependencies": {}, + "devDependencies": {}, + "engines": { + "node": ">=20.x", + "npm": ">=10.x" + }, + "appium": { + "pluginName": "inspector", + "mainClass": "AppiumInspectorPlugin" + } +} diff --git a/scripts/sync-plugin.mjs b/scripts/sync-plugin.mjs new file mode 100644 index 000000000..9417570e8 --- /dev/null +++ b/scripts/sync-plugin.mjs @@ -0,0 +1,48 @@ +import fs from 'node:fs/promises'; +import path from 'node:path'; +import {fileURLToPath} from 'node:url'; + +const PROJECT_ROOT = path.dirname(fileURLToPath(import.meta.url)); +const ROOT_PKG_JSON_PATH = path.resolve(PROJECT_ROOT, '..', 'package.json'); +const PLUGIN_PKG_JSON_PATH = path.resolve(PROJECT_ROOT, '..', 'plugins', 'package.json'); + +const SYNC_PACKAGE_KEYS = [ + // To update ever version release + 'version', + + // These basic information should be the same with the top package.json + 'engines', + 'license', + 'repository', + 'author', + 'bugs', + 'homepage', +]; + +/** + * Return JSON parsed contents from the given path. + * @param {string} path + * @returns {object} + */ +async function readJsonContent(jsonPath) { + return JSON.parse(await fs.readFile(jsonPath, 'utf8')); +} + +async function main() { + const [rootJsonContent, pluginJsonContent] = await Promise.all( + [ROOT_PKG_JSON_PATH, PLUGIN_PKG_JSON_PATH].map(readJsonContent), + ); + + for (const key of SYNC_PACKAGE_KEYS) { + pluginJsonContent[key] = rootJsonContent[key]; + } + + // The new line in the last is to avoid prettier error. + await fs.writeFile( + PLUGIN_PKG_JSON_PATH, + `${JSON.stringify(pluginJsonContent, null, 2)}\n`, + 'utf8', + ); +} + +(async () => await main())(); From 1ecb5aa064350767aa0d04659facfed642348d81 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 5 Jan 2025 12:26:00 +0200 Subject: [PATCH 3/4] chore: Update translations (#1881) Co-authored-by: eglitise <37242620+eglitise@users.noreply.github.com> --- app/common/public/locales/ko/translation.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/common/public/locales/ko/translation.json b/app/common/public/locales/ko/translation.json index ffde5dc34..e51471f1b 100644 --- a/app/common/public/locales/ko/translation.json +++ b/app/common/public/locales/ko/translation.json @@ -1,5 +1,5 @@ { - "appiumInspector": "", + "appiumInspector": "Appium Inspector", "Edit": "변경", "Redo": "재실행", "Cut": "자르기", From 31e38f6c346b8c006a311d9c1b19eae2c5b10869 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgars=20Egl=C4=ABtis?= <37242620+eglitise@users.noreply.github.com> Date: Mon, 6 Jan 2025 12:27:58 +0200 Subject: [PATCH 4/4] chore(deps): bump ESlint to v9 and update other lint-related packages (#1882) * chore: bump ESLint-related packages * chore: tune some linting errors/warnings * chore: fix more lint warnings * chore: fix last warning * chore: remove duplicate line in Ignores block * chore: run prettier --- app/common/renderer/actions/Inspector.js | 6 +- app/common/renderer/actions/Session.js | 46 +- .../components/Inspector/Inspector.jsx | 6 +- app/common/renderer/lib/appium-client.js | 18 +- .../lib/client-frameworks/dotnet-nunit.js | 2 +- .../lib/client-frameworks/java-common.js | 2 +- app/common/renderer/reducers/Inspector.js | 20 +- app/common/renderer/reducers/Session.js | 18 +- app/common/renderer/utils/file-handling.js | 2 +- .../renderer/utils/locator-generation.js | 19 +- app/electron/main/updater.js | 3 +- eslint.config.mjs | 18 +- package-lock.json | 658 +++++++----------- package.json | 10 +- renovate.json | 4 +- test/e2e/pages/inspector-page-object.js | 2 +- test/e2e/pre-e2e.test.js | 128 ++-- test/integration/client-actions.test.js | 6 +- test/unit/utils-locator-generation.spec.js | 11 +- 19 files changed, 429 insertions(+), 550 deletions(-) diff --git a/app/common/renderer/actions/Inspector.js b/app/common/renderer/actions/Inspector.js index e2c8ce76f..64c7cff20 100644 --- a/app/common/renderer/actions/Inspector.js +++ b/app/common/renderer/actions/Inspector.js @@ -562,7 +562,7 @@ export function setLocatorTestElement(elementId) { location: {x: commandRes.x, y: commandRes.y}, size: {width: commandRes.width, height: commandRes.height}, }); - } catch (ign) {} + } catch {} } }; } @@ -817,7 +817,7 @@ export function runKeepAliveLoop() { log.info('Pinging Appium server to keep session active'); try { await driver.getTimeouts(); // Pings the Appium server to keep it alive - } catch (ign) {} + } catch {} const now = Date.now(); // If the new command limit has been surpassed, prompt user if they want to keep session going @@ -948,7 +948,7 @@ export function uploadGesturesFromFile(fileList) { gesture.description = gesture.description || i18n.t('gestureImportedFrom', {fileName}); parsedGestures.push(_.omit(gesture, ['id'])); - } catch (e) { + } catch { invalidGestures[fileName] = [i18n.t('gestureInvalidJsonError')]; } } diff --git a/app/common/renderer/actions/Session.js b/app/common/renderer/actions/Session.js index bc21f0742..fa7594b26 100644 --- a/app/common/renderer/actions/Session.js +++ b/app/common/renderer/actions/Session.js @@ -1,5 +1,5 @@ import {notification} from 'antd'; -import {includes, isPlainObject, isUndefined, toPairs, union, values, without} from 'lodash'; +import _ from 'lodash'; import moment from 'moment'; import {Web2Driver} from 'web2driver'; @@ -110,7 +110,7 @@ export function getCapsObject(caps) { try { let obj = JSON.parse(cap.value); return {[cap.name]: obj}; - } catch (ign) {} + } catch {} } return {[cap.name]: cap.value}; }), @@ -134,7 +134,7 @@ export function showError(e, params = {methodName: null, secs: 5, url: null}) { } else if (e.data) { try { e.data = JSON.parse(e.data); - } catch (ign) {} + } catch {} if (e.data.value && e.data.value.message) { errMessage = e.data.value.message; } else { @@ -149,8 +149,8 @@ export function showError(e, params = {methodName: null, secs: 5, url: null}) { } if ( errMessage === 'ECONNREFUSED' || - includes(errMessage, 'Failed to fetch') || - includes(errMessage, 'The requested resource could not be found') + _.includes(errMessage, 'Failed to fetch') || + _.includes(errMessage, 'The requested resource could not be found') ) { errMessage = i18n.t('couldNotConnect', {url}); } @@ -265,7 +265,7 @@ export function newSession(caps, attachSessId = null) { return false; } https = false; - if (!isPlainObject(desiredCapabilities[SAUCE_OPTIONS_CAP])) { + if (!_.isPlainObject(desiredCapabilities[SAUCE_OPTIONS_CAP])) { desiredCapabilities[SAUCE_OPTIONS_CAP] = {}; } if (!desiredCapabilities[SAUCE_OPTIONS_CAP].name) { @@ -277,7 +277,7 @@ export function newSession(caps, attachSessId = null) { let headspinUrl; try { headspinUrl = new URL(session.server.headspin.webDriverUrl); - } catch (ign) { + } catch { showError(new Error(`${i18n.t('Invalid URL:')} ${session.server.headspin.webDriverUrl}`)); return false; } @@ -328,7 +328,9 @@ export function newSession(caps, attachSessId = null) { desiredCapabilities['lt:options'].source = 'appiumdesktop'; desiredCapabilities['lt:options'].isRealMobile = true; if (session.server.advanced.useProxy) { - desiredCapabilities['lt:options'].proxyUrl = isUndefined(session.server.advanced.proxy) + desiredCapabilities['lt:options'].proxyUrl = _.isUndefined( + session.server.advanced.proxy, + ) ? '' : session.server.advanced.proxy; } @@ -336,7 +338,9 @@ export function newSession(caps, attachSessId = null) { desiredCapabilities['lambdatest:source'] = 'appiumdesktop'; desiredCapabilities['lambdatest:isRealMobile'] = true; if (session.server.advanced.useProxy) { - desiredCapabilities['lambdatest:proxyUrl'] = isUndefined(session.server.advanced.proxy) + desiredCapabilities['lambdatest:proxyUrl'] = _.isUndefined( + session.server.advanced.proxy, + ) ? '' : session.server.advanced.proxy; } @@ -422,7 +426,7 @@ export function newSession(caps, attachSessId = null) { let experitestUrl; try { experitestUrl = new URL(session.server.experitest.url); - } catch (ign) { + } catch { showError(new Error(`${i18n.t('Invalid URL:')} ${session.server.experitest.url}`)); return false; } @@ -464,7 +468,7 @@ export function newSession(caps, attachSessId = null) { let mobitruUrl; try { mobitruUrl = new URL(webDriverUrl); - } catch (ign) { + } catch { showError(new Error(`${i18n.t('Invalid URL:')} ${webDriverUrl}`)); return false; } @@ -524,13 +528,13 @@ export function newSession(caps, attachSessId = null) { // If a newCommandTimeout wasn't provided, set it to 60 * 60 so that sessions don't close on users in short term. // I saw sometimes infinit session timeout was not so good for cloud providers. // So, let me define this value as NEW_COMMAND_TIMEOUT_SEC by default. - if (isUndefined(desiredCapabilities[CAPS_NEW_COMMAND])) { + if (_.isUndefined(desiredCapabilities[CAPS_NEW_COMMAND])) { desiredCapabilities[CAPS_NEW_COMMAND] = NEW_COMMAND_TIMEOUT_SEC; } // If someone didn't specify connectHardwareKeyboard, set it to true by // default - if (isUndefined(desiredCapabilities[CAPS_CONNECT_HARDWARE_KEYBOARD])) { + if (_.isUndefined(desiredCapabilities[CAPS_CONNECT_HARDWARE_KEYBOARD])) { desiredCapabilities[CAPS_CONNECT_HARDWARE_KEYBOARD] = true; } @@ -602,7 +606,7 @@ export function newSession(caps, attachSessId = null) { try { mode = APP_MODE.WEB_HYBRID; await driver.navigateTo('https://appium.io'); - } catch (ign) {} + } catch {} } let mjpegScreenshotUrl = @@ -836,7 +840,7 @@ export function setSavedServerParams() { if (server) { // if we have a cloud provider as a saved server, but for some reason the // cloud provider is no longer in the list, revert server type to remote - if (values(SERVER_TYPES).includes(serverType) && !currentProviders.includes(serverType)) { + if (_.values(SERVER_TYPES).includes(serverType) && !currentProviders.includes(serverType)) { serverType = SERVER_TYPES.REMOTE; } dispatch({type: SET_SERVER, server, serverType}); @@ -953,7 +957,7 @@ async function fetchAllSessions(baseUrl, authToken) { try { const res = await fetchSessionInformation({url, authToken}); return res.data.value ?? []; - } catch (err) { + } catch { return []; } } @@ -963,7 +967,7 @@ async function fetchAllSessions(baseUrl, authToken) { try { const res = await fetchSessionInformation({url, authToken}); return formatSeleniumGridSessions(res); - } catch (err) { + } catch { return []; } } @@ -1023,7 +1027,7 @@ export function saveRawDesiredCaps() { } // Translate the caps JSON to array format - let newCapsArray = toPairs(newCaps).map(([name, value]) => ({ + let newCapsArray = _.toPairs(newCaps).map(([name, value]) => ({ type: (() => { let type = typeof value; @@ -1078,7 +1082,7 @@ export function stopAddCloudProvider() { export function addVisibleProvider(provider) { return async (dispatch, getState) => { let currentProviders = getState().session.visibleProviders; - const providers = union(currentProviders, [provider]); + const providers = _.union(currentProviders, [provider]); await setSetting(VISIBLE_PROVIDERS, providers); dispatch({type: SET_PROVIDERS, providers}); }; @@ -1091,7 +1095,7 @@ export function removeVisibleProvider(provider) { const action = changeServerType('remote'); await action(dispatch, getState); } - const providers = without(visibleProviders, provider); + const providers = _.without(visibleProviders, provider); await setSetting(VISIBLE_PROVIDERS, providers); dispatch({type: SET_PROVIDERS, providers}); }; @@ -1172,7 +1176,7 @@ export function initFromQueryString(loadNewSession) { try { const state = JSON.parse(initialState); dispatch({type: SET_STATE_FROM_URL, state}); - } catch (e) { + } catch { showError(new Error('Could not parse initial state from URL'), {secs: 0}); } } diff --git a/app/common/renderer/components/Inspector/Inspector.jsx b/app/common/renderer/components/Inspector/Inspector.jsx index 8799bbfd1..cea311001 100644 --- a/app/common/renderer/components/Inspector/Inspector.jsx +++ b/app/common/renderer/components/Inspector/Inspector.jsx @@ -13,7 +13,7 @@ import { ThunderboltOutlined, } from '@ant-design/icons'; import {Button, Card, Modal, Space, Spin, Switch, Tabs, Tooltip} from 'antd'; -import {debounce} from 'lodash'; +import _ from 'lodash'; import {useEffect, useRef, useState} from 'react'; import {useNavigate} from 'react-router'; @@ -123,7 +123,7 @@ const Inspector = (props) => { setScaleRatio(windowSize.width / newImgWidth); }; - const updateScreenshotScaleDebounced = debounce(updateScreenshotScale, 50); + const updateScreenshotScaleDebounced = _.debounce(updateScreenshotScale, 50); const checkMjpegStream = async () => { const {setAwaitingMjpegStream} = props; @@ -133,7 +133,7 @@ const Inspector = (props) => { try { await img.decode(); imgReady = true; - } catch (ign) {} + } catch {} if (imgReady && isAwaitingMjpegStream) { setAwaitingMjpegStream(false); updateScreenshotScaleDebounced(); diff --git a/app/common/renderer/lib/appium-client.js b/app/common/renderer/lib/appium-client.js index 594faa866..893341424 100644 --- a/app/common/renderer/lib/appium-client.js +++ b/app/common/renderer/lib/appium-client.js @@ -40,7 +40,7 @@ export default class AppiumClient { if (methodName === 'quit') { try { await this.driver.quit(); - } catch (ign) {} + } catch {} _instance = null; @@ -193,7 +193,7 @@ export default class AppiumClient { let element = null; try { element = await this.driver.findElement(strategy, selector); - } catch (err) { + } catch { return {}; } @@ -301,13 +301,13 @@ export default class AppiumClient { try { const systemBars = await this.driver.executeScript('mobile:getSystemBars', []); webviewTopOffset = systemBars.statusBar.height; - } catch (e) { + } catch { try { // to minimize the endpoint call which gets error in newer chromedriver. const sessionDetails = await this.driver.getSession(); // in case driver does not support mobile:getSystemBars webviewTopOffset = sessionDetails.viewportRect.top; - } catch (ign) {} + } catch {} } } } else if (this.driver.client.isIOS) { @@ -316,7 +316,7 @@ export default class AppiumClient { // emulate optional chaining of deeply embedded property which might not exist using // a try catch browserName = this.driver.client.capabilities.browserName.toLowerCase(); - } catch (ign) {} + } catch {} const isSafari = browserName === 'safari'; if (isSafari) { // on iOS, if we're in Safari simply find the top status bar and address bar and use its Y endpoint @@ -336,12 +336,12 @@ export default class AppiumClient { [], ); webviewLeftOffset = deviceScreenInfo.statusBarSize.height; - } catch (e) { + } catch { try { const sessionDetails = await this.driver.getSession(); // in case driver does not support mobile:deviceScreenInfo webviewLeftOffset = sessionDetails.statBarHeight; - } catch (ign) {} + } catch {} } } } else { @@ -406,7 +406,7 @@ export default class AppiumClient { try { await this.driver.getContexts(); return true; - } catch (ign) {} + } catch {} // If the app under test returns non JSON format response return false; @@ -454,7 +454,7 @@ export default class AppiumClient { let descriptionJSON = {attached: false}; try { descriptionJSON = JSON.parse(page.description); - } catch (ign) {} + } catch {} // You can have multiple `type` of pages, like service workers // We need to have pages with or 1. an attached view or 2. with an empty description diff --git a/app/common/renderer/lib/client-frameworks/dotnet-nunit.js b/app/common/renderer/lib/client-frameworks/dotnet-nunit.js index be77f1f8e..e96b6ee73 100644 --- a/app/common/renderer/lib/client-frameworks/dotnet-nunit.js +++ b/app/common/renderer/lib/client-frameworks/dotnet-nunit.js @@ -329,7 +329,7 @@ _driver.PerformActions(new List { swipe }); settings.push(`_driver.SetSetting("${settingName}", ${this.getCSharpVal(settingValue)});`); } return settings.join('\n'); - } catch (e) { + } catch { return `// Could not parse: ${settingsJson}`; } } diff --git a/app/common/renderer/lib/client-frameworks/java-common.js b/app/common/renderer/lib/client-frameworks/java-common.js index b6815dc55..75e24e4da 100644 --- a/app/common/renderer/lib/client-frameworks/java-common.js +++ b/app/common/renderer/lib/client-frameworks/java-common.js @@ -309,7 +309,7 @@ driver.perform(Arrays.asList(swipe)); settings.push(`driver.setSetting("${settingName}", ${this.getJavaVal(settingValue)});`); } return settings.join('\n'); - } catch (e) { + } catch { return `// Could not parse: ${settingsJson}`; } } diff --git a/app/common/renderer/reducers/Inspector.js b/app/common/renderer/reducers/Inspector.js index ddae04d2e..cf2b7ec3d 100644 --- a/app/common/renderer/reducers/Inspector.js +++ b/app/common/renderer/reducers/Inspector.js @@ -1,4 +1,4 @@ -import {omit} from 'lodash'; +import _ from 'lodash'; import { ADD_ASSIGNED_VAR_CACHE, @@ -207,7 +207,7 @@ export default function inspector(state = INITIAL_STATE, action) { }; case UNSELECT_CENTROID: - return omit(state, 'selectedCentroid'); + return _.omit(state, 'selectedCentroid'); case SET_SELECTED_ELEMENT_ID: return { @@ -231,7 +231,7 @@ export default function inspector(state = INITIAL_STATE, action) { }; case UNSELECT_HOVERED_ELEMENT: - return omit(state, 'hoveredElement'); + return _.omit(state, 'hoveredElement'); case SELECT_HOVERED_CENTROID: return { @@ -240,7 +240,7 @@ export default function inspector(state = INITIAL_STATE, action) { }; case UNSELECT_HOVERED_CENTROID: - return omit(state, 'hoveredCentroid'); + return _.omit(state, 'hoveredCentroid'); case METHOD_CALL_REQUESTED: return { @@ -600,7 +600,7 @@ export default function inspector(state = INITIAL_STATE, action) { ...state, savedGestures: action.savedGestures || [], }; - return omit(nextState, 'getSavedGesturesRequested'); + return _.omit(nextState, 'getSavedGesturesRequested'); case DELETE_SAVED_GESTURES_REQUESTED: return { @@ -609,7 +609,7 @@ export default function inspector(state = INITIAL_STATE, action) { }; case DELETE_SAVED_GESTURES_DONE: - return omit(state, 'deleteGesture'); + return _.omit(state, 'deleteGesture'); case SET_LOADED_GESTURE: return { @@ -618,7 +618,7 @@ export default function inspector(state = INITIAL_STATE, action) { }; case REMOVE_LOADED_GESTURE: - return omit(state, 'loadedGesture'); + return _.omit(state, 'loadedGesture'); case SHOW_GESTURE_ACTION: return { @@ -627,7 +627,7 @@ export default function inspector(state = INITIAL_STATE, action) { }; case HIDE_GESTURE_ACTION: - return omit(state, 'showGesture'); + return _.omit(state, 'showGesture'); case SELECT_TICK_ELEMENT: return { @@ -636,7 +636,7 @@ export default function inspector(state = INITIAL_STATE, action) { }; case UNSELECT_TICK_ELEMENT: - return omit(state, 'selectedTick'); + return _.omit(state, 'selectedTick'); case SET_GESTURE_TAP_COORDS_MODE: return { @@ -648,7 +648,7 @@ export default function inspector(state = INITIAL_STATE, action) { }; case CLEAR_TAP_COORDINATES: - return omit(state, 'tickCoordinates'); + return _.omit(state, 'tickCoordinates'); case TOGGLE_SHOW_ATTRIBUTES: return {...state, showSourceAttrs: !state.showSourceAttrs}; diff --git a/app/common/renderer/reducers/Session.js b/app/common/renderer/reducers/Session.js index 33fa730f6..eb174c3f8 100644 --- a/app/common/renderer/reducers/Session.js +++ b/app/common/renderer/reducers/Session.js @@ -1,4 +1,4 @@ -import _, {omit} from 'lodash'; +import _ from 'lodash'; import { ABORT_DESIRED_CAPS_EDITOR, @@ -92,10 +92,10 @@ export default function session(state = INITIAL_STATE, action) { ...state, newSessionLoading: true, }; - return omit(nextState, 'newSessionRequested'); + return _.omit(nextState, 'newSessionRequested'); case NEW_SESSION_DONE: - return omit(state, 'newSessionLoading'); + return _.omit(state, 'newSessionLoading'); case ADD_CAPABILITY: return { @@ -133,14 +133,14 @@ export default function session(state = INITIAL_STATE, action) { capsUUID: action.uuid, capsName: action.name, }; - return omit(nextState, 'isCapsDirty'); + return _.omit(nextState, 'isCapsDirty'); case SAVE_SESSION_REQUESTED: nextState = { ...state, saveSessionRequested: true, }; - return omit(nextState, 'showSaveAsModal'); + return _.omit(nextState, 'showSaveAsModal'); case SAVE_SESSION_DONE: nextState = { @@ -148,7 +148,7 @@ export default function session(state = INITIAL_STATE, action) { isEditingDesiredCapsName: false, isDuplicateCapsName: false, }; - return omit(nextState, ['saveSessionRequested', 'saveAsText']); + return _.omit(nextState, ['saveSessionRequested', 'saveAsText']); case GET_SAVED_SESSIONS_REQUESTED: return { @@ -161,7 +161,7 @@ export default function session(state = INITIAL_STATE, action) { ...state, savedSessions: action.savedSessions || [], }; - return omit(nextState, 'getSavedSessionsRequested'); + return _.omit(nextState, 'getSavedSessionsRequested'); case DELETE_SAVED_SESSION_REQUESTED: return { @@ -194,7 +194,7 @@ export default function session(state = INITIAL_STATE, action) { ...state, isDuplicateCapsName: false, }; - return omit(nextState, ['saveAsText', 'showSaveAsModal']); + return _.omit(nextState, ['saveAsText', 'showSaveAsModal']); case SET_SAVE_AS_TEXT: return { @@ -369,7 +369,7 @@ export default function session(state = INITIAL_STATE, action) { ...state.server, ...(action.state.server || {}), }, - ...omit(action.state, ['server']), + ..._.omit(action.state, ['server']), }; case SET_CAPABILITY_NAME_ERROR: diff --git a/app/common/renderer/utils/file-handling.js b/app/common/renderer/utils/file-handling.js index 024292634..572696560 100644 --- a/app/common/renderer/utils/file-handling.js +++ b/app/common/renderer/utils/file-handling.js @@ -60,7 +60,7 @@ export function parseSessionFileContents(sessionFileString) { } } return sessionJSON; - } catch (e) { + } catch { return null; } } diff --git a/app/common/renderer/utils/locator-generation.js b/app/common/renderer/utils/locator-generation.js index cb2ee6a94..d910809da 100644 --- a/app/common/renderer/utils/locator-generation.js +++ b/app/common/renderer/utils/locator-generation.js @@ -1,5 +1,5 @@ import _ from 'lodash'; -import XPath from 'xpath'; +import XPath, {select as xpathSelect} from 'xpath'; import {log} from './logger'; import {childNodesOf, domToXML, findDOMNodeByPath, xmlToDOM} from './source-parsing'; @@ -48,7 +48,7 @@ export function areAttrAndValueUnique(attrName, attrValue, sourceDoc) { if (!sourceDoc || _.isEmpty(sourceDoc)) { return true; } - return XPath.select(`//*[@${attrName}="${attrValue.replace(/"/g, '')}"]`, sourceDoc).length < 2; + return xpathSelect(`//*[@${attrName}="${attrValue.replace(/"/g, '')}"]`, sourceDoc).length < 2; } /** @@ -150,8 +150,9 @@ function determineXpathUniqueness(xpath, doc, domNode) { // If the XPath does not parse, move to the next unique attribute try { + // eslint-disable-next-line import/no-named-as-default-member -- needed for Vitest spy functionality othersWithAttr = XPath.select(xpath, doc); - } catch (ign) { + } catch { return [false]; } @@ -357,8 +358,8 @@ export function getOptimalClassChain(doc, domNode) { // If the XPath does not parse, move to the next unique attribute try { - othersWithAttr = XPath.select(xpath, doc); - } catch (ign) { + othersWithAttr = xpathSelect(xpath, doc); + } catch { continue; } @@ -429,8 +430,8 @@ export function getOptimalPredicateString(doc, domNode) { // If the XPath does not parse, move to the next attribute try { - othersWithAttr = XPath.select(xpath, doc); - } catch (ign) { + othersWithAttr = xpathSelect(xpath, doc); + } catch { continue; } @@ -506,8 +507,8 @@ export function getOptimalUiAutomatorSelector(doc, domNode, path) { // If the XPath does not parse, move to the next unique attribute try { - othersWithAttr = XPath.select(xpath, newDoc); - } catch (ign) { + othersWithAttr = xpathSelect(xpath, newDoc); + } catch { continue; } diff --git a/app/electron/main/updater.js b/app/electron/main/updater.js index 1febecccd..779dddf3b 100644 --- a/app/electron/main/updater.js +++ b/app/electron/main/updater.js @@ -1,6 +1,5 @@ import {dialog} from 'electron'; -import pkg from 'electron-updater'; -const {autoUpdater} = pkg; +import {autoUpdater} from 'electron-updater'; import {t} from './helpers'; diff --git a/eslint.config.mjs b/eslint.config.mjs index c74373944..e7f448735 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -1,9 +1,8 @@ import path from 'node:path'; import {fileURLToPath} from 'node:url'; +import appiumConfig from '@appium/eslint-config-appium-ts'; import {includeIgnoreFile} from '@eslint/compat'; -import {FlatCompat} from '@eslint/eslintrc'; -import js from '@eslint/js'; import reactPlugin from 'eslint-plugin-react'; import simpleImportSortPlugin from 'eslint-plugin-simple-import-sort'; import globals from 'globals'; @@ -11,20 +10,15 @@ import globals from 'globals'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); const gitignorePath = path.resolve(__dirname, '.gitignore'); -const compat = new FlatCompat({ - baseDirectory: __dirname, - recommendedConfig: js.configs.recommended, - allConfig: js.configs.all, -}); export default [ + ...appiumConfig, { name: 'React Plugin', files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'], ...reactPlugin.configs.flat.recommended, ...reactPlugin.configs.flat['jsx-runtime'], }, - ...compat.extends('@appium/eslint-config-appium-ts'), { name: 'JS/TS Files', files: ['**/*.{js,mjs,cjs,jsx,mjsx,ts,tsx,mtsx}'], @@ -50,11 +44,7 @@ export default [ }, }, { - ignores: [ - ...includeIgnoreFile(gitignorePath).ignores, - '**/.*', // dotfiles aren't ignored by default in FlatConfig - '**/*.xml', - '**/*.html', - ], + name: 'Ignores', + ignores: [...includeIgnoreFile(gitignorePath).ignores, '**/*.xml', '**/*.html'], }, ]; diff --git a/package-lock.json b/package-lock.json index f7c1033c8..ed7828c66 100644 --- a/package-lock.json +++ b/package-lock.json @@ -40,19 +40,17 @@ }, "devDependencies": { "@appium/docutils": "1.0.27", - "@appium/eslint-config-appium-ts": "0.3.3", + "@appium/eslint-config-appium-ts": "1.0.1", "@appium/fake-driver": "5.6.0", "@appium/support": "6.0.1", - "@eslint/compat": "1.1.1", - "@eslint/eslintrc": "3.2.0", - "@eslint/js": "9.17.0", + "@eslint/compat": "1.2.4", "@types/react": "18.3.18", "@vitejs/plugin-react": "4.3.4", "asyncbox": "3.0.0", "electron": "33.2.1", "electron-builder": "25.1.8", "electron-vite": "2.3.0", - "eslint": "8.57.1", + "eslint": "9.17.0", "eslint-plugin-react": "7.37.3", "eslint-plugin-simple-import-sort": "12.1.1", "globals": "15.14.0", @@ -254,29 +252,10 @@ "node": ">= 14" } }, - "node_modules/@appium/eslint-config-appium": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/@appium/eslint-config-appium/-/eslint-config-appium-8.0.5.tgz", - "integrity": "sha512-Hi6HHPs6Y0xO09cXfWkrV1NSzxQm5FRDKjGBmvnam7uxmKySKvSwS1jFAkPAom/CJi5B2MijvvdlCSWXVyFWUA==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0", - "npm": ">=8" - }, - "peerDependencies": { - "eslint": "^8.21.0", - "eslint-config-prettier": "^8.5.0 || ^9.0.0", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-mocha": "^10.1.0", - "eslint-plugin-promise": "^6.0.0" - } - }, "node_modules/@appium/eslint-config-appium-ts": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@appium/eslint-config-appium-ts/-/eslint-config-appium-ts-0.3.3.tgz", - "integrity": "sha512-GWRSAn+dwUB/nPzOvZaZuQtQZzHG3+ImkLy5L4xEJ14nuxu9KG1moKXybvzmplbm+WuK0Cso3vaWlfwEcwB0Fw==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@appium/eslint-config-appium-ts/-/eslint-config-appium-ts-1.0.1.tgz", + "integrity": "sha512-L4VlytgMeukkNeKToONIgQExpUAjMMb14oGYDlDyR3uPrOEi/9QiWEj4+k598g6kXUe/O3Ehq2/8SAgh197wRw==", "dev": true, "license": "Apache-2.0", "engines": { @@ -284,15 +263,16 @@ "npm": ">=8" }, "peerDependencies": { - "@appium/eslint-config-appium": "^8.0.0", - "@typescript-eslint/eslint-plugin": "^7.0.0", - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0", + "@eslint/compat": "^1.1.0", + "@eslint/js": "^9.0.0", + "@typescript-eslint/eslint-plugin": "^8.0.0", + "@typescript-eslint/parser": "^8.0.0", + "eslint": "^9.0.0", "eslint-config-prettier": "^9.0.0", "eslint-import-resolver-typescript": "^3.5.0", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-mocha": "^10.1.0", - "eslint-plugin-promise": "^6.0.0" + "eslint-plugin-import": "^2.30.0", + "eslint-plugin-mocha": "^10.4.0", + "eslint-plugin-promise": "^7.0.0" } }, "node_modules/@appium/fake-driver": { @@ -1661,11 +1641,47 @@ } }, "node_modules/@eslint/compat": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.1.1.tgz", - "integrity": "sha512-lpHyRyplhGPL5mGEh6M9O5nnKk0Gz4bFI+Zu6tKlPpDUN7XshWvH9C/px4UVm87IAANE0W81CEsNGbS1KlzXpA==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.2.4.tgz", + "integrity": "sha512-S8ZdQj/N69YAtuqFt7653jwcvuUj131+6qGLUyDqfDg1OIoBQ66OCuXC473YQfO2AaxITTutiRQiDwoo7ZLYyg==", "dev": true, "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": "^9.10.0" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/@eslint/config-array": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.19.1.tgz", + "integrity": "sha512-fo6Mtm5mWyKjA/Chy1BYTdn5mGJoDNjC7C64ug20ADsRDGrA85bN3uK3MaKbeRkRuuIEAR5N33Jr1pbm411/PA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.5", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.9.1.tgz", + "integrity": "sha512-GuUdqkyyzQI5RMIWkHhvTWLCyLo1jNK3vzkSyaExH5kHPDHcuL2VOpHjmMY+y3+NC69qAKToBqldTBgYeLSr9Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } @@ -1717,6 +1733,29 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, + "node_modules/@eslint/object-schema": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.5.tgz", + "integrity": "sha512-o0bhxnL89h5Bae5T318nFoFzGy+YE5i/gGkoPAgkmTVdRKTiv3p8JHevPiPaMwoloKfEiiaHlawCqaZMqRm+XQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.4.tgz", + "integrity": "sha512-zSkKow6H5Kdm0ZUQUB2kV5JIXqoG0+uH5YADhaEHswm664N9Db8dXSi0nMJpacpMf+MyyglF1vnZohpEg5yUtg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@gar/promisify": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", @@ -1724,20 +1763,42 @@ "dev": true, "license": "MIT" }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.6", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz", + "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.3.0" }, "engines": { - "node": ">=10.10.0" + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" } }, "node_modules/@humanwhocodes/module-importer": { @@ -1754,13 +1815,19 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", + "node_modules/@humanwhocodes/retry": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz", + "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==", "dev": true, - "license": "BSD-3-Clause" + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@img/sharp-darwin-arm64": { "version": "0.33.5", @@ -2382,6 +2449,7 @@ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -2396,6 +2464,7 @@ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">= 8" } @@ -2406,6 +2475,7 @@ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -3457,83 +3527,75 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", - "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.19.0.tgz", + "integrity": "sha512-NggSaEZCdSrFddbctrVjkVZvFC6KGfKfNK0CU7mNK/iKHGKbzT4Wmgm08dKpcZECBu9f5FypndoMyRHkdqfT1Q==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/type-utils": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", + "@typescript-eslint/scope-manager": "8.19.0", + "@typescript-eslint/type-utils": "8.19.0", + "@typescript-eslint/utils": "8.19.0", + "@typescript-eslint/visitor-keys": "8.19.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/parser": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", - "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.19.0.tgz", + "integrity": "sha512-6M8taKyOETY1TKHp0x8ndycipTVgmp4xtg5QpEZzXxDhNvvHOJi5rLRkLr8SK3jTgD5l4fTlvBiRdfsuWydxBw==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "peer": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", + "@typescript-eslint/scope-manager": "8.19.0", + "@typescript-eslint/types": "8.19.0", + "@typescript-eslint/typescript-estree": "8.19.0", + "@typescript-eslint/visitor-keys": "8.19.0", "debug": "^4.3.4" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", - "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.19.0.tgz", + "integrity": "sha512-hkoJiKQS3GQ13TSMEiuNmSCvhz7ujyqD1x3ShbaETATHrck+9RaDdUbt+osXaUuns9OFwrDTTrjtwsU8gJyyRA==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0" + "@typescript-eslint/types": "8.19.0", + "@typescript-eslint/visitor-keys": "8.19.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -3541,43 +3603,39 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", - "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.19.0.tgz", + "integrity": "sha512-TZs0I0OSbd5Aza4qAMpp1cdCYVnER94IziudE3JU328YUHgWu9gwiwhag+fuLeJ2LkWLXI+F/182TbG+JaBdTg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/utils": "7.18.0", + "@typescript-eslint/typescript-estree": "8.19.0", + "@typescript-eslint/utils": "8.19.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/types": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", - "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.19.0.tgz", + "integrity": "sha512-8XQ4Ss7G9WX8oaYvD4OOLCjIQYgRQxO+qCiR2V2s2GxI9AUpo7riNwo6jDhKtTcaJjT8PY54j2Yb33kWtSJsmA==", "dev": true, "license": "MIT", "peer": true, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -3585,33 +3643,31 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", - "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.19.0.tgz", + "integrity": "sha512-WW9PpDaLIFW9LCbucMSdYUuGeFUz1OkWYS/5fwZwTA+l2RwlWFdJvReQqMUMBw4yJWJOfqd7An9uwut2Oj8sLw==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "peer": true, "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", + "@typescript-eslint/types": "8.19.0", + "@typescript-eslint/visitor-keys": "8.19.0", "debug": "^4.3.4", - "globby": "^11.1.0", + "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^1.3.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { @@ -3643,54 +3699,62 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", - "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.19.0.tgz", + "integrity": "sha512-PTBG+0oEMPH9jCZlfg07LCB2nYI0I317yyvXGfxnvGvw4SHIOuRnQ3kadyyXY6tGdChusIHIbM5zfIbp4M6tCg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0" + "@typescript-eslint/scope-manager": "8.19.0", + "@typescript-eslint/types": "8.19.0", + "@typescript-eslint/typescript-estree": "8.19.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <5.8.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", - "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", + "version": "8.19.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.19.0.tgz", + "integrity": "sha512-mCFtBbFBJDCNCWUl5y6sZSCHXw1DEFEk3c/M3nRK2a4XUB8StGFtmcEMizdjKuBzB6e/smJAAWYug3VrdLMr1w==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "@typescript-eslint/types": "7.18.0", - "eslint-visitor-keys": "^3.4.3" + "@typescript-eslint/types": "8.19.0", + "eslint-visitor-keys": "^4.2.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.1.tgz", - "integrity": "sha512-fEzPV3hSkSMltkw152tJKNARhOupqbH96MZWyRjNaYZOMIzbrTeQDG+MTc6Mr2pgzFQzFxAfmhGDNP5QK++2ZA==", + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, - "license": "ISC" + "license": "Apache-2.0", + "peer": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } }, "node_modules/@vitejs/plugin-react": { "version": "4.3.4", @@ -4627,17 +4691,6 @@ "integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==", "license": "MIT" }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/array.prototype.findlast": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", @@ -6483,20 +6536,6 @@ "p-limit": "^3.1.0 " } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/dmg-builder": { "version": "25.1.8", "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-25.1.8.tgz", @@ -6593,19 +6632,6 @@ "node": ">=8" } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/dom-align": { "version": "1.12.4", "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.4.tgz", @@ -7705,60 +7731,63 @@ } }, "node_modules/eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", - "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.17.0.tgz", + "integrity": "sha512-evtlNcpJg+cZLcnVKwsai8fExnqjGPicK7gnUtlNuzu+Fv9bI0aLpND5T44VLQtoMEnI57LoXO9XAkIXwohKrA==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.19.0", + "@eslint/core": "^0.9.0", + "@eslint/eslintrc": "^3.2.0", + "@eslint/js": "9.17.0", + "@eslint/plugin-kit": "^0.2.3", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", + "@humanwhocodes/retry": "^0.4.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.6", "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", - "esquery": "^1.4.2", + "eslint-scope": "^8.2.0", + "eslint-visitor-keys": "^4.2.0", + "espree": "^10.3.0", + "esquery": "^1.5.0", "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", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-config-prettier": { @@ -7988,14 +8017,17 @@ } }, "node_modules/eslint-plugin-promise": { - "version": "6.6.0", - "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-6.6.0.tgz", - "integrity": "sha512-57Zzfw8G6+Gq7axm2Pdo3gW/Rx3h9Yywgn61uE/3elTCOePEHVrn2i5CdfBwA1BLK0Q0WqctICIUSqXZW/VprQ==", + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-7.2.1.tgz", + "integrity": "sha512-SWKjd+EuvWkYaS+uN2csvj0KoP43YTu7+phKQ5v+xw6+A0gutVX2yqCeCkC3uLCJFiPfR2dD8Es5L7yUsmvEaA==", "dev": true, "license": "ISC", "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -8089,9 +8121,9 @@ } }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz", + "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==", "dev": true, "license": "BSD-2-Clause", "dependencies": { @@ -8099,7 +8131,7 @@ "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -8149,87 +8181,19 @@ "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.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" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/eslint/node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, + "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/espree": { "version": "10.3.0", "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz", @@ -8575,6 +8539,7 @@ "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "license": "ISC", + "peer": true, "dependencies": { "reusify": "^1.0.4" } @@ -8597,16 +8562,16 @@ "peer": true }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/filelist": { @@ -8713,57 +8678,17 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "license": "MIT", "dependencies": { "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flat-cache/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "keyv": "^4.5.4" }, "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/flat-cache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "node": ">=16" } }, "node_modules/flatted": { @@ -9239,28 +9164,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", @@ -9310,7 +9213,8 @@ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true, - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/handle-thing": { "version": "2.0.1", @@ -10188,16 +10092,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -12534,17 +12428,6 @@ "node": ">=16" } }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/pathe": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", @@ -12870,7 +12753,8 @@ "url": "https://feross.org/support" } ], - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/queue-tick": { "version": "1.0.1", @@ -14008,6 +13892,7 @@ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, "license": "MIT", + "peer": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -14203,6 +14088,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "queue-microtask": "^1.2.2" } @@ -14766,17 +14652,6 @@ "node": ">=10" } }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=8" - } - }, "node_modules/slice-ansi": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", @@ -15461,13 +15336,6 @@ "license": "MIT", "peer": true }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true, - "license": "MIT" - }, "node_modules/throttle-debounce": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.2.tgz", diff --git a/package.json b/package.json index 785436625..8b7bcac39 100644 --- a/package.json +++ b/package.json @@ -95,25 +95,21 @@ "xpath": "0.0.34" }, "//devDependencies": { - "@eslint/compat": "1.2.0: peer dependency on ESLint 9", - "eslint": "V9: need support in Appium's config", "vite": "V6: need support in electron-vite" }, "devDependencies": { "@appium/docutils": "1.0.27", - "@appium/eslint-config-appium-ts": "0.3.3", + "@appium/eslint-config-appium-ts": "1.0.1", "@appium/fake-driver": "5.6.0", "@appium/support": "6.0.1", - "@eslint/compat": "1.1.1", - "@eslint/eslintrc": "3.2.0", - "@eslint/js": "9.17.0", + "@eslint/compat": "1.2.4", "@types/react": "18.3.18", "@vitejs/plugin-react": "4.3.4", "asyncbox": "3.0.0", "electron": "33.2.1", "electron-builder": "25.1.8", "electron-vite": "2.3.0", - "eslint": "8.57.1", + "eslint": "9.17.0", "eslint-plugin-react": "7.37.3", "eslint-plugin-simple-import-sort": "12.1.1", "globals": "15.14.0", diff --git a/renovate.json b/renovate.json index 33eeb9d98..edb1603c4 100644 --- a/renovate.json +++ b/renovate.json @@ -12,12 +12,12 @@ "automerge": true }, { - "matchPackageNames": ["antd", "cheerio", "eslint", "react", "vite"], + "matchPackageNames": ["antd", "cheerio", "react", "vite"], "matchUpdateTypes": ["major"], "enabled": false }, { - "matchPackageNames": ["@eslint/compat", "web2driver"], + "matchPackageNames": ["web2driver"], "matchUpdateTypes": ["minor", "patch"], "enabled": false }, diff --git a/test/e2e/pages/inspector-page-object.js b/test/e2e/pages/inspector-page-object.js index aecb300aa..bf9429000 100644 --- a/test/e2e/pages/inspector-page-object.js +++ b/test/e2e/pages/inspector-page-object.js @@ -60,7 +60,7 @@ export default class InspectorPage extends BasePage { await retryInterval(5, 500, async () => { await (await this.client.$('.ant-notification-notice-close')).click(); }); - } catch (ign) {} + } catch {} } async startRecording() { diff --git a/test/e2e/pre-e2e.test.js b/test/e2e/pre-e2e.test.js index 94f9739c0..56d666774 100644 --- a/test/e2e/pre-e2e.test.js +++ b/test/e2e/pre-e2e.test.js @@ -8,63 +8,81 @@ const platform = os.platform(); const appName = 'inspector'; const log = logger.getLogger('E2E Test'); -before(async function () { - let appPath; - // let args = []; - if (process.env.SPECTRON_TEST_PROD_BINARIES) { - if (platform === 'linux') { - appPath = join(__dirname, '..', '..', appName, 'release', 'linux-unpacked', 'appium-desktop'); - } else if (platform === 'darwin') { - appPath = join( - __dirname, - '..', - '..', - appName, - 'release', - 'mac', - 'Appium.app', - 'Contents', - 'MacOS', - 'Appium', - ); - } else if (platform === 'win32') { - appPath = join(__dirname, '..', '..', appName, 'release', 'win-ia32-unpacked', 'Appium.exe'); +describe('E2E tests', function () { + before(async function () { + let appPath; + // let args = []; + if (process.env.SPECTRON_TEST_PROD_BINARIES) { + if (platform === 'linux') { + appPath = join( + __dirname, + '..', + '..', + appName, + 'release', + 'linux-unpacked', + 'appium-desktop', + ); + } else if (platform === 'darwin') { + appPath = join( + __dirname, + '..', + '..', + appName, + 'release', + 'mac', + 'Appium.app', + 'Contents', + 'MacOS', + 'Appium', + ); + } else if (platform === 'win32') { + appPath = join( + __dirname, + '..', + '..', + appName, + 'release', + 'win-ia32-unpacked', + 'Appium.exe', + ); + } + } else { + appPath = require(join(__dirname, '..', '..', 'node_modules', 'electron')); + // args = [join(__dirname, '..', '..')]; } - } else { - appPath = require(join(__dirname, '..', '..', 'node_modules', 'electron')); - // args = [join(__dirname, '..', '..')]; - } - this.timeout(process.env.E2E_TIMEOUT || 60 * 1000); - log.info(`Running Appium from: ${appPath}`); - log.info(`Checking that "${appPath}" exists`); - const applicationExists = await fs.exists(appPath); - if (!applicationExists) { - log.error(`Could not run tests. "${appPath}" does not exist.`); - process.exit(1); - } - log.info(`App exists. Creating application instance`); - // this.app = new Application({ - // path: appPath, - // env: { - // FORCE_NO_WRONG_FOLDER: true, - // }, - // args, - // }); - log.info(`Application instance created. Starting app`); - await this.app.start(); - const client = this.app.client; - log.info(`App started; waiting for splash page to go away`); - await retryInterval(20, 1000, async function () { - const handles = await client.getWindowHandles(); - await client.switchToWindow(handles[0]); - expect(await client.getUrl()).toContain('index.html'); + this.timeout(process.env.E2E_TIMEOUT || 60 * 1000); + log.info(`Running Appium from: ${appPath}`); + log.info(`Checking that "${appPath}" exists`); + const applicationExists = await fs.exists(appPath); + if (!applicationExists) { + log.error(`Could not run tests. "${appPath}" does not exist.`); + process.exit(1); + } + log.info(`App exists. Creating application instance`); + // this.app = new Application({ + // path: appPath, + // env: { + // FORCE_NO_WRONG_FOLDER: true, + // }, + // args, + // }); + log.info(`Application instance created. Starting app`); + await this.app.start(); + const client = this.app.client; + log.info(`App started; waiting for splash page to go away`); + await retryInterval(20, 1000, async function () { + const handles = await client.getWindowHandles(); + await client.switchToWindow(handles[0]); + expect(await client.getUrl()).toContain('index.html'); + }); + log.info(`App ready for automation`); }); - log.info(`App ready for automation`); -}); -after(function () { - if (this.app && this.app.isRunning()) { - return this.app.stop(); - } + after(function () { + if (this.app && this.app.isRunning()) { + return this.app.stop(); + } + }); }); diff --git a/test/integration/client-actions.test.js b/test/integration/client-actions.test.js index ba2f09d67..01769fd27 100644 --- a/test/integration/client-actions.test.js +++ b/test/integration/client-actions.test.js @@ -35,7 +35,7 @@ describe('Appium client actions', function () { afterAll(async function () { try { await driver.quit(); - } catch (ign) {} + } catch {} await server.close(); }); @@ -78,7 +78,7 @@ describe('Appium client actions', function () { }); }); describe('.executeMethod', function () { - it('should call the click method and have the variableName, variableType, etc... returned to it with source/screenshot', async function () { + it('should be able to call the click method on a single element', async function () { const {id, variableName, variableType} = await client.fetchElement({ strategy: 'xpath', selector: '//MockListItem', @@ -97,7 +97,7 @@ describe('Appium client actions', function () { expect(source).toBeTruthy(); expect(screenshot).toBeTruthy(); }); - it('should call the click method and have the variableName, variableType, etc... returned to it with source/screenshot', async function () { + it('should be able to call the click method on multiple elements', async function () { const {elements} = await client.fetchElements({ strategy: 'xpath', selector: '//MockListItem', diff --git a/test/unit/utils-locator-generation.spec.js b/test/unit/utils-locator-generation.spec.js index 0d2d957a7..00b249788 100644 --- a/test/unit/utils-locator-generation.spec.js +++ b/test/unit/utils-locator-generation.spec.js @@ -20,17 +20,16 @@ function testXPath(doc, node, expectedXPath) { describe('utils/locator-generation.js', function () { describe('#areAttrAndValueUnique', function () { - it('should return false if two nodes have the same attribute value', function () { + it('should return true if there is only one node with this attribute value', function () { expect( areAttrAndValueUnique( 'id', 'ID', xmlToDOM(` - `), ), - ).toBe(false); + ).toBe(true); }); it('should return false if two nodes have the same attribute value', function () { @@ -40,9 +39,13 @@ describe('utils/locator-generation.js', function () { 'ID', xmlToDOM(` + `), ), - ).toBe(true); + ).toBe(false); + }); + + it('should return true if there are no nodes with this attribute', function () { expect( areAttrAndValueUnique( 'id',