feat: Remove @appium/doctor from the monorepo (#20805)

This commit is contained in:
Mykola Mokhnach
2024-12-04 08:31:32 +01:00
committed by GitHub
parent 16c3ae25ea
commit 9a3f990739
39 changed files with 32 additions and 4258 deletions

View File

@@ -23,8 +23,6 @@ targets:
path: ./packages/appium
- type: npm
path: ./packages/base-driver
- type: npm
path: ./packages/doctor
- type: npm
path: ./packages/eslint-config-appium
- type: npm

5
.github/labeler.yml vendored
View File

@@ -53,11 +53,6 @@ labels:
matcher:
files: ['packages/base-plugin/**']
- label: '@appium/doctor'
sync: true
matcher:
files: ['packages/doctor/**']
- label: '@appium/docutils'
sync: true
matcher:

420
package-lock.json generated
View File

@@ -102,10 +102,6 @@
"resolved": "packages/base-plugin",
"link": true
},
"node_modules/@appium/doctor": {
"resolved": "packages/doctor",
"link": true
},
"node_modules/@appium/docutils": {
"resolved": "packages/docutils",
"link": true
@@ -252,19 +248,6 @@
"kuler": "^2.0.0"
}
},
"node_modules/@devicefarmer/adbkit-apkreader": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/@devicefarmer/adbkit-apkreader/-/adbkit-apkreader-3.2.4.tgz",
"integrity": "sha512-WtVmPuirX3/lBN9Z2AC/4DnK7XrXcMi0h3yhxNogxgp6+GVbO6W4RqmuCKlNm1PjyI2GRbw4XwGRQ8cR/IRN6A==",
"dependencies": {
"bluebird": "^3.4.7",
"debug": "~4.3.1",
"yauzl": "^2.7.0"
},
"engines": {
"node": ">= 4"
}
},
"node_modules/@emnapi/runtime": {
"version": "0.44.0",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-0.44.0.tgz",
@@ -1274,17 +1257,6 @@
"uuid": "dist/bin/uuid"
}
},
"node_modules/@ljharb/through": {
"version": "2.3.11",
"resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.11.tgz",
"integrity": "sha512-ccfcIDlogiXNq5KcbAwbaO7lMh3Tm1i3khMPYpxlK8hH/W53zN81KM9coerRLOnTGu3nfXIniAmQbRI9OxbC0w==",
"dependencies": {
"call-bind": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"license": "MIT",
@@ -4076,6 +4048,7 @@
},
"node_modules/ansi-escapes": {
"version": "4.3.2",
"dev": true,
"license": "MIT",
"dependencies": {
"type-fest": "^0.21.3"
@@ -4089,6 +4062,7 @@
},
"node_modules/ansi-escapes/node_modules/type-fest": {
"version": "0.21.3",
"dev": true,
"license": "(MIT OR CC0-1.0)",
"engines": {
"node": ">=10"
@@ -5224,6 +5198,7 @@
},
"node_modules/chardet": {
"version": "0.7.0",
"dev": true,
"license": "MIT"
},
"node_modules/check-error": {
@@ -8192,6 +8167,7 @@
},
"node_modules/external-editor": {
"version": "3.1.0",
"dev": true,
"license": "MIT",
"dependencies": {
"chardet": "^0.7.0",
@@ -9838,14 +9814,6 @@
"version": "2.0.4",
"license": "ISC"
},
"node_modules/ini": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz",
"integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==",
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/init-package-json": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-6.0.3.tgz",
@@ -14003,6 +13971,7 @@
},
"node_modules/os-tmpdir": {
"version": "1.0.2",
"dev": true,
"license": "MIT",
"engines": {
"node": ">=0.10.0"
@@ -16938,6 +16907,7 @@
},
"node_modules/tmp": {
"version": "0.0.33",
"dev": true,
"license": "MIT",
"dependencies": {
"os-tmpdir": "~1.0.2"
@@ -19136,209 +19106,6 @@
"npm": ">=8"
}
},
"packages/doctor": {
"name": "@appium/doctor",
"version": "2.1.15",
"license": "Apache-2.0",
"dependencies": {
"@appium/support": "^5.1.8",
"@colors/colors": "1.6.0",
"@types/bluebird": "3.5.42",
"@types/teen_process": "2.0.4",
"appium-adb": "12.7.0",
"bluebird": "3.7.2",
"inquirer": "9.2.12",
"lodash": "4.17.21",
"source-map-support": "0.5.21",
"teen_process": "2.2.0",
"yargs": "17.7.2"
},
"bin": {
"appium-doctor": "appium-doctor.js"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0",
"npm": ">=8"
}
},
"packages/doctor/node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"packages/doctor/node_modules/appium-adb": {
"version": "12.0.3",
"resolved": "https://registry.npmjs.org/appium-adb/-/appium-adb-12.0.3.tgz",
"integrity": "sha512-wQ4Zi75lIpQF8Xvh9BW3e87diKiF0Hlgc9yCdS9GyRg2rMUfHA8hOV1JzgpyCYcNAP+nLrZoLDztDvg4Qjnjlg==",
"dependencies": {
"@appium/support": "^4.0.0",
"@devicefarmer/adbkit-apkreader": "^3.2.4",
"async-lock": "^1.0.0",
"asyncbox": "^3.0.0",
"bluebird": "^3.4.7",
"ini": "^4.1.1",
"lodash": "^4.0.0",
"lru-cache": "^10.0.0",
"semver": "^7.0.0",
"source-map-support": "^0.x",
"teen_process": "^2.0.1"
},
"engines": {
"node": ">=14",
"npm": ">=8"
}
},
"packages/doctor/node_modules/chalk": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
"integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==",
"engines": {
"node": "^12.17.0 || ^14.13 || >=16.0.0"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"packages/doctor/node_modules/cli-width": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz",
"integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==",
"engines": {
"node": ">= 12"
}
},
"packages/doctor/node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"packages/doctor/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"packages/doctor/node_modules/escape-string-regexp": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
"integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"packages/doctor/node_modules/figures": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz",
"integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==",
"dependencies": {
"escape-string-regexp": "^5.0.0",
"is-unicode-supported": "^1.2.0"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"packages/doctor/node_modules/inquirer": {
"version": "9.2.12",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.12.tgz",
"integrity": "sha512-mg3Fh9g2zfuVWJn6lhST0O7x4n03k7G8Tx5nvikJkbq8/CK47WDVm+UznF0G6s5Zi0KcyUisr6DU8T67N5U+1Q==",
"dependencies": {
"@ljharb/through": "^2.3.11",
"ansi-escapes": "^4.3.2",
"chalk": "^5.3.0",
"cli-cursor": "^3.1.0",
"cli-width": "^4.1.0",
"external-editor": "^3.1.0",
"figures": "^5.0.0",
"lodash": "^4.17.21",
"mute-stream": "1.0.0",
"ora": "^5.4.1",
"run-async": "^3.0.0",
"rxjs": "^7.8.1",
"string-width": "^4.2.3",
"strip-ansi": "^6.0.1",
"wrap-ansi": "^6.2.0"
},
"engines": {
"node": ">=14.18.0"
}
},
"packages/doctor/node_modules/is-unicode-supported": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz",
"integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"packages/doctor/node_modules/lru-cache": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz",
"integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==",
"engines": {
"node": "14 || >=16.14"
}
},
"packages/doctor/node_modules/mute-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz",
"integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==",
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"packages/doctor/node_modules/run-async": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz",
"integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==",
"engines": {
"node": ">=0.12.0"
}
},
"packages/doctor/node_modules/rxjs": {
"version": "7.8.1",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
"integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
"dependencies": {
"tslib": "^2.1.0"
}
},
"packages/doctor/node_modules/wrap-ansi": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": ">=8"
}
},
"packages/docutils": {
"name": "@appium/docutils",
"version": "1.0.25",
@@ -20329,146 +20096,6 @@
"@appium/support": "^5.1.8"
}
},
"@appium/doctor": {
"version": "file:packages/doctor",
"requires": {
"@appium/support": "^5.1.8",
"@colors/colors": "1.6.0",
"@types/bluebird": "3.5.42",
"@types/teen_process": "2.0.4",
"appium-adb": "12.7.0",
"bluebird": "3.7.2",
"inquirer": "9.2.12",
"lodash": "4.17.21",
"source-map-support": "0.5.21",
"teen_process": "2.2.0",
"yargs": "17.7.2"
},
"dependencies": {
"ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"requires": {
"color-convert": "^2.0.1"
}
},
"appium-adb": {
"version": "https://registry.npmjs.org/appium-adb/-/appium-adb-12.0.3.tgz",
"integrity": "sha512-wQ4Zi75lIpQF8Xvh9BW3e87diKiF0Hlgc9yCdS9GyRg2rMUfHA8hOV1JzgpyCYcNAP+nLrZoLDztDvg4Qjnjlg==",
"requires": {
"@appium/support": "^4.0.0",
"@devicefarmer/adbkit-apkreader": "^3.2.4",
"async-lock": "^1.0.0",
"asyncbox": "^3.0.0",
"bluebird": "^3.4.7",
"ini": "^4.1.1",
"lodash": "^4.0.0",
"lru-cache": "^10.0.0",
"semver": "^7.0.0",
"source-map-support": "^0.x",
"teen_process": "^2.0.1"
}
},
"chalk": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz",
"integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w=="
},
"cli-width": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz",
"integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ=="
},
"color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"requires": {
"color-name": "~1.1.4"
}
},
"color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"escape-string-regexp": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
"integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw=="
},
"figures": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz",
"integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==",
"requires": {
"escape-string-regexp": "^5.0.0",
"is-unicode-supported": "^1.2.0"
}
},
"inquirer": {
"version": "9.2.12",
"resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.12.tgz",
"integrity": "sha512-mg3Fh9g2zfuVWJn6lhST0O7x4n03k7G8Tx5nvikJkbq8/CK47WDVm+UznF0G6s5Zi0KcyUisr6DU8T67N5U+1Q==",
"requires": {
"@ljharb/through": "^2.3.11",
"ansi-escapes": "^4.3.2",
"chalk": "^5.3.0",
"cli-cursor": "^3.1.0",
"cli-width": "^4.1.0",
"external-editor": "^3.1.0",
"figures": "^5.0.0",
"lodash": "^4.17.21",
"mute-stream": "1.0.0",
"ora": "^5.4.1",
"run-async": "^3.0.0",
"rxjs": "^7.8.1",
"string-width": "^4.2.3",
"strip-ansi": "^6.0.1",
"wrap-ansi": "^6.2.0"
}
},
"is-unicode-supported": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz",
"integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ=="
},
"lru-cache": {
"version": "10.2.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz",
"integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q=="
},
"mute-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz",
"integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA=="
},
"run-async": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz",
"integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q=="
},
"rxjs": {
"version": "7.8.1",
"resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz",
"integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==",
"requires": {
"tslib": "^2.1.0"
}
},
"wrap-ansi": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
"requires": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
}
}
}
},
"@appium/docutils": {
"version": "file:packages/docutils",
"requires": {
@@ -21107,16 +20734,6 @@
"kuler": "^2.0.0"
}
},
"@devicefarmer/adbkit-apkreader": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/@devicefarmer/adbkit-apkreader/-/adbkit-apkreader-3.2.4.tgz",
"integrity": "sha512-WtVmPuirX3/lBN9Z2AC/4DnK7XrXcMi0h3yhxNogxgp6+GVbO6W4RqmuCKlNm1PjyI2GRbw4XwGRQ8cR/IRN6A==",
"requires": {
"bluebird": "^3.4.7",
"debug": "~4.3.1",
"yauzl": "^2.7.0"
}
},
"@emnapi/runtime": {
"version": "0.44.0",
"resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-0.44.0.tgz",
@@ -21668,14 +21285,6 @@
}
}
},
"@ljharb/through": {
"version": "2.3.11",
"resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.11.tgz",
"integrity": "sha512-ccfcIDlogiXNq5KcbAwbaO7lMh3Tm1i3khMPYpxlK8hH/W53zN81KM9coerRLOnTGu3nfXIniAmQbRI9OxbC0w==",
"requires": {
"call-bind": "^1.0.2"
}
},
"@nodelib/fs.scandir": {
"version": "2.1.5",
"requires": {
@@ -23669,12 +23278,14 @@
},
"ansi-escapes": {
"version": "4.3.2",
"dev": true,
"requires": {
"type-fest": "^0.21.3"
},
"dependencies": {
"type-fest": {
"version": "0.21.3"
"version": "0.21.3",
"dev": true
}
}
},
@@ -24526,7 +24137,8 @@
}
},
"chardet": {
"version": "0.7.0"
"version": "0.7.0",
"dev": true
},
"check-error": {
"version": "2.1.1",
@@ -26524,6 +26136,7 @@
},
"external-editor": {
"version": "3.1.0",
"dev": true,
"requires": {
"chardet": "^0.7.0",
"iconv-lite": "^0.4.24",
@@ -27630,11 +27243,6 @@
"inherits": {
"version": "2.0.4"
},
"ini": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz",
"integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g=="
},
"init-package-json": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/init-package-json/-/init-package-json-6.0.3.tgz",
@@ -30471,7 +30079,8 @@
"dev": true
},
"os-tmpdir": {
"version": "1.0.2"
"version": "1.0.2",
"dev": true
},
"p-cancelable": {
"version": "3.0.0",
@@ -32432,6 +32041,7 @@
},
"tmp": {
"version": "0.0.33",
"dev": true,
"requires": {
"os-tmpdir": "~1.0.2"
}

View File

@@ -43,7 +43,7 @@
"docs": "npm run -w packages/appium build:docs",
"docs:preview": "npm run -w packages/appium build:docs:preview",
"docs:publish": "npm run -w packages/appium publish:docs",
"doctor": "node ./packages/doctor",
"doctor": "node ./scripts/doctor-stub.mjs",
"install-docs-deps": "npm run -w packages/appium install-docs-deps",
"lint": "eslint .",
"lint:ci": "eslint --quiet .",

View File

@@ -1,702 +0,0 @@
# Change Log
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
## [2.1.15](https://github.com/appium/appium/compare/@appium/doctor@2.1.14...@appium/doctor@2.1.15) (2024-12-02)
**Note:** Version bump only for package @appium/doctor
## [2.1.14](https://github.com/appium/appium/compare/@appium/doctor@2.1.13...@appium/doctor@2.1.14) (2024-11-29)
### Bug Fixes
* **doctor:** update dependency appium-adb to v12.6.1 ([7e19c88](https://github.com/appium/appium/commit/7e19c88b79ea8c79489db54fcb3d56d9b2ab56dd))
* **doctor:** update dependency appium-adb to v12.6.2 ([#20735](https://github.com/appium/appium/issues/20735)) ([d046657](https://github.com/appium/appium/commit/d04665777a0296e5d5bbc93ddc74329887cf9677))
* **doctor:** update dependency appium-adb to v12.7.0 ([#20738](https://github.com/appium/appium/issues/20738)) ([9d21f56](https://github.com/appium/appium/commit/9d21f56edb4081f09a1255a665e589103fafe781))
## [2.1.13](https://github.com/appium/appium/compare/@appium/doctor@2.1.12...@appium/doctor@2.1.13) (2024-10-24)
**Note:** Version bump only for package @appium/doctor
## [2.1.12](https://github.com/appium/appium/compare/@appium/doctor@2.1.11...@appium/doctor@2.1.12) (2024-10-15)
**Note:** Version bump only for package @appium/doctor
## [2.1.11](https://github.com/appium/appium/compare/@appium/doctor@2.1.10...@appium/doctor@2.1.11) (2024-09-16)
### Bug Fixes
* **doctor:** update dependency appium-adb to v12.5.2 ([db28605](https://github.com/appium/appium/commit/db286055324c980459f12163ec8253c0b90c1754))
* **doctor:** update dependency appium-adb to v12.5.3 ([048ce52](https://github.com/appium/appium/commit/048ce520d83f31ceab393f5fe46588274fd2ef56))
* **doctor:** update dependency appium-adb to v12.6.0 ([42d7ed8](https://github.com/appium/appium/commit/42d7ed8afe199584cb3850b4a5826d0cb1dc8dc2))
## [2.1.10](https://github.com/appium/appium/compare/@appium/doctor@2.1.9...@appium/doctor@2.1.10) (2024-08-07)
### Bug Fixes
* **doctor:** update dependency appium-adb to v12.5.0 ([b7b97a2](https://github.com/appium/appium/commit/b7b97a24d66e5c561b4c9559a4b0aea25503f39a))
* **doctor:** update dependency appium-adb to v12.5.1 ([82b7515](https://github.com/appium/appium/commit/82b7515867c10c20843dd02c37c7a2e9014c3703))
## [2.1.9](https://github.com/appium/appium/compare/@appium/doctor@2.1.8...@appium/doctor@2.1.9) (2024-07-10)
### Bug Fixes
* **doctor:** update dependency appium-adb to v12.4.6 ([5281f5a](https://github.com/appium/appium/commit/5281f5a01a63e12454093cb296286da02adc77ee))
* **doctor:** update dependency appium-adb to v12.4.8 ([177dff4](https://github.com/appium/appium/commit/177dff4f0ed84880ce9df55f94ff62b922a80ae5))
* **support:** update dependency teen_process to v2.1.10 ([86f843b](https://github.com/appium/appium/commit/86f843b9e1fc56576d7a08bf95838a58971e98b3))
* **support:** update dependency teen_process to v2.1.7 ([5226fa8](https://github.com/appium/appium/commit/5226fa897b90e9fec9be3e79a7d48fc7b4e0016d))
* **support:** update dependency teen_process to v2.2.0 ([06607da](https://github.com/appium/appium/commit/06607da92e93d015747fd6d6d5bdabe1b3ac58d2))
## [2.1.8](https://github.com/appium/appium/compare/@appium/doctor@2.1.7...@appium/doctor@2.1.8) (2024-06-28)
**Note:** Version bump only for package @appium/doctor
## [2.1.7](https://github.com/appium/appium/compare/@appium/doctor@2.1.6...@appium/doctor@2.1.7) (2024-06-27)
### Bug Fixes
* **doctor:** update dependency appium-adb to v12.4.3 ([4345a40](https://github.com/appium/appium/commit/4345a40a15d2473bb13524593ab66ff8ae3d8a7e))
* **doctor:** update dependency appium-adb to v12.4.4 ([15234bc](https://github.com/appium/appium/commit/15234bc05502157ebf847856d38e35da4d542df7))
* **support:** update dependency teen_process to v2.1.5 ([bc388db](https://github.com/appium/appium/commit/bc388db1116f411f4b241105f5feae30418c9a27))
* **support:** update dependency teen_process to v2.1.6 ([5412461](https://github.com/appium/appium/commit/541246184dc7521c825ec1902775e681ea6f0db3))
## [2.1.6](https://github.com/appium/appium/compare/@appium/doctor@2.1.5...@appium/doctor@2.1.6) (2024-06-11)
**Note:** Version bump only for package @appium/doctor
## [2.1.5](https://github.com/appium/appium/compare/@appium/doctor@2.1.4...@appium/doctor@2.1.5) (2024-06-11)
**Note:** Version bump only for package @appium/doctor
## [2.1.4](https://github.com/appium/appium/compare/@appium/doctor@2.1.3...@appium/doctor@2.1.4) (2024-06-11)
**Note:** Version bump only for package @appium/doctor
## [2.1.3](https://github.com/appium/appium/compare/@appium/doctor@2.1.2...@appium/doctor@2.1.3) (2024-06-10)
**Note:** Version bump only for package @appium/doctor
## [2.1.2](https://github.com/appium/appium/compare/@appium/doctor@2.1.1...@appium/doctor@2.1.2) (2024-06-06)
**Note:** Version bump only for package @appium/doctor
## [2.1.1](https://github.com/appium/appium/compare/@appium/doctor@2.1.0...@appium/doctor@2.1.1) (2024-06-06)
**Note:** Version bump only for package @appium/doctor
## [2.1.0](https://github.com/appium/appium/compare/@appium/doctor@2.0.37...@appium/doctor@2.1.0) (2024-06-06)
### Features
* **appium:** Replace npmlog with the local fork ([#20190](https://github.com/appium/appium/issues/20190)) ([8915934](https://github.com/appium/appium/commit/8915934270243bfb46c4d104a098ce1cc481b0ff))
### Bug Fixes
* **doctor:** update dependency appium-adb to v12.4.1 ([e3e1757](https://github.com/appium/appium/commit/e3e1757c564cffd467f3e9931f9aaa5a973fa825))
* **doctor:** update dependency appium-adb to v12.4.2 ([bea47aa](https://github.com/appium/appium/commit/bea47aacca1b1a27cce48b027246513e674c2bb7))
* **support:** update dependency teen_process to v2.1.4 ([96a7a3f](https://github.com/appium/appium/commit/96a7a3f23bead7c1d18700550138cd2d70ce5e3c))
## [2.0.37](https://github.com/appium/appium/compare/@appium/doctor@2.0.36...@appium/doctor@2.0.37) (2024-05-27)
### Bug Fixes
* **doctor:** update dependency appium-adb to v12.0.9 ([fd63e9b](https://github.com/appium/appium/commit/fd63e9bdbd0c941453963cfb9636972129a3b57a))
* **doctor:** update dependency appium-adb to v12.2.0 ([e961a9b](https://github.com/appium/appium/commit/e961a9b9c5347ed85317de9bfc5687ad74a711ff))
* **doctor:** update dependency appium-adb to v12.3.2 ([f764c38](https://github.com/appium/appium/commit/f764c38c29c657133dec1ea3f0e3c6c2663ee7df))
* **doctor:** update dependency appium-adb to v12.4.0 ([33be2ee](https://github.com/appium/appium/commit/33be2ee45d725e6a64fc24683dfbcbff29dfbe84))
* **support:** update dependency teen_process to v2.1.3 ([b34ce3c](https://github.com/appium/appium/commit/b34ce3cff0279be5bb5dcb9228f7e058d27a5e72))
## [2.0.36](https://github.com/appium/appium/compare/@appium/doctor@2.0.35...@appium/doctor@2.0.36) (2024-04-21)
**Note:** Version bump only for package @appium/doctor
## [2.0.35](https://github.com/appium/appium/compare/@appium/doctor@2.0.34...@appium/doctor@2.0.35) (2024-04-16)
**Note:** Version bump only for package @appium/doctor
## [2.0.34](https://github.com/appium/appium/compare/@appium/doctor@2.0.33...@appium/doctor@2.0.34) (2024-04-08)
### Bug Fixes
* **doctor:** update dependency appium-adb to v12.0.4 ([df07665](https://github.com/appium/appium/commit/df076655098db68c986079037a794ce3477314bd))
* **doctor:** update dependency appium-adb to v12.0.5 ([a6d49c1](https://github.com/appium/appium/commit/a6d49c1ac84c98ebe085abf32161d2f39c172d5a))
* **doctor:** update dependency appium-adb to v12.0.6 ([26ab0ef](https://github.com/appium/appium/commit/26ab0ef7595580722f9a63a1c1e5c3bbef3b18f1))
* **doctor:** update dependency appium-adb to v12.0.7 ([3936cb4](https://github.com/appium/appium/commit/3936cb43dceb45e1386c9418453a0dd734e32215))
* **doctor:** update dependency appium-adb to v12.0.8 ([1f36882](https://github.com/appium/appium/commit/1f368828e6b3093a7317853e94437bb79955c399))
## [2.0.33](https://github.com/appium/appium/compare/@appium/doctor@2.0.32...@appium/doctor@2.0.33) (2024-02-13)
**Note:** Version bump only for package @appium/doctor
## [2.0.32](https://github.com/appium/appium/compare/@appium/doctor@2.0.31...@appium/doctor@2.0.32) (2024-02-06)
### Bug Fixes
* **doctor:** update dependency appium-adb to v11.1.0 ([cbc1f50](https://github.com/appium/appium/commit/cbc1f500bc0721edcdf7f47af949ae113c038a46))
* **doctor:** update dependency appium-adb to v12 ([#19648](https://github.com/appium/appium/issues/19648)) ([9617974](https://github.com/appium/appium/commit/961797448116b6be7b500a68b4202b969805825c))
* **doctor:** update dependency appium-adb to v12.0.1 ([b85a6b9](https://github.com/appium/appium/commit/b85a6b939f688703522ebb6ddab19aa807c64dbe))
* **doctor:** update dependency appium-adb to v12.0.2 ([5936d53](https://github.com/appium/appium/commit/5936d53d7856e6a2aa31236eaa0ea9afee737c95))
* **doctor:** update dependency appium-adb to v12.0.3 ([#19722](https://github.com/appium/appium/issues/19722)) ([6cd2c54](https://github.com/appium/appium/commit/6cd2c547def390eb5d739d6245fe0bab1f99931a))
## [2.0.31](https://github.com/appium/appium/compare/@appium/doctor@2.0.30...@appium/doctor@2.0.31) (2024-01-03)
### Bug Fixes
* **doctor:** update dependency appium-adb to v11.0.9 ([3465495](https://github.com/appium/appium/commit/34654956a3cd5a76865444ab52bd905543dfcb2c))
## [2.0.30](https://github.com/appium/appium/compare/@appium/doctor@2.0.29...@appium/doctor@2.0.30) (2023-12-18)
### Bug Fixes
* **support:** update dependency teen_process to v2.0.109 ([85dce4a](https://github.com/appium/appium/commit/85dce4a72b21e017b4661ddf997c096817e5fd7f))
* **support:** update dependency teen_process to v2.0.110 ([b602693](https://github.com/appium/appium/commit/b60269371662de4c42ccd7586512c9d685d95d52))
* **support:** update dependency teen_process to v2.0.112 ([#19491](https://github.com/appium/appium/issues/19491)) ([d2d8ea7](https://github.com/appium/appium/commit/d2d8ea7a105eb93f59793fbc4d3438a66a191cd8))
* **support:** update dependency teen_process to v2.1.1 ([b79ed2b](https://github.com/appium/appium/commit/b79ed2bed5329b904b15fa5b1fbde7885087c9ad))
## [2.0.29](https://github.com/appium/appium/compare/@appium/doctor@2.0.28...@appium/doctor@2.0.29) (2023-12-04)
### Bug Fixes
* **doctor:** update dependency appium-adb to v11.0.8 ([610be26](https://github.com/appium/appium/commit/610be26cbb177f4f3b43a9f94166fd832b56476e))
* **support:** update dependency teen_process to v2.0.100 ([e50b53f](https://github.com/appium/appium/commit/e50b53fbea4aa3709adc3df4baf4945124d6a217))
* **support:** update dependency teen_process to v2.0.101 ([b837f8c](https://github.com/appium/appium/commit/b837f8ce14bd48edb6af62bca718a708d2b65f09))
* **support:** update dependency teen_process to v2.0.87 ([4df1712](https://github.com/appium/appium/commit/4df1712d9b0c3155e95e38a1aa552f036d37dcfe))
* **support:** update dependency teen_process to v2.0.89 ([c129111](https://github.com/appium/appium/commit/c1291116989159eb7e08d303354bc00262a9e784))
* **support:** update dependency teen_process to v2.0.91 ([6cedd48](https://github.com/appium/appium/commit/6cedd485d7007455151c6efc03dd6172d4a31259))
* **support:** update teen_process-related packages ([c637b05](https://github.com/appium/appium/commit/c637b052f45e0ae7ce68d29b9739718549302756))
## [2.0.28](https://github.com/appium/appium/compare/@appium/doctor@2.0.27...@appium/doctor@2.0.28) (2023-11-14)
### Bug Fixes
* **doctor:** update dependency appium-adb to v11.0.3 ([ee1df47](https://github.com/appium/appium/commit/ee1df47b172009717b81cce7b3465219791b1f97))
* **doctor:** update dependency appium-adb to v11.0.5 ([#19362](https://github.com/appium/appium/issues/19362)) ([b82f13b](https://github.com/appium/appium/commit/b82f13b893c44bcaf9908a9ebe96d3bb51c1f6b3))
* **doctor:** update dependency appium-adb to v11.0.6 ([c2f543f](https://github.com/appium/appium/commit/c2f543fc1009067141bc6cf50a2d0e47f1a455b2))
* **doctor:** update dependency appium-adb to v11.0.7 ([261cfc8](https://github.com/appium/appium/commit/261cfc8694f9eeab774712e67bbf46e72615efa7))
* **support:** update definitelytyped ([5ae8df3](https://github.com/appium/appium/commit/5ae8df3c36c7f03fbf3420087b532086f6742348))
* **support:** update dependency teen_process to v2.0.57 ([1fbd503](https://github.com/appium/appium/commit/1fbd503a66b965a9b32bbb6702062861a8480333))
* **support:** update dependency teen_process to v2.0.63 ([fa57192](https://github.com/appium/appium/commit/fa571925b7ac980cc99c8d23f659420eacd8546c))
* **support:** update dependency teen_process to v2.0.64 ([332bb59](https://github.com/appium/appium/commit/332bb59ee3fdd14c03f6b3c4fd6587a30319d568))
* **support:** update dependency teen_process to v2.0.66 ([3205b5d](https://github.com/appium/appium/commit/3205b5d06f073f1e5c7735c6e36ad08fdf091182))
* **support:** update dependency teen_process to v2.0.67 ([3b5ae2a](https://github.com/appium/appium/commit/3b5ae2ab17c74c9890b53c081aec146152f11c7a))
* **support:** update dependency teen_process to v2.0.73 ([8e453be](https://github.com/appium/appium/commit/8e453bed3f440c1dcf82f016f7d4431365b9cdff))
* **support:** update dependency teen_process to v2.0.75 ([fbb6fd9](https://github.com/appium/appium/commit/fbb6fd9a2780eb00c15584abeaf644a1fcdecb4d))
* **support:** update teen_process-related packages ([84d96db](https://github.com/appium/appium/commit/84d96dbae45dfe56218d32330f8ff2d26b750fb7))
* **support:** update teen_process-related packages ([3d0b97c](https://github.com/appium/appium/commit/3d0b97cae76c616da0aea5b92cebcd38d59263b7))
## [2.0.27](https://github.com/appium/appium/compare/@appium/doctor@2.0.26...@appium/doctor@2.0.27) (2023-10-19)
### Bug Fixes
* **doctor:** update dependency appium-adb to v11 ([#19321](https://github.com/appium/appium/issues/19321)) ([408885a](https://github.com/appium/appium/commit/408885a5b28f8691dbbb3716f3c1a409d662275b))
* **support:** update definitelytyped ([a306ce7](https://github.com/appium/appium/commit/a306ce741a806d21bc44f3b979803b8af5da99aa))
## [2.0.26](https://github.com/appium/appium/compare/@appium/doctor@2.0.25...@appium/doctor@2.0.26) (2023-10-18)
### Bug Fixes
* **doctor:** update dependency appium-adb to v10 ([#19308](https://github.com/appium/appium/issues/19308)) ([3315671](https://github.com/appium/appium/commit/33156712b142b1cb2ffdcf1cfdf65f5b504e7751))
* **doctor:** update dependency appium-adb to v9.14.10 ([809b2da](https://github.com/appium/appium/commit/809b2daea5304942c849b7015f0a74447fb7b57c))
* **doctor:** update dependency appium-adb to v9.14.11 ([c81e99f](https://github.com/appium/appium/commit/c81e99fd80739d97b3dc2099a43cc66245035bc5))
* **doctor:** update dependency appium-adb to v9.14.12 ([0220a9f](https://github.com/appium/appium/commit/0220a9f8e9a890f84031cfeaea026fceb0a303e9))
* **doctor:** update dependency appium-adb to v9.14.7 ([#19058](https://github.com/appium/appium/issues/19058)) ([f8039a7](https://github.com/appium/appium/commit/f8039a70ca851dcc120a2b217e14e3e3b922ba21))
* **doctor:** update dependency appium-adb to v9.14.9 ([9f700bf](https://github.com/appium/appium/commit/9f700bfdf9e09de3cea9f81029fadef84b8e956b))
* **opencv:** update definitelytyped ([d2a9a99](https://github.com/appium/appium/commit/d2a9a99418af9ce9b569bb9b98ee396faab932bb))
* **support:** update definitelytyped ([b6a76ce](https://github.com/appium/appium/commit/b6a76ce91e2765c22f84e389b93f780e0b4490c0))
* **support:** update dependency @types/teen_process to v2.0.1 ([d2f19aa](https://github.com/appium/appium/commit/d2f19aab935cc6ec00a51f042b5f02674a772198))
* **support:** update dependency teen_process to v2.0.10 ([bc1b56a](https://github.com/appium/appium/commit/bc1b56a3c162ed8686d3d7956c30eb1f7682b1a7))
* **support:** update dependency teen_process to v2.0.12 ([c5d6df7](https://github.com/appium/appium/commit/c5d6df7a000d64e8591a56ce5ef65baa2071a36b))
* **support:** update dependency teen_process to v2.0.13 ([a0c4b84](https://github.com/appium/appium/commit/a0c4b84fb7d3977b7a4ca0a07fadd49ee355791a))
* **support:** update dependency teen_process to v2.0.18 ([ffeebc7](https://github.com/appium/appium/commit/ffeebc74b72e5eadf658325e67708ae6ed5b8346))
* **support:** update dependency teen_process to v2.0.19 ([2ef40fe](https://github.com/appium/appium/commit/2ef40febdc717f54ea618ecfe1058b858fe2daf9))
* **support:** update dependency teen_process to v2.0.23 ([1b0459e](https://github.com/appium/appium/commit/1b0459edd656514d8706aab8e21cd4d40de2ec5d))
* **support:** update dependency teen_process to v2.0.24 ([bc72c66](https://github.com/appium/appium/commit/bc72c6676a5412b60e74bb143a223738ce059977))
* **support:** update dependency teen_process to v2.0.27 ([03b2aa6](https://github.com/appium/appium/commit/03b2aa6b6e45fa0ea24c4691b039255bc4399733))
* **support:** update dependency teen_process to v2.0.30 ([7cdb142](https://github.com/appium/appium/commit/7cdb1429a1104ad3699547f2a2dd9b237135891a))
* **support:** update dependency teen_process to v2.0.34 ([#19218](https://github.com/appium/appium/issues/19218)) ([c28fcef](https://github.com/appium/appium/commit/c28fcefa725fbce5a0464e57946051e3cb023d85))
* **support:** update dependency teen_process to v2.0.37 ([6d894be](https://github.com/appium/appium/commit/6d894bef6f377ebfdffdeb1adde7a72624844414))
* **support:** update dependency teen_process to v2.0.38 ([a32dc11](https://github.com/appium/appium/commit/a32dc1110125d0f1fac9c66c17f1309145a634c7))
* **support:** update dependency teen_process to v2.0.40 ([2837bcd](https://github.com/appium/appium/commit/2837bcdeb19532fe973a2902db5c8d730252d962))
* **support:** update dependency teen_process to v2.0.41 ([1a34396](https://github.com/appium/appium/commit/1a34396339f71d40353d323feaf78afcf2269fc9))
* **support:** update dependency teen_process to v2.0.42 ([e2a670e](https://github.com/appium/appium/commit/e2a670e1c4a0f061b0bfb08a6b534d9deb7bdd9c))
* **support:** update dependency teen_process to v2.0.45 ([ea731bf](https://github.com/appium/appium/commit/ea731bf117d680496fce453ac42cfee7f05ada60))
* **support:** update dependency teen_process to v2.0.48 ([eebc651](https://github.com/appium/appium/commit/eebc651f31c282baa7e77a6384d3ee8efc0072d6))
* **support:** update dependency teen_process to v2.0.50 ([ca3e5d9](https://github.com/appium/appium/commit/ca3e5d90e4c51fc1dda32154e1d77e65cb44fb54))
* **support:** update dependency teen_process to v2.0.9 ([6c7f3ef](https://github.com/appium/appium/commit/6c7f3ef670d441bdc4b693948a19dcbdc54e4764))
## [2.0.25](https://github.com/appium/appium/compare/@appium/doctor@2.0.24...@appium/doctor@2.0.25) (2023-08-22)
**Note:** Version bump only for package @appium/doctor
## [2.0.24](https://github.com/appium/appium/compare/@appium/doctor@2.0.23...@appium/doctor@2.0.24) (2023-08-21)
### Bug Fixes
* **doctor:** update dependency appium-adb to v9.14.5 ([d5f3a28](https://github.com/appium/appium/commit/d5f3a288c2497d4020b7eabc667814744e69ac48))
## [2.0.23](https://github.com/appium/appium/compare/@appium/doctor@2.0.22...@appium/doctor@2.0.23) (2023-08-17)
### Bug Fixes
* **doctor:** update dependency appium-adb to v9.14.4 ([#18844](https://github.com/appium/appium/issues/18844)) ([a9e86aa](https://github.com/appium/appium/commit/a9e86aabc657bf22df8b1c5f67ab93acc0ced934))
* **doctor:** update dependency inquirer to v8.2.6 ([#18940](https://github.com/appium/appium/issues/18940)) ([a8cc551](https://github.com/appium/appium/commit/a8cc551210c31b014025f7c56b091163f4d15df1))
* **test-support:** update dependency @colors/colors to v1.6.0 ([1358937](https://github.com/appium/appium/commit/1358937db2edf08ce1ebe3dff2f70ac6b07cd373))
## [2.0.22](https://github.com/appium/appium/compare/@appium/doctor@2.0.21...@appium/doctor@2.0.22) (2023-07-24)
### Bug Fixes
* **support:** update dependency teen_process to v2.0.4 ([151c19c](https://github.com/appium/appium/commit/151c19c1c3b4c9b94aba10033c2d863f567d849b))
## [2.0.21](https://github.com/appium/appium/compare/@appium/doctor@2.0.20...@appium/doctor@2.0.21) (2023-07-03)
### Bug Fixes
* **doctor:** update dependency appium-adb to v9.11.7 ([fdd2ac0](https://github.com/appium/appium/commit/fdd2ac098d1b6e0d17b1429defa0123660d85ca9))
## [2.0.20](https://github.com/appium/appium/compare/@appium/doctor@2.0.19...@appium/doctor@2.0.20) (2023-06-29)
**Note:** Version bump only for package @appium/doctor
## [2.0.19](https://github.com/appium/appium/compare/@appium/doctor@2.0.18...@appium/doctor@2.0.19) (2023-06-15)
**Note:** Version bump only for package @appium/doctor
## [2.0.18](https://github.com/appium/appium/compare/@appium/doctor@2.0.17...@appium/doctor@2.0.18) (2023-06-14)
**Note:** Version bump only for package @appium/doctor
## [2.0.17](https://github.com/appium/appium/compare/@appium/doctor@2.0.16...@appium/doctor@2.0.17) (2023-06-14)
### Bug Fixes
* **doctor:** update dependency appium-adb to v9.11.3 ([a0b434d](https://github.com/appium/appium/commit/a0b434dff7a4e425f66915e12266a6e943d10372))
* **doctor:** update dependency appium-adb to v9.11.4 ([f34c75c](https://github.com/appium/appium/commit/f34c75c65068a299ab4d3427233e771e796fc43a))
* **doctor:** update dependency appium-adb to v9.11.5 ([78c6794](https://github.com/appium/appium/commit/78c67942534705133093aa9fa54d84efb9fe2f69))
## [2.0.16](https://github.com/appium/appium/compare/@appium/doctor@2.0.15...@appium/doctor@2.0.16) (2023-05-19)
**Note:** Version bump only for package @appium/doctor
## [2.0.15](https://github.com/appium/appium/compare/@appium/doctor@2.0.14...@appium/doctor@2.0.15) (2023-05-17)
### Bug Fixes
* **doctor:** update dependency appium-adb to v9.11.2 ([e7df6fd](https://github.com/appium/appium/commit/e7df6fd4f054d6ad6eb4125f77e7e0d58bc05ebf))
* **docutils:** update dependency yargs to v17.7.2 ([3d1e4af](https://github.com/appium/appium/commit/3d1e4af858ea21bcf3ab1e1015aa7bdf1776f3ce))
## [2.0.14](https://github.com/appium/appium/compare/@appium/doctor@2.0.13...@appium/doctor@2.0.14) (2023-04-20)
### Bug Fixes
* **doctor:** update dependency appium-adb to v9.11.1 ([45cd434](https://github.com/appium/appium/commit/45cd43488ce3e7a3c32864912d8fb104934f90d8))
## [2.0.13](https://github.com/appium/appium/compare/@appium/doctor@2.0.12...@appium/doctor@2.0.13) (2023-04-14)
**Note:** Version bump only for package @appium/doctor
## [2.0.12](https://github.com/appium/appium/compare/@appium/doctor@2.0.11...@appium/doctor@2.0.12) (2023-04-10)
**Note:** Version bump only for package @appium/doctor
## [2.0.11](https://github.com/appium/appium/compare/@appium/doctor@2.0.10...@appium/doctor@2.0.11) (2023-04-03)
### Bug Fixes
* **doctor:** update dependency appium-adb to v9.11.0 ([d8b6334](https://github.com/appium/appium/commit/d8b633406a68e88cdd945906dde3f23a2a566a71))
## [2.0.10](https://github.com/appium/appium/compare/@appium/doctor@2.0.9...@appium/doctor@2.0.10) (2023-03-28)
**Note:** Version bump only for package @appium/doctor
## [2.0.9](https://github.com/appium/appium/compare/@appium/doctor@2.0.8...@appium/doctor@2.0.9) (2023-03-08)
**Note:** Version bump only for package @appium/doctor
## [2.0.8](https://github.com/appium/appium/compare/@appium/doctor@2.0.7...@appium/doctor@2.0.8) (2023-02-24)
### Bug Fixes
* **docutils:** update dependency yargs to v17.7.0 ([70d65b7](https://github.com/appium/appium/commit/70d65b7d6230dd415f26aaba6d097a3cbe876b47))
* **docutils:** update dependency yargs to v17.7.1 ([2602016](https://github.com/appium/appium/commit/2602016eb38c73d2d9a40f94e95277faf2444305))
## [2.0.7](https://github.com/appium/appium/compare/@appium/doctor@2.0.6...@appium/doctor@2.0.7) (2023-02-09)
**Note:** Version bump only for package @appium/doctor
## [2.0.6](https://github.com/appium/appium/compare/@appium/doctor@2.0.5...@appium/doctor@2.0.6) (2023-01-23)
### Bug Fixes
* **doctor:** update dependency appium-adb to v9.10.22 ([3b213d4](https://github.com/appium/appium/commit/3b213d40e72ccec850f5efb48777b0aee2918cc4))
* **doctor:** update dependency appium-adb to v9.10.23 ([34081b4](https://github.com/appium/appium/commit/34081b44c88a4b2d820eed864c1e9ab36c217d2c))
* **doctor:** update dependency appium-adb to v9.10.24 ([f76a5a7](https://github.com/appium/appium/commit/f76a5a71c96cddac5ad8b8f12d2c03270a28e330))
## [2.0.5](https://github.com/appium/appium/compare/@appium/doctor@2.0.4...@appium/doctor@2.0.5) (2023-01-13)
**Note:** Version bump only for package @appium/doctor
## [2.0.4](https://github.com/appium/appium/compare/@appium/doctor@2.0.3...@appium/doctor@2.0.4) (2023-01-13)
**Note:** Version bump only for package @appium/doctor
## [2.0.3](https://github.com/appium/appium/compare/@appium/doctor@2.0.2...@appium/doctor@2.0.3) (2023-01-13)
**Note:** Version bump only for package @appium/doctor
## [2.0.2](https://github.com/appium/appium/compare/@appium/doctor@2.0.1...@appium/doctor@2.0.2) (2023-01-13)
### Bug Fixes
* **doctor:** update dependency appium-adb to v9.10.20 ([29bf77c](https://github.com/appium/appium/commit/29bf77cf5a623c7417d9c996814498f76cead2a3))
* **doctor:** update dependency appium-adb to v9.10.21 ([ac2c735](https://github.com/appium/appium/commit/ac2c73596810919dcd1c6d294e8c9496eb91e0b9))
## [2.0.1](https://github.com/appium/appium/compare/@appium/doctor@2.0.0...@appium/doctor@2.0.1) (2022-12-21)
### Bug Fixes
- **doctor:** update dependency appium-adb to v9.10.19 ([2cb1af4](https://github.com/appium/appium/commit/2cb1af4357e0e867c28c7045825140d45fa02393))
# [2.0.0](https://github.com/appium/appium/compare/@appium/doctor@1.16.28...@appium/doctor@2.0.0) (2022-12-14)
### Bug Fixes
- **doctor:** update dependency appium-adb to v9.10.16 ([b3e8b47](https://github.com/appium/appium/commit/b3e8b470895e09d8933ad5c10dbbe17c3ad34941))
- **doctor:** update dependency appium-adb to v9.10.17 ([3e815d2](https://github.com/appium/appium/commit/3e815d2a358720fec3b072d92f125dad47be5ca0))
- **doctor:** update dependency appium-adb to v9.10.18 ([8a285cd](https://github.com/appium/appium/commit/8a285cdeceb044d88f657ccd4d5e6939bb15f4eb))
- **doctor:** update dependency inquirer to v8 ([4dd2a46](https://github.com/appium/appium/commit/4dd2a46338a0fb26421c39418c5e20282a400eb3))
- **gulp-plugins:** update dependency yargs to v17.6.1 ([ea1b6a3](https://github.com/appium/appium/commit/ea1b6a3334ee5330abd456a7d4467fc92d94270d))
- **gulp-plugins:** update dependency yargs to v17.6.2 ([a95b2e0](https://github.com/appium/appium/commit/a95b2e0fe6fc646ad5e1fb3479b448ad3a66c880))
- **opencv:** update definitelytyped ([32557f4](https://github.com/appium/appium/commit/32557f4bca5acc2f89cfd3a70f369cebeb94c588))
- chore!: set engines to minimum Node.js v14.17.0 ([a1dbe6c](https://github.com/appium/appium/commit/a1dbe6c43efe76604943a607d402f4c8b864d652))
### Features
- **doctor:** print APPIUM_HOME ([#17625](https://github.com/appium/appium/issues/17625)) ([22d5b2f](https://github.com/appium/appium/commit/22d5b2fd9e0b1f65d5cb78b4dcd45b095537cae1))
- experimental support for typedoc generation ([4746080](https://github.com/appium/appium/commit/4746080e54ed8bb494cbc7c6ce83db503bf6bb52))
### BREAKING CHANGES
- Appium now supports version range `^14.17.0 || ^16.13.0 || >=18.0.0`
## [1.16.28](https://github.com/appium/appium/compare/@appium/doctor@1.16.27...@appium/doctor@1.16.28) (2022-10-14)
**Note:** Version bump only for package @appium/doctor
## [1.16.27](https://github.com/appium/appium/compare/@appium/doctor@1.16.26...@appium/doctor@1.16.27) (2022-10-13)
**Note:** Version bump only for package @appium/doctor
## [1.16.26](https://github.com/appium/appium/compare/@appium/doctor@1.16.25...@appium/doctor@1.16.26) (2022-09-07)
**Note:** Version bump only for package @appium/doctor
## [1.16.25](https://github.com/appium/appium/compare/@appium/doctor@1.16.24...@appium/doctor@1.16.25) (2022-08-10)
**Note:** Version bump only for package @appium/doctor
## [1.16.24](https://github.com/appium/appium/compare/@appium/doctor@1.16.23...@appium/doctor@1.16.24) (2022-08-03)
### Bug Fixes
- **appium,base-driver,base-plugin,doctor,docutils,eslint-config-appium,execute-driver-plugin,fake-driver,fake-plugin,gulp-plugins,images-plugin,opencv,relaxed-caps-plugin,schema,support,test-support,types,universal-xml-plugin:** update engines ([d8d2382](https://github.com/appium/appium/commit/d8d2382327ba7b7db8a4d1cad987c0e60184c92d))
## [1.16.23](https://github.com/appium/appium/compare/@appium/doctor@1.16.22...@appium/doctor@1.16.23) (2022-07-28)
### Bug Fixes
- **doctor:** actually build bin dir, fix dev script ([10421fa](https://github.com/appium/appium/commit/10421fa5ad8c9d2e5916e5a701fefdeb3f5b9969))
- moved type packages to deps of specific packages ([f9129df](https://github.com/appium/appium/commit/f9129dfee32fcc3f89ffcfa69fb83b7c2419c24f))
## [1.16.22](https://github.com/appium/appium/compare/@appium/doctor@1.16.21...@appium/doctor@1.16.22) (2022-06-04)
**Note:** Version bump only for package @appium/doctor
## [1.16.21](https://github.com/appium/appium/compare/@appium/doctor@1.16.20...@appium/doctor@1.16.21) (2022-05-31)
**Note:** Version bump only for package @appium/doctor
## [1.16.20](https://github.com/appium/appium/compare/@appium/doctor@1.16.19...@appium/doctor@1.16.20) (2022-05-31)
### Bug Fixes
- **appium:** fix extension autoinstall postinstall script ([3e2c05d](https://github.com/appium/appium/commit/3e2c05d8a290072484afde34fe5fd968618f6359)), closes [#16924](https://github.com/appium/appium/issues/16924)
## [1.16.19](https://github.com/appium/appium/compare/@appium/doctor@1.16.18...@appium/doctor@1.16.19) (2022-05-03)
**Note:** Version bump only for package @appium/doctor
## [1.16.18](https://github.com/appium/appium/compare/@appium/doctor@1.16.17...@appium/doctor@1.16.18) (2022-05-02)
**Note:** Version bump only for package @appium/doctor
## [1.16.17](https://github.com/appium/appium/compare/@appium/doctor@1.16.16...@appium/doctor@1.16.17) (2022-04-20)
**Note:** Version bump only for package @appium/doctor
## [1.16.16](https://github.com/appium/appium/compare/@appium/doctor@1.16.15...@appium/doctor@1.16.16) (2022-04-20)
**Note:** Version bump only for package @appium/doctor
## [1.16.15](https://github.com/appium/appium/compare/@appium/doctor@1.16.14...@appium/doctor@1.16.15) (2022-04-20)
**Note:** Version bump only for package @appium/doctor
## [1.16.14](https://github.com/appium/appium/compare/@appium/doctor@1.16.13...@appium/doctor@1.16.14) (2022-04-12)
**Note:** Version bump only for package @appium/doctor
## [1.16.13](https://github.com/appium/appium/compare/@appium/doctor@1.16.12...@appium/doctor@1.16.13) (2022-04-12)
**Note:** Version bump only for package @appium/doctor
## [1.16.12](https://github.com/appium/appium/compare/@appium/doctor@1.16.11...@appium/doctor@1.16.12) (2022-04-07)
**Note:** Version bump only for package @appium/doctor
## [1.16.11](https://github.com/appium/appium/compare/@appium/doctor@1.16.10...@appium/doctor@1.16.11) (2022-03-23)
**Note:** Version bump only for package @appium/doctor
## [1.16.10](https://github.com/appium/appium/compare/@appium/doctor@1.16.9...@appium/doctor@1.16.10) (2022-03-22)
**Note:** Version bump only for package @appium/doctor
## [1.16.9](https://github.com/appium/appium/compare/@appium/doctor@1.16.8...@appium/doctor@1.16.9) (2022-01-21)
**Note:** Version bump only for package @appium/doctor
## [1.16.8](https://github.com/appium/appium/compare/@appium/doctor@1.16.7...@appium/doctor@1.16.8) (2022-01-11)
### Bug Fixes
- **support:** allow @u4/opencv4nodejs in addition to the old one, and promote it in doctor instead ([7d8d547](https://github.com/appium/appium/commit/7d8d547fbd5f234922a38c79239391c83d48aa5b))
- Switch colors package to a non-compomised repository ([#16317](https://github.com/appium/appium/issues/16317)) ([40a6f05](https://github.com/appium/appium/commit/40a6f054dca3d94fc88773af9c6336ba12ebfb81))
## [1.16.7](https://github.com/appium/appium/compare/@appium/doctor@1.16.6...@appium/doctor@1.16.7) (2021-11-19)
### Bug Fixes
- **doctor:** move index to support cjs wrapper ([69820ea](https://github.com/appium/appium/commit/69820eaf9369969ebbad038ca53accf973d18aa4))
## [1.16.6](https://github.com/appium/appium/compare/@appium/doctor@1.16.5...@appium/doctor@1.16.6) (2021-11-15)
**Note:** Version bump only for package @appium/doctor
## [1.16.5](https://github.com/appium/appium/compare/@appium/doctor@1.16.4...@appium/doctor@1.16.5) (2021-11-09)
**Note:** Version bump only for package @appium/doctor
## [1.16.4](https://github.com/appium/appium/compare/@appium/doctor@1.16.3...@appium/doctor@1.16.4) (2021-09-16)
**Note:** Version bump only for package @appium/doctor
## [1.16.3](https://github.com/appium/appium/compare/@appium/doctor@1.16.2...@appium/doctor@1.16.3) (2021-09-14)
**Note:** Version bump only for package @appium/doctor
## [1.16.2](https://github.com/appium/appium/compare/@appium/doctor@1.16.1...@appium/doctor@1.16.2) (2021-09-14)
**Note:** Version bump only for package @appium/doctor
## 1.16.1 (2021-08-16)
# 2.0.0-beta (2021-08-13)
### Bug Fixes
- **doctor:** update reference to @appium/idb README ([c20a13e](https://github.com/appium/appium/commit/c20a13ea95070c1fb705147f65254b50af761b95))
- **doctor:** use @appium/test-support ([80c9919](https://github.com/appium/appium/commit/80c991998540faad464ba764df612a443db35ff2))

View File

@@ -1,39 +0,0 @@
# @appium/doctor
> Attempts to diagnose and fix common Appium configuration issues
[![NPM version](http://img.shields.io/npm/v/@appium/doctor.svg)](https://npmjs.org/package/@appium/doctor)
[![Downloads](http://img.shields.io/npm/dm/@appium/doctor.svg)](https://npmjs.org/package/@appium/doctor)
> [!WARNING]
> This package has been deprecated since the Appium server v 2.4.0 and will be removed in the future.
> Use doctor checks (if any exist) integrated into your installed driver or plugin by
> running `appium driver doctor <driver_name>` or `appium plugin doctor <plugin_name>`.
### Install
```
npm install @appium/doctor -g
```
### Usage
```
➜ appium-doctor -h
Usage: appium-doctor.js [options, defaults: --ios --android]
Options:
--ios Check iOS setup [boolean]
--android Check Android setup [boolean]
--dev Check dev setup [boolean]
--debug Show debug messages [boolean]
--yes Always respond yes [boolean]
--no Always respond no [boolean]
--demo Run appium-doctor demo (for dev). [boolean]
-h, --help Show help [boolean]
```
## License
Apache-2.0

View File

@@ -1,3 +0,0 @@
#!/usr/bin/env node
module.exports = require('./build/bin/appium-doctor');

View File

@@ -1,51 +0,0 @@
// transpile:main
import yargs from 'yargs';
import newDoctor from '../lib/factory';
import {configureBinaryLog} from '../lib/utils';
import {configure as configurePrompt} from '../lib/prompt';
import {system} from '@appium/support';
yargs
.strict()
.usage('Usage: $0 [options, defaults: --ios --android]')
.boolean('ios')
.describe('ios', 'Check iOS setup')
.boolean('android')
.describe('android', 'Check Android setup')
.boolean('dev')
.describe('dev', 'Check dev setup')
.boolean('debug')
.describe('debug', 'Show debug messages')
.boolean('yes')
.describe('yes', 'Always respond yes')
.boolean('no')
.describe('no', 'Always respond no')
.boolean('demo')
.describe('demo', 'Run appium-doctor demo (for dev).')
.help('h')
.alias('h', 'help')
.check(function (argv) {
if (!argv.ios && !argv.android && !argv.demo) {
argv.ios = system.isMac();
argv.android = true;
}
return true;
});
// make sure we use the general checks for every test
let opts = Object.assign(
{
general: true,
},
yargs.argv
);
configurePrompt(opts);
configureBinaryLog(opts);
newDoctor(opts)
.run()
.catch(function (e) {
console.error(e); // eslint-disable-line no-console
process.exit(1);
});

View File

@@ -1,165 +0,0 @@
import {DoctorCheck} from './doctor';
import {ok, nok, okOptional, nokOptional, resolveExecutablePath} from './utils';
import {system, fs} from '@appium/support';
import path from 'path';
import EnvVarAndPathCheck from './env';
import '@colors/colors';
import {getAndroidBinaryPath, getSdkRootFromEnv} from 'appium-adb';
import log from './logger';
/**
* @type {import('./factory').DoctorCheckList}
*/
const checks = [];
const javaHome = system.isWindows() ? '%JAVA_HOME%' : '$JAVA_HOME';
checks.push(new EnvVarAndPathCheck('ANDROID_HOME'));
checks.push(new EnvVarAndPathCheck('JAVA_HOME'));
// Check that the PATH includes the jdk's bin directory
export class JavaOnPathCheck extends DoctorCheck {
/**
* @override
*/
async diagnose() {
if (process.env.JAVA_HOME) {
const javaHomeBin = path.resolve(process.env.JAVA_HOME, 'bin');
return (await fs.exists(javaHomeBin))
? ok(`'bin' subfolder exists under '${process.env.JAVA_HOME}'`)
: nok(
`'bin' subfolder does not exist under '${process.env.JAVA_HOME}'. ` +
`Is ${javaHome} set to a proper value?`
);
}
return nok(
`Cannot check ${javaHome} requirements since the environment variable itself is not set`
);
}
/**
* @override
*/
async fix() {
return `Set ${javaHome} environment variable to the root folder path of your local JDK installation`;
}
}
// Check tools
export class AndroidToolCheck extends DoctorCheck {
constructor() {
super();
this.tools = ['adb', 'emulator', `apkanalyzer${system.isWindows() ? '.bat' : ''}`];
this.noBinaries = [];
}
/**
* @override
*/
async diagnose() {
const listOfTools = this.tools.join(', ');
const sdkRoot = getSdkRootFromEnv();
if (!sdkRoot) {
return nok(
`${listOfTools} could not be found because ANDROID_HOME is NOT set!`
);
}
log.info(` Checking ${listOfTools}`);
for (const binary of this.tools) {
try {
log.info(` '${binary}' is in ${await getAndroidBinaryPath(binary)}`);
} catch (e) {
this.noBinaries.push(binary);
}
}
if (this.noBinaries.length > 0) {
return nok(`${this.noBinaries.join(', ')} could NOT be found in ${sdkRoot}!`);
}
return ok(`${listOfTools} exist: ${sdkRoot}`);
}
/**
* @override
*/
async fix() {
if (typeof process.env.ANDROID_HOME === 'undefined') {
return `Manually configure ${'ANDROID_HOME'.bold} and run appium-doctor again.`;
}
return (
`Manually install ${this.noBinaries.join(', ').bold} and add it to ${'PATH'.bold}. ` +
'https://developer.android.com/studio#cmdline-tools and ' +
'https://developer.android.com/studio/intro/update#sdk-manager may help to setup.'
);
}
}
checks.push(new AndroidToolCheck());
checks.push(new JavaOnPathCheck());
export class OptionalAppBundleCheck extends DoctorCheck {
/**
* @override
*/
async diagnose() {
const bundletoolPath = await resolveExecutablePath('bundletool.jar');
return bundletoolPath
? okOptional(`bundletool.jar is installed at: ${bundletoolPath}`)
: nokOptional('bundletool.jar cannot be found');
}
/**
* @override
*/
async fix() {
return (
`${
'bundletool.jar'.bold
} is used to handle Android App Bundle. Please read http://appium.io/docs/en/writing-running-appium/android/android-appbundle/ to install it` +
`${
system.isWindows()
? '. Also consider adding the ".jar" extension into your PATHEXT environment variable in order to fix the problem for Windows'
: ''
}`
);
}
}
checks.push(new OptionalAppBundleCheck());
export class OptionalGstreamerCheck extends DoctorCheck {
GSTREAMER_BINARY = `gst-launch-1.0${system.isWindows() ? '.exe' : ''}`;
GST_INSPECT_BINARY = `gst-inspect-1.0${system.isWindows() ? '.exe' : ''}`;
/**
* @override
*/
async diagnose() {
const gstreamerPath = await resolveExecutablePath(this.GSTREAMER_BINARY);
const gstInspectPath = await resolveExecutablePath(this.GST_INSPECT_BINARY);
return gstreamerPath && gstInspectPath
? okOptional(
`${this.GSTREAMER_BINARY} and ${this.GST_INSPECT_BINARY} are installed at: ${gstreamerPath} and ${gstInspectPath}`
)
: nokOptional(`${this.GSTREAMER_BINARY} and/or ${this.GST_INSPECT_BINARY} cannot be found`);
}
/**
* @override
*/
async fix() {
return (
`${
`${this.GSTREAMER_BINARY} and ${this.GST_INSPECT_BINARY}`.bold
} are used to stream the screen of the device under test. ` +
'Please read https://appium.io/docs/en/writing-running-appium/android/android-screen-streaming/ to install them and for more details'
);
}
}
checks.push(new OptionalGstreamerCheck());
export {EnvVarAndPathCheck};
export default checks;

View File

@@ -1,88 +0,0 @@
// demo rule to test the gui
import {ok, nok} from './utils';
import {fs} from '@appium/support';
import {exec} from 'teen_process';
import {DoctorCheck, FixSkippedError} from './doctor';
import log from './logger';
import {fixIt} from './prompt';
/**
* @type {import('./factory').DoctorCheckList}
*/
const checks = [];
export class DirCheck extends DoctorCheck {
/**
* @param {string} path
*/
constructor(path) {
super({autofix: false});
this.path = path;
}
/**
* @override
*/
async diagnose() {
if (!(await fs.exists(this.path))) {
return nok(`Could NOT find directory at '${this.path}'!`);
}
let stats = await fs.lstat(this.path);
return stats.isDirectory()
? ok(`Found directory at: ${this.path}`)
: nok(`'${this.path}' is NOT a directory!`);
}
/**
* @override
*/
async fix() {
return `Manually create a directory at: ${this.path}`;
}
}
checks.push(new DirCheck('/tmp/appium-doctor'));
checks.push(new DirCheck('/tmp/appium-doctor/demo'));
export class FileCheck extends DoctorCheck {
/**
* @param {string} path
*/
constructor(path) {
super({autofix: true});
this.path = path;
}
/**
* @override
*/
async diagnose() {
return (await fs.exists(this.path))
? ok(`Found file at: ${this.path}`)
: nok(`Could NOT find file at '${this.path}'!`);
}
/**
* @override
*/
async fix() {
log.info(`The following command need be executed: touch '${this.path}'`);
let yesno = await fixIt();
if (yesno === 'yes') {
await exec('touch', [this.path]);
} else {
log.info(`Skipping. You will need to touch '${this.path}' manually.`);
throw new FixSkippedError('bbb');
}
return null;
}
}
checks.push(
new FileCheck('/tmp/appium-doctor/demo/apple.fruit'),
new FileCheck('/tmp/appium-doctor/demo/pear.fruit'),
new FileCheck('/tmp/appium-doctor/demo/orange.fruit'),
);
export default checks;

View File

@@ -1,87 +0,0 @@
import {DoctorCheck} from './doctor';
import {ok, nok, resolveExecutablePath} from './utils';
import {fs, system} from '@appium/support';
import path from 'path';
import '@colors/colors';
/**
* @type {import('./factory').DoctorCheckList}
*/
const checks = [];
// Check PATH binaries
export class BinaryIsInPathCheck extends DoctorCheck {
/**
* @param {string} binary
*/
constructor(binary) {
super();
this.binary = binary;
}
/**
* @override
*/
async diagnose() {
const resolvedPath = await resolveExecutablePath(this.binary);
if (!resolvedPath) {
return nok(`${this.binary} is MISSING in PATH: ${process.env.PATH}`);
}
return ok(`${this.binary} was found at ${resolvedPath}`);
}
/**
* @override
*/
async fix() {
return `Manually install the ${this.binary.bold} binary and add it to ${'PATH'.bold}.`;
}
}
checks.push(
new BinaryIsInPathCheck(system.isWindows() ? 'mvn.bat' : 'mvn'),
new BinaryIsInPathCheck(system.isWindows() ? 'ant.bat' : 'ant'),
new BinaryIsInPathCheck(system.isWindows() ? 'adb.exe' : 'adb'),
);
// Check Android SDKs
export class AndroidSdkExists extends DoctorCheck {
/**
* @param {string} sdk
*/
constructor(sdk) {
super();
this.sdk = sdk;
}
/**
* @override
*/
async diagnose() {
if (typeof process.env.ANDROID_HOME === 'undefined') {
return nok(`${this.sdk} could not be found because ANDROID_HOME is NOT set!`);
}
let sdkPath = path.resolve(process.env.ANDROID_HOME, path.join('platforms', this.sdk));
return (await fs.exists(sdkPath))
? ok(`${this.sdk} was found at: ${sdkPath}`)
: nok(`${this.sdk} could NOT be found at '${sdkPath}'!`);
}
/**
* @override
*/
async fix() {
if (typeof process.env.ANDROID_HOME === 'undefined') {
return `Manually configure ${'ANDROID_HOME'.bold}.`;
}
return `Manually install the ${this.sdk.bold} sdk.`;
}
}
checks.push(
new AndroidSdkExists('android-16'),
new AndroidSdkExists('android-19'),
);
export default checks;

View File

@@ -1,284 +0,0 @@
import '@colors/colors';
import _ from 'lodash';
import log from './logger';
import {fs} from '@appium/support';
const {version} = fs.readPackageJsonFrom(__dirname);
class FixSkippedError extends Error {}
/**
* Create interface for other Doctors
*/
class DoctorCheck {
/**
* @param {DoctorOpts} [opts={}]
*/
constructor(opts = {}) {
this.autofix = !!opts.autofix;
}
/**
* Every doctor diagnose the symptoms
* @returns {Promise<import('./utils').CheckResult>}
* @throws {Error}
*/
async diagnose() {
throw new Error('Not Implemented!');
}
/**
* Every doctor suggest the solutions to fix the sickness
* @returns {Promise<string|null>}
* @throws {Error}
*/
async fix() {
// return string for manual fixes.
throw new Error('Not Implemented!');
}
}
class Doctor {
constructor() {
/**
* All the sub check goes here after register
* @type {DoctorCheck[]}
*/
this.checks = [];
/** @type {DoctorCheck[]} */
this.checkOptionals = [];
/** @type {DoctorIssue[]} */
this.toFix = [];
/** @type {DoctorIssue[]} */
this.toFixOptionals = [];
}
/**
* Register all the sub check and combine them together
* @param {DoctorCheck[] | DoctorCheck} checks
*/
register(checks) {
this.checks.push(...(Array.isArray(checks) ? checks : [checks]));
}
/**
* The doctor shows the report
*/
async diagnose() {
log.info(`### Diagnostic for ${'necessary'.green} dependencies starting ###`);
this.toFix = [];
for (const check of this.checks) {
const res = await check.diagnose();
if (res.optional) {
this.checkOptionals.push(check);
continue;
}
await this.diagnosticResultMessage(res, this.toFix, check);
}
log.info(
`### Diagnostic for necessary dependencies completed, ${await this.fixMessage(
this.toFix.length
)}. ###`
);
log.info('');
log.info(`### Diagnostic for ${'optional'.yellow} dependencies starting ###`);
this.toFixOptionals = [];
for (const checkOptional of this.checkOptionals) {
await this.diagnosticResultMessage(
await checkOptional.diagnose(),
this.toFixOptionals,
checkOptional
);
}
log.info(
`### Diagnostic for optional dependencies completed, ${await this.fixMessage(
this.toFixOptionals.length,
true
)}. ###`
);
log.info('');
}
/**
* @param {DoctorIssue[]} fixes
* @param {DoctorIssue[]} optionalFixes
*/
async reportManualFixes(fixes, optionalFixes) {
const manualFixes = _.filter(fixes, (f) => !f?.check?.autofix);
const manualFixesOptional = _.filter(optionalFixes, (f) => !f?.check?.autofix);
if (manualFixes.length > 0) {
log.info('### Manual Fixes Needed ###');
log.info('The configuration cannot be automatically fixed, please do the following first:');
/** @type {string[]} */
const fixMessages = [];
for (const f of manualFixes) {
const message = await f.check.fix();
if (message) {
fixMessages.push(message);
}
}
for (const m of _.uniq(fixMessages)) {
log.warn(` \u279C ${m}`);
}
log.info('');
}
if (manualFixesOptional.length > 0) {
log.info('### Optional Manual Fixes ###');
log.info('The configuration can install optionally. Please do the following manually:');
/** @type {string[]} */
const fixMessages = [];
for (const f of manualFixesOptional) {
const message = await f.check.fix();
if (message) {
fixMessages.push(message);
}
}
for (const m of _.uniq(fixMessages)) {
log.warn(` \u279C ${m}`);
}
log.info('');
}
if (manualFixes.length > 0 || manualFixesOptional.length > 0) {
log.info('###');
log.info('');
log.info('Bye! Run appium-doctor again when all manual fixes have been applied!');
log.info('');
return true;
}
return false;
}
/**
* @param {DoctorIssue} f
*/
async runAutoFix(f) {
log.info(`### Fixing: ${f.error} ###`);
try {
await f.check.fix();
} catch (err) {
if (err instanceof FixSkippedError) {
log.info(`### Skipped fix ###`);
return;
} else {
log.warn(`${err}`.replace(/\n$/g, ''));
log.info(`### Fix did not succeed ###`);
return;
}
}
log.info('Checking if this was fixed:');
const res = await f.check.diagnose();
if (res.ok) {
f.fixed = true;
log.info(` ${'\u2714'.green} ${res.message}`);
log.info(`### Fix was successfully applied ###`);
} else {
log.info(` ${'\u2716'.red} ${res.message}`);
log.info(`### Fix was applied but issue remains ###`);
}
}
async runAutoFixes() {
const autoFixes = _.filter(this.toFix, (f) => f?.check?.autofix);
for (const f of autoFixes) {
await this.runAutoFix(f);
log.info('');
}
if (_.find(autoFixes, (f) => !f.fixed)) {
// a few issues remain.
log.info('Bye! A few issues remain, fix manually and/or rerun appium-doctor!');
} else {
// nothing left to fix.
log.info('Bye! All issues have been fixed!');
}
log.info('');
}
async run() {
log.info(`Appium Doctor v.${version}`);
log.warn(`This package is deprecated since the Appium server version 2.4.0 and will be removed in the future.`);
log.warn(`Use doctor checks (if any exist) integrated into your installed driver or plugin by ` +
`running \`appium driver doctor <driver_name>\` or \`appium plugin doctor <plugin_name>\`.`);
await this.diagnose();
if (await this.reportSuccess(this.toFix.length, this.toFixOptionals.length)) {
return;
}
if (await this.reportManualFixes(this.toFix, this.toFixOptionals)) {
return;
}
await this.runAutoFixes();
}
/**
* Generating messages
*
* @param {import('./utils').CheckResult} result
* @param {DoctorIssue[]} toFixList
* @param {DoctorCheck} check
*/
async diagnosticResultMessage(result, toFixList, check) {
if (result.ok) {
log.info(` ${'\u2714'.green} ${result.message}`);
} else {
const errorMessage = result.optional
? ` ${'\u2716'.yellow} ${result.message}`
: ` ${'\u2716'.red} ${result.message}`;
log.warn(errorMessage);
toFixList.push({
error: errorMessage,
check,
});
}
}
/**
* @param {number} length
* @param {boolean} [optional=false]
* @returns {Promise<string>}
*/
async fixMessage(length, optional = false) {
let message;
switch (length) {
case 0:
message = 'no fix';
break;
case 1:
message = 'one fix';
break;
default:
message = `${length} fixes`;
}
return `${message} ${optional ? 'possible' : 'needed'}`;
}
/**
* @param {number} length
* @param {number} lengthOptional
* @returns {Promise<boolean>}
*/
async reportSuccess(length, lengthOptional) {
if (length === 0 && lengthOptional === 0) {
log.info('Everything looks good, bye!');
log.info('');
return true;
} else {
return false;
}
}
}
export {Doctor, DoctorCheck, FixSkippedError};
/**
* @typedef DoctorOpts
* @property {boolean?} [autofix]
*/
/**
* @typedef DoctorIssue
* @property {DoctorCheck} check
* @property {string} error
* @property {boolean} [fixed]
*/

View File

@@ -1,49 +0,0 @@
import {fs, system} from '@appium/support';
import {DoctorCheck} from './doctor';
import {ok, nok} from './utils';
import '@colors/colors';
// Check env variables
export class EnvVarAndPathCheck extends DoctorCheck {
/**
* @param {string} varName
*/
constructor(varName) {
super();
this.varName = varName;
}
/**
* @override
*/
async diagnose() {
let varValue = process.env[this.varName];
if (typeof varValue === 'undefined') {
return nok(`${this.varName} environment variable is NOT set!`);
}
if (await fs.exists(varValue)) {
return ok(`${this.varName} is set to: ${varValue}`);
}
let err_msg = `${this.varName} is set to '${varValue}' but this is NOT a valid path!`;
// On Windows, when the env var has %LOCALAPPDATA%, fs.exists cannot resolve the path.
// Then, it would be safe to request the user to set the full path instead.
if (system.isWindows() && varValue.includes('%LOCALAPPDATA%')) {
err_msg += ` Please set '${process.env.LOCALAPPDATA}' instead of '%LOCALAPPDATA%' as the environment variable.`;
}
return nok(err_msg);
}
/**
* @override
*/
async fix() {
return (
`Make sure the environment variable ${this.varName.bold} is properly configured for the Appium process. ` +
`Refer https://github.com/appium/java-client/blob/master/docs/environment.md for more details.`
);
}
}
export default EnvVarAndPathCheck;

View File

@@ -1,37 +0,0 @@
import _ from 'lodash';
import {Doctor} from './doctor';
import generalChecks from './general';
import iosChecks from './ios';
import androidChecks from './android';
import devChecks from './dev';
import demoChecks from './demo';
/**
* @type {DoctorGroup}
*/
const checks = {generalChecks, iosChecks, androidChecks, devChecks, demoChecks};
const newDoctor = (/** @type {Record<string, any>} */ opts) => {
const doctor = new Doctor();
for (const [k, v] of _.toPairs(opts)) {
if (v) {
doctor.register(checks[`${k}Checks`] || []);
}
}
return doctor;
};
export default newDoctor;
/**
* @typedef {import('./doctor').DoctorCheck[]} DoctorCheckList
*/
/**
* @typedef DoctorGroup - Contain a group of Doctors
* @property {DoctorCheckList} generalChecks - Check AppiumHome, NodeBinary, NodeVersion, ffmpeg, mjpeg-consumer
* @property {DoctorCheckList} iosChecks - Check if iOS toolchains are installed
* @property {DoctorCheckList} androidChecks - Check if Android toolchains are installed
* @property {DoctorCheckList} devChecks - Check Path Binary and Android SDKs
* @property {DoctorCheckList} demoChecks - Check /tmp/appium-doctor/demo/*
*/

View File

@@ -1,140 +0,0 @@
import {ok, nok, okOptional, nokOptional, resolveExecutablePath, getNpmPackageInfo} from './utils';
import {exec} from 'teen_process';
import {DoctorCheck} from './doctor';
import NodeDetector from './node-detector';
import {util, env} from '@appium/support';
import '@colors/colors';
/**
* @type {import('./factory').DoctorCheckList}
*/
const checks = [];
export class AppiumHomeCheck extends DoctorCheck {
/**
* @override
*/
async diagnose() {
return ok(`APPIUM_HOME is ${await env.resolveAppiumHome()}`);
}
/**
* @override
*/
async fix() {
return null;
}
}
checks.push(new AppiumHomeCheck());
// Node Binary
export class NodeBinaryCheck extends DoctorCheck {
/**
* @override
*/
async diagnose() {
let nodePath = await NodeDetector.detect();
return nodePath
? ok(`The Node.js binary was found at: ${nodePath}`)
: nok('The Node.js binary was NOT found!');
}
/**
* @override
*/
async fix() {
return `Manually setup ${'Node.js'.bold}.`;
}
}
checks.push(new NodeBinaryCheck());
const REQUIRED_NODE_VERSION = '14.0.0';
// Node version
export class NodeVersionCheck extends DoctorCheck {
/**
* @override
*/
async diagnose() {
let nodePath = await NodeDetector.detect();
if (!nodePath) {
return nok('Node is not installed, so no version to check!');
}
let {stdout} = await exec(nodePath, ['--version']);
let versionString = stdout.replace('v', '').trim();
try {
return util.compareVersions(REQUIRED_NODE_VERSION, '<=', versionString)
? ok(`Node version is ${versionString}`)
: nok(`Node version should be at least ${REQUIRED_NODE_VERSION}!`);
} catch {
return nok(`Unable to find node version (version = '${versionString}')`);
}
}
/**
* @override
*/
async fix() {
return `Manually upgrade ${'Node.js'.bold}.`;
}
}
checks.push(new NodeVersionCheck());
export class OptionalFfmpegCommandCheck extends DoctorCheck {
/**
* @override
*/
async diagnose() {
const ffmpegPath = await resolveExecutablePath('ffmpeg');
return ffmpegPath
? okOptional(
`ffmpeg is installed at: ${ffmpegPath}. ${
(await exec('ffmpeg', ['-version'])).stdout.split('\n')[0]
}`
)
: nokOptional('ffmpeg cannot be found');
}
/**
* @override
*/
async fix() {
return `${
'ffmpeg'.bold
} is needed to record screen features. Please read https://www.ffmpeg.org/ to install it`;
}
}
checks.push(new OptionalFfmpegCommandCheck());
export class OptionalMjpegConsumerCommandCheck extends DoctorCheck {
/**
* @override
*/
async diagnose() {
const packageName = 'mjpeg-consumer';
const packageInfo = await getNpmPackageInfo(packageName);
if (packageInfo) {
return okOptional(
`${packageName} is installed at: ${packageInfo.path}. Installed version is: ${packageInfo.version}`
);
}
return nokOptional(`${packageName} cannot be found.`);
}
/**
* @override
*/
async fix() {
return `${
'mjpeg-consumer'.bold
} module is required to use MJPEG-over-HTTP features. Please install it with 'npm i -g mjpeg-consumer'.`;
}
}
checks.push(new OptionalMjpegConsumerCommandCheck());
export default checks;
/**
* @typedef {import('./utils').CheckResult} UtilsResult
*/

View File

@@ -1,4 +0,0 @@
import newDoctor from './factory';
import {Doctor, DoctorCheck} from './doctor';
export {newDoctor, Doctor, DoctorCheck};

View File

@@ -1,224 +0,0 @@
import {ok, nok, okOptional, nokOptional, resolveExecutablePath} from './utils'; // eslint-disable-line
import {fs} from '@appium/support';
import {exec} from 'teen_process';
import {DoctorCheck, FixSkippedError} from './doctor';
import log from './logger';
import {fixIt} from './prompt';
import EnvVarAndPathCheck from './env';
import '@colors/colors';
/**
* @type {import('./factory').DoctorCheckList}
*/
const checks = [];
export const fixes = {};
// Check for Xcode.
export class XcodeCheck extends DoctorCheck {
/**
* @override
*/
async diagnose() {
let xcodePath;
try {
// https://github.com/appium/appium/issues/12093#issuecomment-459358120 can happen
await exec('xcrun', ['simctl', 'help']);
} catch (err) {
return nok('Error running xcrun simctl');
}
try {
const {stdout} = await exec('xcode-select', ['-p']);
xcodePath = (stdout || '').replace('\n', '');
} catch (err) {
return nok('Xcode is NOT installed!');
}
return xcodePath && (await fs.exists(xcodePath))
? ok(`Xcode is installed at: ${xcodePath}`)
: nok(`Xcode cannot be found at '${xcodePath}'!`);
}
/**
* @override
*/
async fix() {
return `Manually install ${
'Xcode'.bold
}, and make sure 'xcode-select -p' command shows proper path like '/Applications/Xcode.app/Contents/Developer'`;
}
}
checks.push(new XcodeCheck());
// Check for Xcode Command Line Tools.
export class XcodeCmdLineToolsCheck extends DoctorCheck {
constructor() {
super({autofix: true});
}
/**
* @override
*/
async diagnose() {
const errMess = 'Xcode Command Line Tools are NOT installed!';
try {
// https://stackoverflow.com/questions/15371925/how-to-check-if-command-line-tools-is-installed
const stdout = (await exec('xcode-select', ['-p'])).stdout;
return ok(`Xcode Command Line Tools are installed in: ${stdout.trim()}`);
} catch (err) {
log.debug(err);
return nok(errMess);
}
}
/**
* @override
*/
async fix() {
log.info(`The following command need be executed: xcode-select --install`);
let yesno = await fixIt();
if (yesno === 'yes') {
await exec('xcode-select', ['--install']);
} else {
log.info(`Skipping. You will need to install ${'Xcode'.bold} manually.`);
throw new FixSkippedError();
}
return null;
}
}
checks.push(new XcodeCmdLineToolsCheck());
// Dev Tools Security
export class DevToolsSecurityCheck extends DoctorCheck {
/**
* @override
*/
async diagnose() {
const errMess = 'DevToolsSecurity is NOT enabled!';
let stdout;
try {
stdout = (await exec('DevToolsSecurity', [])).stdout;
} catch (err) {
log.debug(err);
return nok(errMess);
}
return stdout && stdout.match(/enabled/) ? ok('DevToolsSecurity is enabled.') : nok(errMess);
}
}
checks.push(
new DevToolsSecurityCheck(),
new EnvVarAndPathCheck('HOME'),
);
export class OptionalLyftCommandCheck extends DoctorCheck {
/**
* @override
*/
async diagnose() {
const lyftCmd = await resolveExecutablePath('set-simulator-location');
if (lyftCmd) {
return okOptional('set-simulator-location is installed');
}
return nokOptional('set-simulator-location is not installed');
}
/**
* @override
*/
async fix() {
return (
`${'set-simulator-location'.bold} is needed to set location for Simulator. ` +
'Please read https://github.com/lyft/set-simulator-location to install it'
);
}
}
checks.push(new OptionalLyftCommandCheck());
export class OptionalIdbCommandCheck extends DoctorCheck {
/**
* @override
*/
async diagnose() {
const fbIdbPath = await resolveExecutablePath('idb');
const fbCompanionIdbPath = await resolveExecutablePath('idb_companion');
if (fbIdbPath && fbCompanionIdbPath) {
return okOptional('idb and idb_companion are installed');
}
if (!fbIdbPath && fbCompanionIdbPath) {
return nokOptional('idb is not installed');
} else if (fbIdbPath && !fbCompanionIdbPath) {
return nokOptional('idb_companion is not installed');
}
return nokOptional('idb and idb_companion are not installed');
}
/**
* @override
*/
async fix() {
return `Why ${'idb'.bold} is needed and how to install it: ${
OptionalIdbCommandCheck.idbReadmeURL
}`;
}
}
// link to idb README.md
// https://github.com/appium/appium-ios/blob/main/packages/idb/README.md
OptionalIdbCommandCheck.idbReadmeURL = 'https://git.io/JnxQc';
checks.push(new OptionalIdbCommandCheck());
export class OptionalApplesimutilsCommandCheck extends DoctorCheck {
/**
* @override
*/
async diagnose() {
const applesimutilsPath = await resolveExecutablePath('applesimutils');
return applesimutilsPath
? okOptional(
`applesimutils is installed at: ${applesimutilsPath}. Installed versions are: ${(
await exec('brew', ['list', '--versions', 'applesimutils'])
).stdout.trim()}`
)
: nokOptional('applesimutils cannot be found');
}
/**
* @override
*/
async fix() {
return `Why ${
'applesimutils'.bold
} is needed and how to install it: ` +
`https://github.com/appium/appium-xcuitest-driver/blob/master/docs/execute-methods.md#mobile-setpermission`;
}
}
checks.push(new OptionalApplesimutilsCommandCheck());
export class OptionalIOSDeployCommandCheck extends DoctorCheck {
/**
* @override
*/
async diagnose() {
const iosDeployPath = await resolveExecutablePath('ios-deploy');
return iosDeployPath
? okOptional(
`ios-deploy is installed at: ${iosDeployPath}. Installed version is: ${(
await exec(iosDeployPath, ['-V'])
).stdout.trim()}`
)
: nokOptional('ios-deploy cannot be found');
}
/**
* @override
*/
async fix() {
return `${
'ios-deploy'.bold
} is used as a fallback command to install iOS applications to real device. ` +
`Please read https://github.com/ios-control/ios-deploy/ to install it`;
}
}
checks.push(new OptionalIOSDeployCommandCheck());
export default checks;

View File

@@ -1,5 +0,0 @@
import {logger} from '@appium/support';
const log = logger.getLogger('AppiumDoctor');
export default log;

View File

@@ -1,35 +0,0 @@
import log from './logger';
import {resolveExecutablePath} from './utils';
// Look for node
export class NodeDetector {
/**
* @returns {Promise<string?>}
*/
static async retrieveUsingSystemCall() {
const nodePath = await resolveExecutablePath('node');
if (!nodePath) {
log.debug(`Node binary not found in PATH: ${process.env.PATH}`);
return null;
}
log.debug(`Node binary found at: ${nodePath}`);
return nodePath;
}
/**
* @returns {Promise<string?>}
*/
static async detect() {
const nodePath = await NodeDetector.retrieveUsingSystemCall();
if (nodePath) {
return nodePath;
} else {
log.warn('The node binary could not be found.');
return null;
}
}
}
export default NodeDetector;

View File

@@ -1,53 +0,0 @@
import { prompt } from './utils';
/**
* @type {string|undefined}
*/
let persistentResponse;
const fixItQuestion = {
type: 'list',
name: 'confirmation',
message: 'Fix it:',
choices: ['yes', 'no', 'always', 'never'],
/**
*
* @param {string} val
* @returns {string}
*/
filter(val) {
return val.toLowerCase();
},
};
/**
* @param {Record<string, any>} opts
*/
export function configure(opts) {
if (opts.yes) {
persistentResponse = 'yes';
}
if (opts.no) {
persistentResponse = 'no';
}
}
/**
* @returns {void}
*/
export function clear() {
persistentResponse = undefined;
}
/**
* @returns {Promise<string|undefined>}
*/
export async function fixIt() {
if (persistentResponse) {
return persistentResponse;
}
const resp = await prompt(fixItQuestion);
persistentResponse = resp.confirmation === 'always' ? 'yes' : persistentResponse;
persistentResponse = resp.confirmation === 'never' ? 'no' : persistentResponse;
return persistentResponse || resp.confirmation;
}

View File

@@ -1,135 +0,0 @@
import log from '../lib/logger';
import {fs, system} from '@appium/support';
import {exec} from 'teen_process';
import {isFunction} from 'lodash';
/**
* @param {string} message
* @returns {CheckResult}
*/
export function ok(message) {
return {ok: true, optional: false, message};
}
/**
* @param {string} message
* @returns {CheckResult}
*/
export function nok(message) {
return {ok: false, optional: false, message};
}
/**
* @param {string} message
* @returns {CheckResult}
*/
export function okOptional(message) {
return {ok: true, optional: true, message};
}
/**
* @param {string} message
* @returns {CheckResult}
*/
export function nokOptional(message) {
return {ok: false, optional: true, message};
}
/**
* @param {any} question https://www.npmjs.com/package/inquirer#question
* @returns {Promise<{confirmation: string}>}
*/
export async function prompt(question) {
const {default: inquirer} = await import('inquirer');
return await inquirer.prompt(question);
}
let onLogMessageHandler = null;
export function configureBinaryLog(opts) {
const internalLogger = log.unwrap();
if (isFunction(opts.onLogMessage) && !onLogMessageHandler) {
onLogMessageHandler = (/** @type {import('@appium/logger').MessageObject} */ msg) => opts.onLogMessage(
msg.level, msg.prefix, msg.message
);
internalLogger.on('log', onLogMessageHandler);
};
internalLogger.level = opts.debug ? 'debug' : 'info';
}
/**
* If {@link configureBinaryLog} was called, this will restore the original `log` function.
*/
export function resetLog() {
if (onLogMessageHandler) {
log.unwrap().off('log', onLogMessageHandler);
onLogMessageHandler = null;
}
}
/**
* Return an executable path of cmd
*
* @param {string} cmd Standard output by command
* @return {Promise<string?>} The full path of cmd. `null` if the cmd is not found.
*/
export async function resolveExecutablePath(cmd) {
let executablePath;
try {
executablePath = await fs.which(cmd);
if (executablePath && (await fs.exists(executablePath))) {
return executablePath;
}
} catch (err) {
if (/not found/gi.test(err.message)) {
log.debug(err);
} else {
log.warn(err);
}
}
log.debug(`No executable path of '${cmd}'.`);
if (executablePath) {
log.debug(`Does '${executablePath}' exist?`);
}
return null;
}
/**
* @typedef NpmPackageInfo
* @property {string} version - version
* @property {string} path - A path to npm root
*/
/**
* Returns the path and version of given package name
* @param {string} packageName A package name to get path and version data
* @return {Promise<NpmPackageInfo?>}
*/
export async function getNpmPackageInfo(packageName) {
const npmPath = await resolveExecutablePath(`npm${system.isWindows() ? `.cmd` : ''}`);
if (!npmPath) {
return null;
}
let pJson = {};
try {
const {stdout} = await exec(npmPath, ['list', '-g', '-l', '-j', packageName]);
pJson = JSON.parse(stdout);
} catch (err) {
log.debug(err);
return null;
}
if (pJson.dependencies && pJson.dependencies[packageName]) {
return {version: pJson.dependencies[packageName].version, path: pJson.path};
}
return null;
}
/**
* @typedef CheckResult
* @property {boolean} ok
* @property {boolean} optional
* @property {string} message
*/

View File

@@ -1,67 +0,0 @@
{
"name": "@appium/doctor",
"version": "2.1.15",
"description": "Test environment for fitness to run Appium",
"keywords": [
"automation",
"javascript",
"selenium",
"webdriver",
"ios",
"android",
"firefoxos",
"testing"
],
"homepage": "https://appium.io",
"bugs": {
"url": "https://github.com/appium/appium/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/appium/appium.git",
"directory": "packages/doctor"
},
"license": "Apache-2.0",
"author": "https://github.com/appium",
"main": "./appium-doctor.js",
"bin": {
"appium-doctor": "./appium-doctor.js"
},
"directories": {
"lib": "lib"
},
"files": [
"appium-doctor.js",
"lib",
"bin",
"build",
"tsconfig.json",
"!build/tsconfig.tsbuildinfo"
],
"scripts": {
"test": "npm run test:unit",
"test:smoke": "node ./build/lib/index.js",
"test:unit": "mocha \"./test/unit/**/*.spec.js\""
},
"dependencies": {
"@appium/support": "^5.1.8",
"@colors/colors": "1.6.0",
"@types/bluebird": "3.5.42",
"@types/teen_process": "2.0.4",
"appium-adb": "12.7.0",
"bluebird": "3.7.2",
"inquirer": "9.2.12",
"lodash": "4.17.21",
"source-map-support": "0.5.21",
"teen_process": "2.2.0",
"yargs": "17.7.2"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0",
"npm": ">=8"
},
"publishConfig": {
"access": "public"
},
"gitHead": "8480a85ce2fa466360e0fb1a7f66628331907f02"
}

View File

@@ -1,199 +0,0 @@
import path from 'node:path';
import {
EnvVarAndPathCheck,
AndroidToolCheck,
OptionalAppBundleCheck,
OptionalGstreamerCheck,
} from '../../lib/android';
import {fs, system} from '@appium/support';
import * as adb from 'appium-adb';
import * as utils from '../../lib/utils';
import * as tp from 'teen_process';
import {withMocks, stubEnv} from '@appium/test-support';
import B from 'bluebird';
import {removeColors} from './helper';
import {createSandbox} from 'sinon';
describe('android', function () {
const apkAnalyzerFilename = system.isWindows() ? 'apkanalyzer.bat' : 'apkanalyzer';
const gstLaunchFilename = system.isWindows() ? 'gst-launch-1.0.exe' : 'gst-launch-1.0';
const gstInspectFilename = system.isWindows() ? 'gst-inspect-1.0.exe' : 'gst-inspect-1.0';
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
});
describe(
'EnvVarAndPathCheck',
withMocks({fs}, (mocks) => {
stubEnv();
let check = new EnvVarAndPathCheck('ANDROID_HOME');
it('autofix', function () {
check.autofix.should.not.be.ok;
});
it('diagnose - success', async function () {
process.env.ANDROID_HOME = '/a/b/c/d';
mocks.fs.expects('exists').once().returns(B.resolve(true));
(await check.diagnose()).should.deep.equal({
ok: true,
optional: false,
message: 'ANDROID_HOME is set to: /a/b/c/d',
});
mocks.verify();
});
it('failure - not set', async function () {
delete process.env.ANDROID_HOME;
const {ok, optional, message} = await check.diagnose();
ok.should.be.false;
optional.should.be.false;
message.should.not.be.empty;
mocks.verify();
});
it('failure - file not exists', async function () {
process.env.ANDROID_HOME = '/a/b/c/d';
mocks.fs.expects('exists').once().returns(B.resolve(false));
(await check.diagnose()).should.deep.equal({
ok: false,
optional: false,
message: "ANDROID_HOME is set to '/a/b/c/d' " + 'but this is NOT a valid path!',
});
mocks.verify();
});
it('fix', async function () {
removeColors(await check.fix()).should.contain('ANDROID_HOME');
});
})
);
describe(
'AndroidToolCheck', function () {
// withMocks won't work with ESM modules: https://github.com/sinonjs/sinon/issues/2530
/** @type {sinon.SinonSandbox} */
let sandbox;
beforeEach(function () {
sandbox = createSandbox();
});
afterEach(function () {
sandbox.restore();
});
stubEnv();
const check = new AndroidToolCheck();
it('autofix', function () {
check.autofix.should.not.be.ok;
});
it('diagnose - success', async function () {
process.env.ANDROID_HOME = '/a/b/c/d';
sandbox.stub(adb, 'getAndroidBinaryPath')
.get(() => sandbox.fake.resolves('/path/to/binary'));
(await check.diagnose()).should.deep.equal({
ok: true,
optional: false,
message: `adb, emulator, ${apkAnalyzerFilename} exist: /a/b/c/d`,
});
});
it('diagnose - failure - no ANDROID_HOME', async function () {
delete process.env.ANDROID_HOME;
delete process.env.ANDROID_SDK_ROOT;
(await check.diagnose()).should.deep.equal({
ok: false,
optional: false,
message: `adb, emulator, ${apkAnalyzerFilename} could not be found because ANDROID_HOME is NOT set!`,
});
});
it('diagnose - failure - path not valid', async function () {
process.env.ANDROID_HOME = '/a/b/c/d';
sandbox.stub(adb, 'getAndroidBinaryPath')
.get(() => sandbox.fake.throws());
(await check.diagnose()).should.deep.equal({
ok: false,
optional: false,
message: `adb, emulator, ${apkAnalyzerFilename} could NOT be found in /a/b/c/d!`,
});
});
it('fix - ANDROID_HOME', async function () {
delete process.env.ANDROID_HOME;
removeColors(await check.fix()).should.equal(
'Manually configure ANDROID_HOME ' + 'and run appium-doctor again.'
);
});
it('fix - install', async function () {
process.env.ANDROID_HOME = path.resolve('/', 'a', 'b', 'c', 'd');
removeColors(await check.fix()).should.equal(
`Manually install adb, emulator, ${apkAnalyzerFilename} and add it to PATH. https://developer.android.com/studio#cmdline-tools and https://developer.android.com/studio/intro/update#sdk-manager may help to setup.`
);
});
}
);
describe(
'OptionalAppBundleCheck',
withMocks({tp, utils}, (mocks) => {
let check = new OptionalAppBundleCheck();
it('autofix', function () {
check.autofix.should.not.be.ok;
});
it('diagnose - success', async function () {
mocks.utils.expects('resolveExecutablePath').once().returns('path/to/bundletool.jar');
(await check.diagnose()).should.deep.equal({
ok: true,
optional: true,
message: 'bundletool.jar is installed at: path/to/bundletool.jar',
});
mocks.verify();
});
it('diagnose - failure', async function () {
mocks.utils.expects('resolveExecutablePath').once().returns(false);
(await check.diagnose()).should.deep.equal({
ok: false,
optional: true,
message: 'bundletool.jar cannot be found',
});
mocks.verify();
});
it('fix', async function () {
removeColors(await check.fix()).should.match(
new RegExp(
'bundletool.jar is used to handle Android App Bundle. Please read http://appium.io/docs/en/writing-running-appium/android/android-appbundle/ to install it'
)
);
});
})
);
describe(
'OptionalGstreamerCheck',
withMocks({tp, utils}, (mocks) => {
let check = new OptionalGstreamerCheck();
it('autofix', function () {
check.autofix.should.not.be.ok;
});
it('diagnose - success', async function () {
mocks.utils.expects('resolveExecutablePath').once().returns('path/to/gst-launch');
mocks.utils.expects('resolveExecutablePath').once().returns('path/to/gst-inspect');
(await check.diagnose()).should.deep.equal({
ok: true,
optional: true,
message: `${gstLaunchFilename} and ${gstInspectFilename} are installed at: path/to/gst-launch and path/to/gst-inspect`,
});
mocks.verify();
});
it('diagnose - failure', async function () {
mocks.utils.expects('resolveExecutablePath').twice().returns(false);
(await check.diagnose()).should.deep.equal({
ok: false,
optional: true,
message: `${gstLaunchFilename} and/or ${gstInspectFilename} cannot be found`,
});
mocks.verify();
});
it('fix', async function () {
removeColors(await check.fix()).should.equal(
`${gstLaunchFilename} and ${gstInspectFilename} are used to stream the screen of the device under test. Please read https://appium.io/docs/en/writing-running-appium/android/android-screen-streaming/ to install them and for more details`
);
});
})
);
});

View File

@@ -1,133 +0,0 @@
import {DirCheck, FileCheck} from '../../lib/demo';
import {fs} from '@appium/support';
import * as tp from 'teen_process';
import * as prompt from '../../lib/prompt';
import log from '../../lib/logger';
import {FixSkippedError} from '../../lib/doctor';
import {withMocks, withSandbox, stubLog} from '@appium/test-support';
import B from 'bluebird';
describe('demo', function () {
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
});
describe(
'DirCheck',
withMocks({fs}, (mocks) => {
let check = new DirCheck('/a/b/c/d');
it('diagnose - success', async function () {
mocks.fs.expects('exists').once().returns(B.resolve(true));
mocks.fs
.expects('lstat')
.once()
.returns(
B.resolve({
isDirectory() {
return true;
},
})
);
(await check.diagnose()).should.deep.equal({
ok: true,
optional: false,
message: 'Found directory at: /a/b/c/d',
});
mocks.verify();
});
it('failure - not there', async function () {
mocks.fs.expects('exists').once().returns(B.resolve(false));
(await check.diagnose()).should.deep.equal({
ok: false,
optional: false,
message: "Could NOT find directory at '/a/b/c/d'!",
});
mocks.verify();
});
it('failure - not a dir', async function () {
mocks.fs.expects('exists').once().returns(B.resolve(true));
mocks.fs
.expects('lstat')
.once()
.returns(
B.resolve({
isDirectory() {
return false;
},
})
);
(await check.diagnose()).should.deep.equal({
ok: false,
optional: false,
message: "'/a/b/c/d' is NOT a directory!",
});
mocks.verify();
});
it('fix', async function () {
(await check.fix()).should.equal('Manually create a directory at: /a/b/c/d');
});
})
);
describe(
'FileCheck',
withSandbox({mocks: {fs, tp, prompt}}, (S) => {
let check = new FileCheck('/a/b/c/d');
it('diagnose - success', async function () {
S.mocks.fs.expects('exists').once().returns(B.resolve(true));
(await check.diagnose()).should.deep.equal({
ok: true,
optional: false,
message: 'Found file at: /a/b/c/d',
});
S.verify();
});
it('failure - not there', async function () {
S.mocks.fs.expects('exists').once().returns(B.resolve(false));
(await check.diagnose()).should.deep.equal({
ok: false,
optional: false,
message: "Could NOT find file at '/a/b/c/d'!",
});
S.verify();
});
it('fix - yes', async function () {
let logStub = stubLog(S.sandbox, log, {stripColors: true});
S.mocks.prompt.expects('fixIt').once().returns(B.resolve('yes'));
S.mocks.tp
.expects('exec')
.once()
.returns(B.resolve({stdout: '', stderr: ''}));
await check.fix();
S.verify();
logStub.output.should.equal(
"info: The following command need be executed: touch '/a/b/c/d'"
);
});
it('fix - no', async function () {
let logStub = stubLog(S.sandbox, log, {stripColors: true});
S.mocks.prompt.expects('fixIt').once().returns(B.resolve('no'));
S.mocks.tp.expects('exec').never();
await check.fix().should.be.rejectedWith(FixSkippedError);
S.verify();
logStub.output.should.equal(
[
"info: The following command need be executed: touch '/a/b/c/d'",
"info: Skipping. You will need to touch '/a/b/c/d' manually.",
].join('\n')
);
});
})
);
});

View File

@@ -1,114 +0,0 @@
import path from 'node:path';
import {BinaryIsInPathCheck, AndroidSdkExists} from '../../lib/dev';
import {fs} from '@appium/support';
import * as tp from 'teen_process';
import {withMocks, stubEnv} from '@appium/test-support';
import B from 'bluebird';
import {removeColors} from './helper';
describe('dev', function () {
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
});
describe(
'BinaryIsInPathCheck',
withMocks({tp, fs}, (mocks) => {
stubEnv();
let check = new BinaryIsInPathCheck('mvn');
it('autofix', function () {
check.autofix.should.not.be.ok;
});
it('diagnose - success', async function () {
process.env.PATH = '/a/b/c/d;/e/f/g/h';
mocks.fs.expects('which').once().returns(B.resolve('/a/b/c/d/mvn'));
mocks.fs.expects('exists').once().returns(B.resolve(true));
(await check.diagnose()).should.deep.equal({
ok: true,
optional: false,
message: 'mvn was found at /a/b/c/d/mvn',
});
mocks.verify();
});
it('diagnose - failure - not in path ', async function () {
process.env.PATH = '/a/b/c/d;/e/f/g/h';
mocks.fs
.expects('which')
.once()
.returns(B.resolve({stack: 'mvn not found'}));
(await check.diagnose()).should.deep.equal({
ok: false,
optional: false,
message: 'mvn is MISSING in PATH: /a/b/c/d;/e/f/g/h',
});
mocks.verify();
});
it('diagnose - failure - invalid path', async function () {
process.env.PATH = '/a/b/c/d;/e/f/g/h';
mocks.fs.expects('which').once().returns(B.resolve('/a/b/c/d/mvn'));
mocks.fs.expects('exists').once().returns(B.resolve(false));
(await check.diagnose()).should.deep.equal({
ok: false,
optional: false,
message: 'mvn is MISSING in PATH: /a/b/c/d;/e/f/g/h',
});
mocks.verify();
});
it('fix', async function () {
removeColors(await check.fix()).should.equal(
'Manually install the mvn binary and add it to PATH.'
);
});
})
);
describe(
'AndroidSdkExists',
withMocks({fs}, (mocks) => {
stubEnv();
let check = new AndroidSdkExists('android-16');
it('autofix', function () {
check.autofix.should.not.be.ok;
});
it('diagnose - success', async function () {
process.env.ANDROID_HOME = path.resolve('/', 'a', 'b', 'c', 'd');
mocks.fs.expects('exists').once().returns(B.resolve(true));
(await check.diagnose()).should.deep.equal({
ok: true,
optional: false,
message: `android-16 was found at: ${process.env.ANDROID_HOME}${path.sep}platforms${path.sep}android-16`,
});
mocks.verify();
});
it('failure - missing android home', async function () {
delete process.env.ANDROID_HOME;
(await check.diagnose()).should.deep.equal({
ok: false,
optional: false,
message: 'android-16 could not be found because ANDROID_HOME is NOT set!',
});
mocks.verify();
});
it('diagnose - failure - invalid path', async function () {
process.env.ANDROID_HOME = path.resolve('/', 'a', 'b', 'c', 'd');
mocks.fs.expects('exists').once().returns(B.resolve(false));
(await check.diagnose()).should.deep.equal({
ok: false,
optional: false,
message: `android-16 could NOT be found at '${process.env.ANDROID_HOME}${path.sep}platforms${path.sep}android-16'!`,
});
mocks.verify();
});
it('fix - ANDROID_HOME', async function () {
delete process.env.ANDROID_HOME;
removeColors(await check.fix()).should.equal('Manually configure ANDROID_HOME.');
});
it('fix - install', async function () {
process.env.ANDROID_HOME = '/a/b/c/d';
removeColors(await check.fix()).should.equal('Manually install the android-16 sdk.');
});
})
);
});

View File

@@ -1,438 +0,0 @@
import {Doctor, DoctorCheck, FixSkippedError} from '../../lib/doctor';
import {withSandbox, stubLog} from '@appium/test-support';
import log from '../../lib/logger';
import B from 'bluebird';
describe('doctor', function () {
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
});
it('register', function () {
let doctor = new Doctor();
doctor.checks.should.have.length(0);
doctor.register(new DoctorCheck());
doctor.checks.should.have.length(1);
doctor.register([new DoctorCheck(), new DoctorCheck()]);
doctor.checks.should.have.length(3);
});
function configure() {
let doctor = new Doctor();
let checks = [
new DoctorCheck(),
new DoctorCheck(),
new DoctorCheck(),
new DoctorCheck(),
new DoctorCheck(),
];
doctor.register(checks);
return {doctor, checks};
}
describe(
'diagnose',
withSandbox({}, (S) => {
it('should detect all issues', async function () {
let logStub = stubLog(S.sandbox, log, {stripColors: true});
let {doctor, checks} = configure();
S.mocks.checks = checks.map((check) => S.sandbox.mock(check));
S.mocks.checks[0].expects('diagnose').once().returns({ok: true, message: 'All Good!'});
S.mocks.checks[1]
.expects('diagnose')
.twice()
.returns({ok: true, optional: true, message: 'All Good Option!'});
S.mocks.checks[2].expects('diagnose').once().returns({ok: false, message: 'Oh No!'});
S.mocks.checks[3]
.expects('diagnose')
.twice()
.returns({ok: false, optional: true, message: 'Oh No Option!'});
S.mocks.checks[4].expects('diagnose').once().returns({ok: false, message: 'Oh No!'});
await doctor.diagnose();
S.verify();
doctor.toFix.should.have.length(2);
doctor.toFixOptionals.should.have.length(1);
logStub.output.should.equal(
[
'info: ### Diagnostic for necessary dependencies starting ###',
'info: ✔ All Good!',
'warn: ✖ Oh No!',
'warn: ✖ Oh No!',
'info: ### Diagnostic for necessary dependencies completed, 2 fixes needed. ###',
'info: ',
'info: ### Diagnostic for optional dependencies starting ###',
'info: ✔ All Good Option!',
'warn: ✖ Oh No Option!',
'info: ### Diagnostic for optional dependencies completed, one fix possible. ###',
'info: ',
].join('\n')
);
});
})
);
describe(
'reportSuccess',
withSandbox({}, (S) => {
let doctor = new Doctor();
it('should report success when no fixes are needed', async function () {
let logStub = stubLog(S.sandbox, log, {stripColors: true});
(
await doctor.reportSuccess(doctor.toFix.length, doctor.toFixOptionals.length)
).should.equal(true);
logStub.output.should.equal(['info: Everything looks good, bye!', 'info: '].join('\n'));
});
it('should return false when fixes are needed', async function () {
doctor.toFix = [{}];
(await doctor.reportSuccess(doctor.toFix.length)).should.equal(false);
});
})
);
describe(
'reportManualFixes',
withSandbox({}, (S) => {
let doctor = new Doctor();
it('should ask for manual fixes to be applied', async function () {
let logStub = stubLog(S.sandbox, log, {stripColors: true});
doctor.toFix = [
{
error: 'Oh no this need to be manually fixed.',
check: new DoctorCheck(),
},
{
error: 'Oh no this is an autofix.',
check: new DoctorCheck({autofix: true}),
},
{
error: 'Oh no this also need to be manually fixed.',
check: new DoctorCheck(),
},
{
error: 'Oh no this also need to be manually fixed.',
check: new DoctorCheck(),
},
];
doctor.toFixOptionals = [];
for (let i = 0; i < doctor.toFix.length; i++) {
let m = S.sandbox.mock(doctor.toFix[i].check);
if (doctor.toFix[i].check.autofix) {
m.expects('fix').never();
} else {
m.expects('fix')
.once()
.returns(B.resolve(`Manual fix for ${i} is do something.`));
}
}
(await doctor.reportManualFixes(doctor.toFix, doctor.toFixOptionals)).should.equal(true);
S.verify();
logStub.output.should.equal(
[
'info: ### Manual Fixes Needed ###',
'info: The configuration cannot be automatically fixed, please do the following first:',
'warn: ➜ Manual fix for 0 is do something.',
'warn: ➜ Manual fix for 2 is do something.',
'warn: ➜ Manual fix for 3 is do something.',
'info: ',
'info: ###',
'info: ',
'info: Bye! Run appium-doctor again when all manual fixes have been applied!',
'info: ',
].join('\n')
);
});
it('should ask for manual fixes to be applied for optional', async function () {
let logStub = stubLog(S.sandbox, log, {stripColors: true});
doctor.toFix = [];
doctor.toFixOptionals = [
{
error: 'Oh no this need to be manually fixed.',
check: new DoctorCheck(),
},
{
error: 'Oh no this also need to be manually fixed.',
check: new DoctorCheck(),
},
];
for (let i = 0; i < doctor.toFixOptionals.length; i++) {
let m = S.sandbox.mock(doctor.toFixOptionals[i].check);
if (doctor.toFixOptionals[i].check.autofix) {
m.expects('fix').never();
} else {
m.expects('fix')
.once()
.returns(B.resolve(`Manual fix for ${i} is do something.`));
}
}
(await doctor.reportManualFixes(doctor.toFix, doctor.toFixOptionals)).should.equal(true);
S.verify();
logStub.output.should.equal(
[
'info: ### Optional Manual Fixes ###',
'info: The configuration can install optionally. Please do the following manually:',
'warn: ➜ Manual fix for 0 is do something.',
'warn: ➜ Manual fix for 1 is do something.',
'info: ',
'info: ###',
'info: ',
'info: Bye! Run appium-doctor again when all manual fixes have been applied!',
'info: ',
].join('\n')
);
});
it('should ask for manual fixes to be applied for necessary and optional', async function () {
let logStub = stubLog(S.sandbox, log, {stripColors: true});
doctor.toFix = [
{
error: 'Oh no this need to be manually fixed.',
check: new DoctorCheck(),
},
];
doctor.toFixOptionals = [
{
error: 'Oh no this need to be manually fixed, but it is optional.',
check: new DoctorCheck(),
},
];
S.sandbox
.mock(doctor.toFix[0].check)
.expects('fix')
.once()
.returns(B.resolve(`Manual fix for 0 is do something.`));
S.sandbox
.mock(doctor.toFixOptionals[0].check)
.expects('fix')
.once()
.returns(B.resolve(`Manual fix for 0 is do something.`));
(await doctor.reportManualFixes(doctor.toFix, doctor.toFixOptionals)).should.equal(true);
S.verify();
logStub.output.should.equal(
[
'info: ### Manual Fixes Needed ###',
'info: The configuration cannot be automatically fixed, please do the following first:',
'warn: ➜ Manual fix for 0 is do something.',
'info: ',
'info: ### Optional Manual Fixes ###',
'info: The configuration can install optionally. Please do the following manually:',
'warn: ➜ Manual fix for 0 is do something.',
'info: ',
'info: ###',
'info: ',
'info: Bye! Run appium-doctor again when all manual fixes have been applied!',
'info: ',
].join('\n')
);
});
it('should return false when there is no manual fix', async function () {
doctor.toFix = [{error: 'Oh no!', check: new DoctorCheck({autofix: true})}];
(await doctor.reportManualFixes()).should.equal(false);
});
})
);
describe(
'runAutoFix',
withSandbox({}, (S) => {
let doctor = new Doctor();
let fix = {
error: 'Something wrong!',
check: {
fix() {},
diagnose() {},
},
};
it('fix - success', async function () {
let logStub = stubLog(S.sandbox, log, {stripColors: true});
S.mocks.check = S.sandbox.mock(fix.check);
S.mocks.check.expects('fix').once();
S.mocks.check
.expects('diagnose')
.once()
.returns(
B.resolve({
ok: true,
optional: false,
message: 'It worked',
})
);
await doctor.runAutoFix(fix);
S.verify();
logStub.output.should.equal(
[
'info: ### Fixing: Something wrong! ###',
'info: Checking if this was fixed:',
'info: ✔ It worked',
'info: ### Fix was successfully applied ###',
].join('\n')
);
});
it('fix - skipped', async function () {
let logStub = stubLog(S.sandbox, log, {stripColors: true});
S.mocks.check = S.sandbox.mock(fix.check);
S.mocks.check.expects('fix').once().throws(new FixSkippedError());
await doctor.runAutoFix(fix);
S.verify();
logStub.output.should.equal(
['info: ### Fixing: Something wrong! ###', 'info: ### Skipped fix ###'].join('\n')
);
});
it('fix - crash', async function () {
let logStub = stubLog(S.sandbox, log, {stripColors: true});
S.mocks.check = S.sandbox.mock(fix.check);
S.mocks.check.expects('fix').once().throws(new Error('Oh No!'));
await doctor.runAutoFix(fix);
S.verify();
logStub.output.should.equal(
[
'info: ### Fixing: Something wrong! ###',
'warn: Error: Oh No!',
'info: ### Fix did not succeed ###',
].join('\n')
);
});
it("fix - didn't fix", async function () {
let logStub = stubLog(S.sandbox, log, {stripColors: true});
S.mocks.check = S.sandbox.mock(fix.check);
S.mocks.check.expects('fix').once();
S.mocks.check
.expects('diagnose')
.once()
.returns(
B.resolve({
ok: false,
message: 'Still Weird!',
})
);
await doctor.runAutoFix(fix);
S.verify();
logStub.output.should.equal(
[
'info: ### Fixing: Something wrong! ###',
'info: Checking if this was fixed:',
'info: ✖ Still Weird!',
'info: ### Fix was applied but issue remains ###',
].join('\n')
);
});
})
);
describe(
'runAutoFixes',
withSandbox({}, (S) => {
let doctor = new Doctor();
it('success', async function () {
let logStub = stubLog(S.sandbox, log, {stripColors: true});
doctor.toFix = [
{error: 'Oh no.', check: new DoctorCheck({autofix: true})},
{error: 'Oh no.', check: new DoctorCheck({autofix: true})},
{error: 'Oh no.', check: new DoctorCheck({autofix: true})},
];
S.sandbox.stub(doctor, 'runAutoFix').callsFake((f) => {
log.info('Autofix log go there.');
f.fixed = true;
});
await doctor.runAutoFixes();
doctor.runAutoFix.calledThrice.should.be.ok;
logStub.output.should.equal(
[
'info: Autofix log go there.',
'info: ',
'info: Autofix log go there.',
'info: ',
'info: Autofix log go there.',
'info: ',
'info: Bye! All issues have been fixed!',
'info: ',
].join('\n')
);
});
it('failure', async function () {
let logStub = stubLog(S.sandbox, log, {stripColors: true});
doctor.toFix = [
{error: 'Oh no.', check: new DoctorCheck({autofix: true})},
{error: 'Oh no.', check: new DoctorCheck({autofix: true})},
{error: 'Oh no.', check: new DoctorCheck({autofix: true})},
];
let succeed = false;
S.sandbox.stub(doctor, 'runAutoFix').callsFake((f) => {
if (succeed) {
log.info('succeeded, Autofix log go there.');
f.fixed = true;
} else {
log.warn('failed, Autofix log go there.');
}
succeed = !succeed;
});
await doctor.runAutoFixes();
doctor.runAutoFix.calledThrice.should.be.ok;
logStub.output.should.equal(
[
'warn: failed, Autofix log go there.',
'info: ',
'info: succeeded, Autofix log go there.',
'info: ',
'warn: failed, Autofix log go there.',
'info: ',
'info: Bye! A few issues remain, fix manually and/or rerun appium-doctor!',
'info: ',
].join('\n')
);
});
})
);
describe(
'run',
withSandbox({}, (S) => {
let doctor = new Doctor();
it('should work', async function () {
try {
let doctor = new Doctor();
await doctor.run();
} catch (err) {}
});
it('should report success', async function () {
S.mocks.doctor = S.sandbox.mock(doctor);
S.mocks.doctor.expects('diagnose').once();
S.mocks.doctor.expects('reportSuccess').once().returns(true);
S.mocks.doctor.expects('reportManualFixes').never();
S.mocks.doctor.expects('runAutoFixes').never();
await doctor.run();
S.verify();
});
it('should report manual fixes', async function () {
S.mocks.doctor = S.sandbox.mock(doctor);
S.mocks.doctor.expects('diagnose').once();
S.mocks.doctor.expects('reportSuccess').once().returns(false);
S.mocks.doctor.expects('reportManualFixes').once().returns(true);
S.mocks.doctor.expects('runAutoFixes').never();
await doctor.run();
S.verify();
});
it('should run autofixes', async function () {
S.mocks.doctor = S.sandbox.mock(doctor);
S.mocks.doctor.expects('diagnose').once();
S.mocks.doctor.expects('reportSuccess').once().returns(false);
S.mocks.doctor.expects('reportManualFixes').once().returns(false);
S.mocks.doctor.expects('runAutoFixes').once();
await doctor.run();
S.verify();
});
})
);
});

View File

@@ -1,19 +0,0 @@
import newDoctor from '../../lib/factory';
describe('factory', function () {
before(async function () {
const chai = await import('chai');
chai.should();
});
function getTest(config) {
return function runTest() {
let doctor = newDoctor(config);
doctor.should.exist;
doctor.checks.should.have.length.above(0);
};
}
for (let config of [{ios: true}, {android: true}, {dev: true}]) {
it(`should work for ${config}`, getTest(config));
}
});

View File

@@ -1 +0,0 @@
WOW

View File

@@ -1,200 +0,0 @@
import {
NodeBinaryCheck,
NodeVersionCheck,
OptionalFfmpegCommandCheck,
OptionalMjpegConsumerCommandCheck,
} from '../../lib/general';
import * as tp from 'teen_process';
import * as utils from '../../lib/utils';
import NodeDetector from '../../lib/node-detector';
import {withMocks} from '@appium/test-support';
import B from 'bluebird';
import {removeColors} from './helper';
describe('general', function () {
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
});
describe(
'NodeBinaryCheck',
withMocks({NodeDetector}, (mocks) => {
let check = new NodeBinaryCheck();
it('autofix', function () {
check.autofix.should.not.be.ok;
});
it('diagnose - success', async function () {
mocks.NodeDetector.expects('detect').once().returns(B.resolve('/a/b/c/d'));
(await check.diagnose()).should.deep.equal({
ok: true,
optional: false,
message: 'The Node.js binary was found at: /a/b/c/d',
});
mocks.verify();
});
it('diagnose - failure', async function () {
mocks.NodeDetector.expects('detect').once().returns(B.resolve(null));
(await check.diagnose()).should.deep.equal({
ok: false,
optional: false,
message: 'The Node.js binary was NOT found!',
});
mocks.verify();
});
it('fix', async function () {
removeColors(await check.fix()).should.equal('Manually setup Node.js.');
});
})
);
describe(
'NodeVersionCheck',
withMocks({NodeDetector, tp}, (mocks) => {
let check = new NodeVersionCheck();
it('autofix', function () {
check.autofix.should.not.be.ok;
});
it('diagnose - success', async function () {
mocks.NodeDetector.expects('detect').once().returns(B.resolve('/a/b/c/d'));
mocks.tp
.expects('exec')
.once()
.returns(B.resolve({stdout: 'v14.0.0', stderr: ''}));
(await check.diagnose()).should.deep.equal({
ok: true,
optional: false,
message: 'Node version is 14.0.0',
});
mocks.verify();
});
it('diagnose - failure - insufficient version', async function () {
mocks.NodeDetector.expects('detect').once().returns(B.resolve('/a/b/c/d'));
mocks.tp
.expects('exec')
.once()
.returns(B.resolve({stdout: 'v0.12.18', stderr: ''}));
(await check.diagnose()).should.deep.equal({
ok: false,
optional: false,
message: 'Node version should be at least 14.0.0!',
});
mocks.verify();
});
it('diagnose - failure - bad output', async function () {
mocks.NodeDetector.expects('detect').once().returns(B.resolve('/a/b/c/d'));
mocks.tp
.expects('exec')
.once()
.returns(B.resolve({stdout: 'blahblahblah', stderr: ''}));
(await check.diagnose()).should.deep.equal({
ok: false,
optional: false,
message: `Unable to find node version (version = 'blahblahblah')`,
});
mocks.verify();
});
it('fix', async function () {
removeColors(await check.fix()).should.equal('Manually upgrade Node.js.');
});
})
);
describe(
'OptionalFfmpegCommandCheck',
withMocks({tp, utils}, (mocks) => {
let check = new OptionalFfmpegCommandCheck();
it('autofix', function () {
check.autofix.should.not.be.ok;
});
it('diagnose - success', async function () {
mocks.tp
.expects('exec')
.once()
.returns({
stdout: `ffmpeg version 4.1 Copyright (c) 2000-2018 the FFmpeg developers
built with Apple LLVM version 14.0.0 (clang-1000.11.45.5)
configuration: --prefix=/usr/local/Cellar/ffmpeg/4.1_1 --enable-shared --enable-pthreads --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-ffplay --enable-gpl --enable-libmp3lame --enable-libopus --enable-libsnappy --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-libxvid --enable-lzma --enable-opencl --enable-videotoolbox
libavutil 56. 22.100 / 56. 22.100
libpostproc 55. 3.100 / 55. 3.100`,
stderr: '',
});
mocks.utils.expects('resolveExecutablePath').once().returns('path/to/ffmpeg');
(await check.diagnose()).should.deep.equal({
ok: true,
optional: true,
message:
'ffmpeg is installed at: path/to/ffmpeg. ffmpeg version 4.1 Copyright (c) 2000-2018 the FFmpeg developers',
});
mocks.verify();
});
it('diagnose - failure', async function () {
mocks.utils.expects('resolveExecutablePath').once().returns(false);
(await check.diagnose()).should.deep.equal({
ok: false,
optional: true,
message: 'ffmpeg cannot be found',
});
mocks.verify();
});
it('fix', async function () {
removeColors(await check.fix()).should.equal(
'ffmpeg is needed to record screen features. Please read https://www.ffmpeg.org/ to install it'
);
});
})
);
describe(
'OptionalMjpegConsumerCommandCheck',
withMocks({tp}, (mocks) => {
let check = new OptionalMjpegConsumerCommandCheck();
it('autofix', function () {
check.autofix.should.not.be.ok;
});
it('diagnose - success', async function () {
mocks.tp
.expects('exec')
.once()
.returns({
stdout: `
{
"dependencies": {
"mjpeg-consumer": {
"version": "1.1.0",
"from": "mjpeg-consumer",
"resolved": "https://registry.npmjs.org/mjpeg-consumer/-/mjpeg-consumer-1.1.0.tgz"
}
},
"path": "/path/to/node/node/v11.4.0/lib"
}
`,
stderr: '',
});
(await check.diagnose()).should.deep.equal({
ok: true,
optional: true,
message:
'mjpeg-consumer is installed at: /path/to/node/node/v11.4.0/lib. Installed version is: 1.1.0',
});
mocks.verify();
});
it('diagnose - failure', async function () {
mocks.tp.expects('exec').once().returns({stdout: '{}', stderr: ''});
(await check.diagnose()).should.deep.equal({
ok: false,
optional: true,
message: 'mjpeg-consumer cannot be found.',
});
mocks.verify();
});
it('fix', async function () {
removeColors(await check.fix()).should.equal(
"mjpeg-consumer module is required to use MJPEG-over-HTTP features. Please install it with 'npm i -g mjpeg-consumer'."
);
});
})
);
});

View File

@@ -1,16 +0,0 @@
/**
* Remove ANSI colors/styles
*
* @param {string} text
* @returns {string} The text which has no ANSI colors/styles
*/
function removeColors(text) {
// https://stackoverflow.com/questions/25245716/remove-all-ansi-colors-styles-from-strings
return text.replace(
// eslint-disable-next-line no-control-regex
/[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g,
''
);
}
export {removeColors};

View File

@@ -1,14 +0,0 @@
import {newDoctor, Doctor, DoctorCheck} from '../../lib';
describe('index', function () {
before(async function () {
const chai = await import('chai');
chai.should();
});
it('should work', function () {
newDoctor.should.exist;
Doctor.should.exist;
DoctorCheck.should.exist;
});
});

View File

@@ -1,395 +0,0 @@
import {
fixes,
XcodeCheck,
XcodeCmdLineToolsCheck,
DevToolsSecurityCheck,
OptionalApplesimutilsCommandCheck,
OptionalIdbCommandCheck,
OptionalIOSDeployCommandCheck,
OptionalLyftCommandCheck,
} from '../../lib/ios';
import {fs, system} from '@appium/support';
import * as utils from '../../lib/utils';
import * as tp from 'teen_process';
import * as prompter from '../../lib/prompt';
import FixSkippedError from '../../lib/doctor';
import log from '../../lib/logger';
import B from 'bluebird';
import {withMocks, withSandbox, stubLog} from '@appium/test-support';
import {removeColors} from './helper';
describe('ios', function () {
before(async function () {
const chai = await import('chai');
const chaiAsPromised = await import('chai-as-promised');
chai.use(chaiAsPromised.default);
chai.should();
});
describe(
'XcodeCheck',
withMocks({tp, fs}, (mocks) => {
let check = new XcodeCheck();
it('autofix', function () {
check.autofix.should.not.be.ok;
});
it('diagnose - success', async function () {
// xcrun
mocks.tp.expects('exec').once().resolves({
stdout: 'usage: simctl [--set <path>] [--profiles <path>] <subcommand> ...',
stderr: '',
});
// xcode-select
mocks.tp
.expects('exec')
.once()
.returns(B.resolve({stdout: '/a/b/c/d\n', stderr: ''}));
mocks.fs.expects('exists').once().resolves(true);
(await check.diagnose()).should.deep.equal({
ok: true,
optional: false,
message: 'Xcode is installed at: /a/b/c/d',
});
mocks.verify();
});
it('diagnose - failure - xcode-select', async function () {
// xcrun
mocks.tp
.expects('exec')
.once()
.returns(
B.resolve({
stdout: 'usage: simctl [--set <path>] [--profiles <path>] <subcommand> ...',
stderr: '',
})
);
// xcode-select
mocks.tp.expects('exec').once().rejects(new Error('Something wrong!'));
(await check.diagnose()).should.deep.equal({
ok: false,
optional: false,
message: 'Xcode is NOT installed!',
});
mocks.verify();
});
it('diagnose - failure - path not exists', async function () {
// xcrun
mocks.tp
.expects('exec')
.once()
.returns(
B.resolve({
stdout: 'usage: simctl [--set <path>] [--profiles <path>] <subcommand> ...',
stderr: '',
})
);
// xcode-select
mocks.tp
.expects('exec')
.once()
.returns(B.resolve({stdout: '/a/b/c/d\n', stderr: ''}));
mocks.fs.expects('exists').once().resolves(false);
(await check.diagnose()).should.deep.equal({
ok: false,
optional: false,
message: "Xcode cannot be found at '/a/b/c/d'!",
});
mocks.verify();
});
it('diagnose - failure - xcrun does not work', async function () {
// xcrun
mocks.tp
.expects('exec')
.once()
.rejects(
new Error(
'xcrun: error: unable to find utility "simctl", not a developer tool or in PATH'
)
);
// no xcode-select
(await check.diagnose()).should.deep.equal({
ok: false,
optional: false,
message: 'Error running xcrun simctl',
});
mocks.verify();
});
it('fix', async function () {
removeColors(await check.fix()).should.equal(
"Manually install Xcode, and make sure 'xcode-select -p' command shows proper path like '/Applications/Xcode.app/Contents/Developer'"
);
});
})
);
describe(
'XcodeCmdLineToolsCheck',
withSandbox({mocks: {tp, utils, prompter, system}}, (S) => {
let check = new XcodeCmdLineToolsCheck();
it('autofix', function () {
check.autofix.should.be.ok;
});
it('diagnose - success', async function () {
S.mocks.tp
.expects('exec')
.once()
.returns(
B.resolve({
stdout: '/Applications/Xcode.app/Contents/Developer\n',
stderr: '',
})
);
(await check.diagnose()).should.deep.equal({
ok: true,
optional: false,
message:
'Xcode Command Line Tools are installed in: /Applications/Xcode.app/Contents/Developer',
});
S.verify();
});
it('diagnose - failure - pkgutil crash', async function () {
S.mocks.tp.expects('exec').once().throws(new Error('Something wrong!'));
(await check.diagnose()).should.deep.equal({
ok: false,
optional: false,
message: 'Xcode Command Line Tools are NOT installed!',
});
S.verify();
});
it('diagnose - failure - xcode-select -p returns status 2', async function () {
S.mocks.tp.expects('exec').once().throws(new Error());
(await check.diagnose()).should.deep.equal({
ok: false,
optional: false,
message: 'Xcode Command Line Tools are NOT installed!',
});
S.verify();
});
it('fix - yes', async function () {
let logStub = stubLog(S.sandbox, log, {stripColors: true});
S.mocks.tp
.expects('exec')
.once()
.returns(B.resolve({stdout: '', stderr: ''}));
S.mocks.prompter.expects('fixIt').once().resolves('yes');
await check.fix();
S.verify();
logStub.output.should.equal(
['info: The following command need be executed: xcode-select --install'].join('\n')
);
});
it('fix - no', async function () {
let logStub = stubLog(S.sandbox, log, {stripColors: true});
S.mocks.tp.expects('exec').never();
S.mocks.prompter.expects('fixIt').once().resolves('no');
await check.fix().should.be.rejectedWith(FixSkippedError);
S.verify();
logStub.output.should.equal(
[
'info: The following command need be executed: xcode-select --install',
'info: Skipping. You will need to install Xcode manually.',
].join('\n')
);
});
})
);
describe(
'DevToolsSecurityCheck',
withMocks({fixes, tp}, (mocks) => {
let check = new DevToolsSecurityCheck();
it('diagnose - success', async function () {
mocks.tp
.expects('exec')
.once()
.returns(B.resolve({stdout: '1234 enabled\n', stderr: ''}));
(await check.diagnose()).should.deep.equal({
ok: true,
optional: false,
message: 'DevToolsSecurity is enabled.',
});
mocks.verify();
});
it('diagnose - failure - DevToolsSecurity crash', async function () {
mocks.tp.expects('exec').once().rejects(new Error('Something wrong!'));
(await check.diagnose()).should.deep.equal({
ok: false,
optional: false,
message: 'DevToolsSecurity is NOT enabled!',
});
mocks.verify();
});
it('diagnose - failure - not enabled', async function () {
mocks.tp
.expects('exec')
.once()
.returns(B.resolve({stdout: '1234 abcd\n', stderr: ''}));
(await check.diagnose()).should.deep.equal({
ok: false,
optional: false,
message: 'DevToolsSecurity is NOT enabled!',
});
mocks.verify();
});
})
);
describe(
'OptionalLyftCommandCheck',
withMocks({tp, utils}, (mocks) => {
let check = new OptionalLyftCommandCheck();
it('autofix', function () {
check.autofix.should.not.be.ok;
});
it('diagnose - success', async function () {
mocks.utils
.expects('resolveExecutablePath')
.once()
.returns('path/to/set-simulator-location');
(await check.diagnose()).should.deep.equal({
ok: true,
optional: true,
message: 'set-simulator-location is installed',
});
mocks.verify();
});
it('diagnose - failure', async function () {
mocks.utils.expects('resolveExecutablePath').once().returns(false);
(await check.diagnose()).should.deep.equal({
ok: false,
optional: true,
message: 'set-simulator-location is not installed',
});
mocks.verify();
});
it('fix', async function () {
removeColors(await check.fix()).should.equal(
'set-simulator-location is needed to set location for Simulator. ' +
'Please read https://github.com/lyft/set-simulator-location to install it'
);
});
})
);
describe(
'OptionalIdbCommandCheck',
withMocks({tp, utils}, (mocks) => {
let check = new OptionalIdbCommandCheck();
it('autofix', function () {
check.autofix.should.not.be.ok;
});
it('diagnose - success', async function () {
mocks.utils.expects('resolveExecutablePath').once().returns('path/to/idb');
mocks.utils.expects('resolveExecutablePath').once().returns('path/to/idb_cpmpanion');
(await check.diagnose()).should.deep.equal({
ok: true,
optional: true,
message: 'idb and idb_companion are installed',
});
mocks.verify();
});
it('diagnose - failure because of no idb_companion and idb', async function () {
mocks.utils.expects('resolveExecutablePath').once().returns(false);
mocks.utils.expects('resolveExecutablePath').once().returns(false);
(await check.diagnose()).should.deep.equal({
ok: false,
optional: true,
message: 'idb and idb_companion are not installed',
});
mocks.verify();
});
it('diagnose - failure because of no idb_companion', async function () {
mocks.utils.expects('resolveExecutablePath').once().returns('path/to/idb');
mocks.utils.expects('resolveExecutablePath').once().returns(false);
(await check.diagnose()).should.deep.equal({
ok: false,
optional: true,
message: 'idb_companion is not installed',
});
mocks.verify();
});
it('diagnose - failure because of no idb', async function () {
mocks.utils.expects('resolveExecutablePath').once().returns(false);
mocks.utils.expects('resolveExecutablePath').once().returns('path/to/idb_cpmpanion');
(await check.diagnose()).should.deep.equal({
ok: false,
optional: true,
message: 'idb is not installed',
});
mocks.verify();
});
it('fix', async function () {
removeColors(await check.fix()).should.equal(
'Why idb is needed and how to install it: https://git.io/JnxQc'
);
});
})
);
describe(
'OptionalApplesimutilsCommandCheck',
withMocks({tp, utils}, (mocks) => {
let check = new OptionalApplesimutilsCommandCheck();
it('autofix', function () {
check.autofix.should.not.be.ok;
});
it('diagnose - success', async function () {
mocks.utils.expects('resolveExecutablePath').once().returns('path/to/applesimutils');
mocks.tp.expects('exec').once().returns({stdout: 'vxx.xx.xx', stderr: ''});
(await check.diagnose()).should.deep.equal({
ok: true,
optional: true,
message:
'applesimutils is installed at: path/to/applesimutils. Installed versions are: vxx.xx.xx',
});
mocks.verify();
});
it('diagnose - failure', async function () {
mocks.utils.expects('resolveExecutablePath').once().returns(false);
(await check.diagnose()).should.deep.equal({
ok: false,
optional: true,
message: 'applesimutils cannot be found',
});
mocks.verify();
});
it('fix', async function () {
removeColors(await check.fix()).should.equal(
'Why applesimutils is needed and how to install it: https://github.com/appium/appium-xcuitest-driver/blob/master/docs/execute-methods.md#mobile-setpermission'
);
});
})
);
describe(
'OptionalIOSDeployCommandCheck',
withMocks({tp, utils}, (mocks) => {
let check = new OptionalIOSDeployCommandCheck();
it('autofix', function () {
check.autofix.should.not.be.ok;
});
it('diagnose - success', async function () {
mocks.utils.expects('resolveExecutablePath').once().returns('path/to/ios-deploy');
mocks.tp.expects('exec').once().returns({stdout: '1.9.4', stderr: ''});
(await check.diagnose()).should.deep.equal({
ok: true,
optional: true,
message: 'ios-deploy is installed at: path/to/ios-deploy. Installed version is: 1.9.4',
});
mocks.verify();
});
it('diagnose - failure', async function () {
mocks.utils.expects('resolveExecutablePath').once().returns(false);
(await check.diagnose()).should.deep.equal({
ok: false,
optional: true,
message: 'ios-deploy cannot be found',
});
mocks.verify();
});
it('fix', async function () {
removeColors(await check.fix()).should.equal(
'ios-deploy is used as a fallback command to install iOS applications to real device. Please read https://github.com/ios-control/ios-deploy/ to install it'
);
});
})
);
});

View File

@@ -1,48 +0,0 @@
import {fs, system} from '@appium/support';
import NodeDetector from '../../lib/node-detector';
import B from 'bluebird';
import {withSandbox} from '@appium/test-support';
describe(
'NodeDetector',
withSandbox({mocks: {fs, system}}, (S) => {
let expect;
before(async function () {
const chai = await import('chai');
chai.should();
expect = chai.expect;
});
it('retrieveUsingSystemCall - success - where returns multiple lines ', async function () {
S.mocks.fs.expects('which').once().returns(B.resolve('/a/b/node.exe'));
S.mocks.fs.expects('exists').once().returns(B.resolve(true));
(await NodeDetector.retrieveUsingSystemCall()).should.equal('/a/b/node.exe');
S.verify();
});
it('retrieveUsingSystemCall - success', async function () {
S.mocks.fs.expects('which').once().returns(B.resolve('/a/b/c/d/node'));
S.mocks.fs.expects('exists').once().returns(B.resolve(true));
(await NodeDetector.retrieveUsingSystemCall()).should.equal('/a/b/c/d/node');
S.verify();
});
it('retrieveUsingSystemCall - failure - path not found ', async function () {
S.mocks.fs.expects('which').once().throws(Error('not found: carthage'));
expect(await NodeDetector.retrieveUsingSystemCall()).to.be.a('null');
S.verify();
});
it('retrieveUsingSystemCall - failure - path not exist', async function () {
S.mocks.fs.expects('which').once().returns(B.resolve('/a/b/c/d'));
S.mocks.fs.expects('exists').once().returns(B.resolve(false));
expect(await NodeDetector.retrieveUsingSystemCall()).to.be.a('null');
});
it('checkForNodeBinary - failure', async function () {
S.mocks.NodeDetector = S.sandbox.mock(NodeDetector);
S.mocks.NodeDetector.expects('retrieveUsingSystemCall').once().returns(null);
expect(await NodeDetector.detect()).to.be.a('null');
S.verify();
});
})
);

View File

@@ -1,48 +0,0 @@
import {fixIt, clear} from '../../lib/prompt';
import * as utils from '../../lib/utils';
import {withMocks} from '@appium/test-support';
import B from 'bluebird';
describe(
'prompt',
withMocks({utils}, (mocks) => {
before(async function () {
const chai = await import('chai');
chai.should();
});
it('fixit - yes', async function () {
clear();
mocks.utils
.expects('prompt')
.once()
.returns(B.resolve({confirmation: 'yes'}));
(await fixIt()).should.equal('yes');
mocks.verify();
});
it('fixit always ', async function () {
clear();
mocks.utils
.expects('prompt')
.once()
.returns(B.resolve({confirmation: 'always'}));
(await fixIt()).should.equal('yes');
(await fixIt()).should.equal('yes');
(await fixIt()).should.equal('yes');
mocks.verify();
});
it('fixit never ', async function () {
clear();
mocks.utils
.expects('prompt')
.once()
.returns(B.resolve({confirmation: 'never'}));
(await fixIt()).should.equal('no');
(await fixIt()).should.equal('no');
(await fixIt()).should.equal('no');
mocks.verify();
});
})
);

View File

@@ -1,36 +0,0 @@
import {configureBinaryLog, resetLog} from '../../lib/utils';
import {fs} from '@appium/support';
import path from 'path';
import {Doctor} from '../../lib/doctor';
describe('utils', function () {
before(async function () {
const chai = await import('chai');
chai.should();
});
it('fs.readFile', async function () {
(await fs.readFile(path.resolve(__dirname, 'fixtures', 'wow.txt'), 'utf8')).should.include(
'WOW'
);
});
it('fs.exists', async function () {
(await fs.exists(path.resolve(__dirname, 'fixtures', 'wow.txt'))).should.be.ok;
(await fs.exists(path.resolve(__dirname, 'fixtures', 'notwow.txt'))).should.not.be.ok;
});
it('Should handle logs through onLogMessage callback', async function () {
function onLogMessage(level, prefix, msg) {
`${level} ${prefix} ${msg}`.should.include('AppiumDoctor');
}
configureBinaryLog({onLogMessage});
let doctor = new Doctor();
try {
await doctor.run();
} finally {
resetLog();
}
});
});

View File

@@ -1,12 +0,0 @@
{
"extends": "@appium/tsconfig/tsconfig.json",
"compilerOptions": {
"outDir": "build",
"checkJs": true,
"paths": {
"@appium/support": ["../support"]
}
},
"include": ["lib", "bin"],
"references": [{"path": "../support"}]
}

View File

@@ -27,7 +27,6 @@
"get-stream",
"globby",
"got",
"inquirer",
"log-symbols",
"ora",
"p-retry",

16
scripts/doctor-stub.mjs Normal file
View File

@@ -0,0 +1,16 @@
import {logger} from '@appium/support';
const log = logger.getLogger('Doctor CLI');
const DEV_DOC_URL = 'https://github.com/appium/appium/blob/master/packages/appium/docs/en/developing/build-doctor-checks.md';
async function main() {
log.warn(`The Appium server's 'doctor' CLI utility has been removed`);
log.warn(
`Please use the 'doctor' script defined for the specific driver or plugin, ` +
`for example 'appium driver doctor uiautomator2'`
);
log.info(`Check ${DEV_DOC_URL} if you would like to contribute to existing doctor checks`);
process.exit(1);
}
(async () => await main())();

View File

@@ -62,9 +62,6 @@
{
"path": "packages/fake-driver"
},
{
"path": "packages/doctor"
},
{
"path": "packages/strongbox"
},