diff --git a/dashboard-frontend b/dashboard-frontend index 1c40b81f4..c1135b6de 160000 --- a/dashboard-frontend +++ b/dashboard-frontend @@ -1 +1 @@ -Subproject commit 1c40b81f47fd4be74de421a1e6dccf94f53e30f2 +Subproject commit c1135b6de2e2ceeb39dd2ae54a1c2e7351513a46 diff --git a/package-lock.json b/package-lock.json index fab51d010..9ec7599f0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "appium-device-farm", - "version": "11.2.10", + "version": "11.2.15", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "appium-device-farm", - "version": "11.2.10", + "version": "11.2.15", "hasInstallScript": true, "license": "ISC", "dependencies": { @@ -4401,6 +4401,46 @@ "node": ">=18" } }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.4.tgz", + "integrity": "sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.3" + } + }, + "node_modules/@img/sharp-darwin-arm64/node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.3.tgz", + "integrity": "sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@img/sharp-darwin-x64": { "version": "0.34.5", "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", @@ -9681,6 +9721,423 @@ "node": ">=18" } }, + "node_modules/appium-uiautomator2-driver/node_modules/@img/sharp-darwin-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.4.tgz", + "integrity": "sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.3" + } + }, + "node_modules/appium-uiautomator2-driver/node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.3.tgz", + "integrity": "sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/appium-uiautomator2-driver/node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.3.tgz", + "integrity": "sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/appium-uiautomator2-driver/node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.3.tgz", + "integrity": "sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/appium-uiautomator2-driver/node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.3.tgz", + "integrity": "sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/appium-uiautomator2-driver/node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.3.tgz", + "integrity": "sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/appium-uiautomator2-driver/node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.3.tgz", + "integrity": "sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/appium-uiautomator2-driver/node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.3.tgz", + "integrity": "sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/appium-uiautomator2-driver/node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.3.tgz", + "integrity": "sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/appium-uiautomator2-driver/node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.3.tgz", + "integrity": "sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/appium-uiautomator2-driver/node_modules/@img/sharp-linux-arm": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.4.tgz", + "integrity": "sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.3" + } + }, + "node_modules/appium-uiautomator2-driver/node_modules/@img/sharp-linux-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.4.tgz", + "integrity": "sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.3" + } + }, + "node_modules/appium-uiautomator2-driver/node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.4.tgz", + "integrity": "sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.3" + } + }, + "node_modules/appium-uiautomator2-driver/node_modules/@img/sharp-linux-s390x": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.4.tgz", + "integrity": "sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.3" + } + }, + "node_modules/appium-uiautomator2-driver/node_modules/@img/sharp-linux-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.4.tgz", + "integrity": "sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.3" + } + }, + "node_modules/appium-uiautomator2-driver/node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.4.tgz", + "integrity": "sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.3" + } + }, + "node_modules/appium-uiautomator2-driver/node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.4.tgz", + "integrity": "sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.3" + } + }, + "node_modules/appium-uiautomator2-driver/node_modules/@img/sharp-wasm32": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.4.tgz", + "integrity": "sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.5.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/appium-uiautomator2-driver/node_modules/@img/sharp-win32-arm64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.4.tgz", + "integrity": "sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/appium-uiautomator2-driver/node_modules/@img/sharp-win32-ia32": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.4.tgz", + "integrity": "sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/appium-uiautomator2-driver/node_modules/@img/sharp-win32-x64": { + "version": "0.34.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.4.tgz", + "integrity": "sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/appium-uiautomator2-driver/node_modules/@isaacs/balanced-match": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", @@ -14040,6 +14497,46 @@ "node": ">=18" } }, + "node_modules/appium-xcuitest-driver/node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/appium-xcuitest-driver/node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/appium-xcuitest-driver/node_modules/@isaacs/balanced-match": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", @@ -14158,6 +14655,17 @@ "dev": true, "license": "MIT" }, + "node_modules/appium-xcuitest-driver/node_modules/@types/node": { + "version": "24.10.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.3.tgz", + "integrity": "sha512-gqkrWUsS8hcm0r44yn7/xZeV1ERva/nLgrLxFRUGb7aoNMIJfZJ3AC261zDQuOAKC7MiXai1WCpYc48jAHoShQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "undici-types": "~7.16.0" + } + }, "node_modules/appium-xcuitest-driver/node_modules/@types/normalize-package-data": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", @@ -18576,8 +19084,9 @@ "version": "7.16.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "extraneous": true, - "license": "MIT" + "dev": true, + "license": "MIT", + "optional": true }, "node_modules/appium-xcuitest-driver/node_modules/unorm": { "version": "1.6.0", @@ -37449,9 +37958,9 @@ "integrity": "sha512-v3UJF8xm68BBj6AF4oQML3ikrfK2c9EmZUyLOfShpJuItAqVBHWP/KtpGinkSsIiP6EZyyb6Z3NXyW9dgS9X1w==" }, "node_modules/typescript": { - "version": "5.5.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", - "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", "bin": { diff --git a/package.json b/package.json index bb1ab9cdb..6275fe5c9 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "test-remote": "mocha --require ts-node/register ./test/e2e/remote.spec.js --timeout 60000 --exit", "test": "mocha -r ts-node/register ./test/unit/*.spec.{j,t}s --plugin-device-farm-platform=both --exit --timeout=20000", "test-jest": "NODE_OPTIONS=--experimental-vm-modules npx jest ./test/unit/AndroidDeviceManager.spec.js", - "test-parallel-android": "mocha --require ts-node/register -p ./test/e2e/android/conf1.spec.js --exit --timeout 260000", + "test-parallel-android": "mocha --require ts-node/register -p ./test/e2e/android/conf.spec.js --exit --timeout 260000", "test-parallel-ios": "mocha --require ts-node/register -p ./test/e2e/ios/conf1.spec.js --exit --timeout 260000", "test-parallel-bs": "mocha --require ts-node/register -p ./test/e2e/android/cloud/bs.spec.ts --exit --timeout 260000", "test-parallel-pcloudy": "mocha --require ts-node/register -p ./test/e2e/android/cloud/pcloudy.spec.ts --exit --timeout 260000", @@ -312,6 +312,12 @@ }, "portRange": { "type": "string" + }, + "androidCleanUpApps": { + "type": "array" + }, + "iosCleanUpApps": { + "type": "array" } }, "title": "Appium device farm plugin", diff --git a/src/device-managers/AndroidDeviceManager.ts b/src/device-managers/AndroidDeviceManager.ts index 647ea6656..b15355163 100644 --- a/src/device-managers/AndroidDeviceManager.ts +++ b/src/device-managers/AndroidDeviceManager.ts @@ -1,24 +1,24 @@ -import { IDeviceManager } from '../interfaces/IDeviceManager'; -import { asyncForEach, getFreePort } from '../helpers'; -import { ADB, getSdkRootFromEnv } from 'appium-adb'; -import log from '../logger'; -import _ from 'lodash'; import { fs } from '@appium/support'; -import ChromeDriverManager from './ChromeDriverManager'; -import { Container } from 'typedi'; import Adb, { Client, DeviceWithPath } from '@devicefarmer/adbkit'; -import { AbortController } from 'node-abort-controller'; +import Tracker from '@devicefarmer/adbkit/dist/src/adb/tracker'; +import { ADB, getSdkRootFromEnv } from 'appium-adb'; import asyncWait from 'async-wait-until'; -import NodeDevices from './NodeDevices'; +import { sleep, waitForCondition } from 'asyncbox'; +import _ from 'lodash'; +import { AbortController } from 'node-abort-controller'; +import { Container } from 'typedi'; import { addNewDevice, generateDeviceId, removeDevice } from '../data-service/device-service'; -import Devices from './cloud/Devices'; -import { DeviceTypeToInclude, IPluginArgs } from '../interfaces/IPluginArgs'; +import { asyncForEach, getFreePort } from '../helpers'; import { IDevice } from '../interfaces/IDevice'; -import { DeviceUpdate } from '../types/DeviceUpdate'; -import Tracker from '@devicefarmer/adbkit/dist/src/adb/tracker'; -import { sleep, waitForCondition } from 'asyncbox'; +import { IDeviceManager } from '../interfaces/IDeviceManager'; +import { DeviceTypeToInclude, IPluginArgs } from '../interfaces/IPluginArgs'; +import log from '../logger'; import { DevicePlugin } from '../plugin'; +import { DeviceUpdate } from '../types/DeviceUpdate'; import { enhancedADBManager } from '../utils/enhanced-adb-manager'; +import ChromeDriverManager from './ChromeDriverManager'; +import Devices from './cloud/Devices'; +import NodeDevices from './NodeDevices'; export default class AndroidDeviceManager implements IDeviceManager { private adb: ADB | undefined; @@ -700,4 +700,16 @@ export default class AndroidDeviceManager implements IDeviceManager { return deviceName; }; + + public async uninstallApp(device: IDevice, packageId: string) { + try { + const { adbInstance } = await this.getAdb(); + await adbInstance.adbExec(['-s', device.udid, 'uninstall', packageId]); + log.info(`Uninstalled app ${packageId} from device ${device.udid}`); + } catch (err: any) { + log.warn( + `Failed to uninstall app ${packageId} from device ${device.udid}. Error: ${err.message}`, + ); + } + } } diff --git a/src/device-managers/IOSDeviceManager.ts b/src/device-managers/IOSDeviceManager.ts index 9faf1c1e8..2701a5abb 100644 --- a/src/device-managers/IOSDeviceManager.ts +++ b/src/device-managers/IOSDeviceManager.ts @@ -1,4 +1,4 @@ -import { utilities as IOSUtils } from 'appium-ios-device'; +import { utilities as IOSUtils, services } from 'appium-ios-device'; import { getDeviceInfo } from 'appium-ios-device/build/lib/utilities'; import Simctl from 'node-simctl'; import os from 'os'; @@ -509,4 +509,32 @@ export default class IOSDeviceManager implements IDeviceManager { const list = await simctl.list(); return { simctl, list }; } + + public async uninstallApp(device: IDevice, bundleId: string) { + try { + if (device.realDevice) { + log.info(`Uninstalling ${bundleId} from real device ${device.udid}`); + const installationService = await services.startInstallationProxyService(device.udid); + try { + await installationService.uninstallApplication(bundleId); + } catch (err) { + log.warn(`Could not uninstall app ${bundleId} from ${device.udid}: ${err}`); + } finally { + installationService.close(); + } + } else { + log.info(`Uninstalling ${bundleId} from simulator ${device.udid}`); + + const { exec } = require('child_process'); + const util = require('util'); + const execAsync = util.promisify(exec); + await execAsync(`xcrun simctl uninstall ${device.udid} ${bundleId}`); + } + log.info(`Uninstalled app ${bundleId} from device ${device.udid}`); + } catch (err: any) { + log.warn( + `Failed to uninstall app ${bundleId} from device ${device.udid}. Error: ${err.message}`, + ); + } + } } diff --git a/src/device-managers/index.ts b/src/device-managers/index.ts index 37838120e..b453786e5 100644 --- a/src/device-managers/index.ts +++ b/src/device-managers/index.ts @@ -5,6 +5,8 @@ import { Platform } from '../types/Platform'; import AndroidDeviceManager from './AndroidDeviceManager'; import IOSDeviceManager from './IOSDeviceManager'; +export { AndroidDeviceManager, IOSDeviceManager }; + export class DeviceFarmManager { private deviceManagers: IDeviceManager[] = []; private nodeId: string; diff --git a/src/interfaces/IDevice.ts b/src/interfaces/IDevice.ts index ff04bb104..da743e19c 100644 --- a/src/interfaces/IDevice.ts +++ b/src/interfaces/IDevice.ts @@ -49,4 +49,5 @@ export interface IDevice { firstname: string; lastname: string; }; + deviceFarmCapabilities?: Record; } diff --git a/src/interfaces/IDeviceManager.ts b/src/interfaces/IDeviceManager.ts index 24958208f..ac250d67f 100644 --- a/src/interfaces/IDeviceManager.ts +++ b/src/interfaces/IDeviceManager.ts @@ -1,9 +1,11 @@ import { IDevice } from './IDevice'; -import { DeviceTypeToInclude, IPluginArgs } from './IPluginArgs'; +import { DeviceTypeToInclude } from './IPluginArgs'; export interface IDeviceManager { getDevices( deviceTypes: { androidDeviceType: DeviceTypeToInclude; iosDeviceType: DeviceTypeToInclude }, existingDeviceDetails: Array, ): Promise; + + uninstallApp?(device: IDevice, bundleId: string): Promise; } diff --git a/src/interfaces/IPluginArgs.ts b/src/interfaces/IPluginArgs.ts index 3e0b64622..93c4429fc 100644 --- a/src/interfaces/IPluginArgs.ts +++ b/src/interfaces/IPluginArgs.ts @@ -86,6 +86,10 @@ export interface IPluginArgs { //node nodeName?: string; portRange?: string; + + // cleanup + androidCleanUpApps?: string[]; + iosCleanUpApps?: string[]; } export const DefaultPluginArgs: IPluginArgs = { @@ -115,4 +119,6 @@ export const DefaultPluginArgs: IPluginArgs = { liveStreaming: true, wdaBundleId: '', preBuildWDAPath: '', + androidCleanUpApps: [], + iosCleanUpApps: [], }; diff --git a/src/modules b/src/modules index e5fe152f2..c1aeb8899 160000 --- a/src/modules +++ b/src/modules @@ -1 +1 @@ -Subproject commit e5fe152f2fe7164455e7967b92ba57dd931d4351 +Subproject commit c1aeb8899a6c834d262966e7fff211e9dab8f858 diff --git a/src/plugin.ts b/src/plugin.ts index c77e65c49..e9ab73133 100644 --- a/src/plugin.ts +++ b/src/plugin.ts @@ -18,7 +18,7 @@ import { addNewPendingSession, removePendingSession, } from './data-service/pending-sessions-service'; -import { DeviceFarmManager } from './device-managers'; +import { AndroidDeviceManager, DeviceFarmManager, IOSDeviceManager } from './device-managers'; import ChromeDriverManager from './device-managers/ChromeDriverManager'; import { allocateDeviceForSession, @@ -56,7 +56,6 @@ import _ from 'lodash'; import { DeviceFarmApiClient } from './api-client'; import { getDeviceFarmCapabilities } from './CapabilityManager'; import { config, config as pluginConfig } from './config'; -import { getFreePort, releasePorts } from './helpers'; import { ATDRepository } from './data-service/db'; import { NodeService } from './data-service/node-service'; import { addCLIArgs } from './data-service/pluginArgs'; @@ -68,6 +67,7 @@ import { AfterSessionDeletedEvent } from './events/after-session-deleted-event'; import { BeforeSessionCreatedEvent } from './events/before-session-create-event'; import { SessionCreatedEvent } from './events/session-created-event'; import { UnexpectedServerShutdownEvent } from './events/unexpected-server-shutdown-event'; +import { getFreePort, releasePorts } from './helpers'; import { IDeviceFilterOptions } from './interfaces/IDeviceFilterOptions'; import { DefaultPluginArgs, IPluginArgs } from './interfaces/IPluginArgs'; import { DEVICE_CONNECTIONS_FACTORY } from './iProxy'; @@ -460,6 +460,7 @@ class DevicePlugin extends BasePlugin { lastname: user.lastname, } : undefined, + deviceFarmCapabilities, }); if (isRemoteOrCloudSession) { addProxyHandler(sessionId, device.host); @@ -755,6 +756,51 @@ class DevicePlugin extends BasePlugin { } } + if (device) { + log.info(`📱 Cleanup: Device found: ${device.udid}`); + const deviceFarmManager = Container.get(DeviceFarmManager); + const deviceManagers = await deviceFarmManager.deviceInstances(); + log.info( + `📱 Cleanup: Loaded managers: ${deviceManagers.map((m) => m.constructor.name).join(', ')}`, + ); + + if (device.platform.toLowerCase() === 'android') { + const androidApps = + device.deviceFarmCapabilities?.androidCleanUpApps || this.pluginArgs.androidCleanUpApps; + log.info(`📱 Cleanup: Android apps to cleanup: ${JSON.stringify(androidApps)}`); + if (androidApps && androidApps.length > 0) { + const androidManager = deviceManagers.find((m) => m instanceof AndroidDeviceManager); + if (androidManager) { + if (androidManager.uninstallApp) { + for (const app of androidApps) { + await androidManager.uninstallApp(device, app); + } + } + } else { + log.warn(`📱 Cleanup: AndroidManager not found in device managers.`); + } + } + } else if (device.platform.toLowerCase() === 'ios') { + const iosApps = + device.deviceFarmCapabilities?.iosCleanUpApps || this.pluginArgs.iosCleanUpApps; + log.info(`📱 Cleanup: iOS apps to cleanup: ${JSON.stringify(iosApps)}`); + if (iosApps && iosApps.length > 0) { + const iosManager = deviceManagers.find((m) => m instanceof IOSDeviceManager); + if (iosManager) { + if (iosManager.uninstallApp) { + for (const app of iosApps) { + await iosManager.uninstallApp(device, app); + } + } + } else { + log.warn(`📱 Cleanup: IOSDeviceManager not found in device managers.`); + } + } + } + } else { + log.info(`📱 Cleanup: No device found for session ${sessionId}`); + } + // Release all collected ports const validPorts = portsToRelease.filter((p) => p !== null && p !== undefined); if (validPorts.length > 0) { diff --git a/test/e2e/android/conf.spec.js b/test/e2e/android/conf.spec.js index ba02d2d34..5b930eede 100644 --- a/test/e2e/android/conf.spec.js +++ b/test/e2e/android/conf.spec.js @@ -1,7 +1,7 @@ import { remote } from 'webdriverio'; const APPIUM_HOST = '127.0.0.1'; -const APPIUM_PORT = 31337; +const APPIUM_PORT = 4723; const WDIO_PARAMS = { connectionRetryCount: 0, hostname: APPIUM_HOST,