test: add e2e tests for driver cli
MODIFY
gulpfile.js
gulpfile.js
@@ -47,6 +47,7 @@ boilerplate({
test: {
files: ['${testDir}/**/*-specs.js']
},
+ testTimeout: 160000,
preCommitTasks: ['eslint', 'once'],
});

MODIFY
lib/cli-utils.js
lib/cli-utils.js
@@ -11,7 +11,7 @@ const JSON_SPACES = 4;
*/
function errAndQuit (json, msg) {
if (json) {
- console.log(JSON.stringify({error: `${msg}`}), null, JSON_SPACES);
+ console.log(JSON.stringify({error: `${msg}`}, null, JSON_SPACES));
} else {
console.error(`${msg}`.red);
}

MODIFY
lib/driver-cli.js
lib/driver-cli.js
@@ -257,7 +257,7 @@ class DriverCommand {
await this.config.removeDriver(driver);
}
log(this.isJsonOutput, `Successfully uninstalled driver '${driver}'`.green);
- return true;
+ return this.config.installedDrivers;
}
update (/*{driver}*/) {

MODIFY
lib/driver-config.js
lib/driver-config.js
@@ -46,8 +46,11 @@ export default class DriverConfig {
`cache file (${this.configFile}). Ensure it exists and is ` +
`readable. Specific error: ${err.message}`);
}
- if (!await fs.access(this.appiumHome)) {
- // if appium home exists but the dir is not readable/writable
+
+ // if appium home exists but the dir is not readable/writable, fs.access will error
+ try {
+ await fs.access(this.appiumHome);
+ } catch {
throw new Error(`Appium could not read or write from the Appium Home directory ` +
`(${this.appiumHome}). Please ensure it is writable.`);
}

ADD
test/cli-e2e-specs.js
+import path from 'path';
+import { exec } from 'teen_process';
+import chai from 'chai';
+import chaiAsPromised from 'chai-as-promised';
+import { tempDir, fs, mkdirp, util } from 'appium-support';
+import { KNOWN_DRIVERS } from '../lib/drivers';
+
+chai.should();
+chai.use(chaiAsPromised);
+const cwd = path.resolve(__dirname, '..', '..');
+
+describe('Driver CLI', function () {
+ let appiumHome;
+
+ before(async function () {
+ appiumHome = await tempDir.openDir();
+ });
+
+ after(async function () {
+ await fs.rimraf(appiumHome);
+ });
+
+ async function clear () {
+ await fs.rimraf(appiumHome);
+ await mkdirp(appiumHome);
+ }
+
+ async function run (driverCmd, args = [], raw = false) {
+ args = [...args, '--appium-home', appiumHome];
+ const ret = await exec('node', ['.', 'driver', driverCmd, ...args], {cwd});
+ if (raw) {
+ return ret;
+ }
+ return ret.stdout;
+ }
+
+ describe('list', function () {
+ it('should list available drivers', async function () {
+ const stdout = await run('list');
+ for (const d of Object.keys(KNOWN_DRIVERS)) {
+ stdout.should.match(new RegExp(`${d}.+[not installed]`));
+ }
+ });
+ it('should list available drivers in json format', async function () {
+ const driverData = JSON.parse(await run('list', ['--json']));
+ for (const d of Object.keys(KNOWN_DRIVERS)) {
+ driverData[d].should.eql({installed: false, pkgName: KNOWN_DRIVERS[d]});
+ }
+ });
+ it('should allow filtering by installed drivers', async function () {
+ const out = await run('list', ['--installed', '--json']);
+ JSON.parse(out).should.eql({});
+ });
+ it('should show updates for installed drivers with --updates', async function () {
+ await clear();
+ await run('install', ['appium-fake-driver@0.9.0', '--source', 'npm', '--json']);
+ const {fake} = JSON.parse(await run('list', ['--updates', '--json']));
+ util.compareVersions(fake.updateVersion, '>', '0.9.0').should.be.true;
+ const stdout = await run('list', ['--updates']);
+ stdout.should.match(new RegExp(`fake.+[${fake.updateVersion} available]`));
+ });
+ });
+
+ describe('install', function () {
+ it('should install a driver from the list of known drivers', async function () {
+ await clear();
+ const ret = JSON.parse(await run('install', ['uiautomator2', '--json']));
+ ret.uiautomator2.pkgName.should.eql('appium-uiautomator2-driver');
+ ret.uiautomator2.installType.should.eql('npm');
+ ret.uiautomator2.installSpec.should.eql('uiautomator2');
+ const list = JSON.parse(await run('list', ['--installed', '--json']));
+ delete list.uiautomator2.installed;
+ list.should.eql(ret);
+ });
+ it('should install a driver from npm', async function () {
+ await clear();
+ const ret = JSON.parse(await run('install', ['appium-fake-driver', '--source', 'npm', '--json']));
+ ret.fake.pkgName.should.eql('appium-fake-driver');
+ ret.fake.installType.should.eql('npm');
+ ret.fake.installSpec.should.eql('appium-fake-driver');
+ const list = JSON.parse(await run('list', ['--installed', '--json']));
+ delete list.fake.installed;
+ list.should.eql(ret);
+ });
+ it('should install a driver from npm with a specific version/tag', async function () {
+ await clear();
+ const ret = JSON.parse(await run('install', ['appium-fake-driver@0.9.0', '--source', 'npm', '--json']));
+ ret.fake.pkgName.should.eql('appium-fake-driver');
+ ret.fake.installType.should.eql('npm');
+ ret.fake.installSpec.should.eql('appium-fake-driver@0.9.0');
+ const list = JSON.parse(await run('list', ['--installed', '--json']));
+ delete list.fake.installed;
+ list.should.eql(ret);
+ });
+ it('should install a driver from github', async function () {
+ await clear();
+ const ret = JSON.parse(await run('install', ['appium/appium-fake-driver', '--source', 'github', '--json']));
+ ret.fake.pkgName.should.eql('appium-fake-driver');
+ ret.fake.installType.should.eql('github');
+ ret.fake.installSpec.should.eql('appium/appium-fake-driver');
+ const list = JSON.parse(await run('list', ['--installed', '--json']));
+ delete list.fake.installed;
+ list.should.eql(ret);
+ });
+ it('should install a driver from git', async function () {
+ await clear();
+ const ret = JSON.parse(await run('install', ['git+https://github.com/appium/appium-fake-driver.git', '--source', 'git', '--json']));
+ ret.fake.pkgName.should.eql('appium-fake-driver');
+ ret.fake.installType.should.eql('git');
+ ret.fake.installSpec.should.eql('git+https://github.com/appium/appium-fake-driver');
+ const list = JSON.parse(await run('list', ['--installed', '--json']));
+ delete list.fake.installed;
+ list.should.eql(ret);
+ });
+ it('should install a driver from a local npm module', async function () {
+ await clear();
+ // take advantage of the fact that we know we have fake driver installed as a dependency in
+ // this module, so we know its local path on disk
+ const localFakeDriverPath = path.resolve(__dirname, '..', '..', 'node_modules', 'appium-fake-driver');
+ const ret = JSON.parse(await run('install', [localFakeDriverPath, '--source', 'local', '--json']));
+ ret.fake.pkgName.should.eql('appium-fake-driver');
+ ret.fake.installType.should.eql('local');
+ ret.fake.installSpec.should.eql(localFakeDriverPath);
+ const list = JSON.parse(await run('list', ['--installed', '--json']));
+ delete list.fake.installed;
+ list.should.eql(ret);
+ });
+ });
+
+ describe('uninstall', function () {
+ it('should uninstall a driver based on its driver name', async function () {
+ await clear();
+ const ret = JSON.parse(await run('install', ['appium-fake-driver', '--source', 'npm', '--json']));
+ const installPath = path.resolve(appiumHome, ret.fake.installPath);
+ await fs.exists(installPath).should.eventually.be.true;
+ let list = JSON.parse(await run('list', ['--installed', '--json']));
+ list.fake.installed.should.be.true;
+ const uninstall = JSON.parse(await run('uninstall', ['fake', '--json']));
+ uninstall.should.not.have.key('fake');
+ await fs.exists(installPath).should.eventually.be.false;
+ });
+ });
+});

test: add e2e tests for driver cli