Skip to content

Commit

Permalink
Allows --desired-caps to be passed a filename
Browse files Browse the repository at this point in the history
The --desired-caps flag can now be passed the name of a JSON file as an
argument. This also adds an alias for the flag, `-dc`, and fixes tests.
  • Loading branch information
usmonster committed May 1, 2016
1 parent 00041de commit 734a96b
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 10 deletions.
5 changes: 4 additions & 1 deletion docs/en/writing-running-appium/default-capabilities-arg.md
Expand Up @@ -3,10 +3,13 @@
Appium 1.5 does away with most CLI flags; the remainder can be converted into JSON and made part of the `--default-capabilities` flag. For example:

```
# raw JSON as an argument
--default-capabilities '{"app": "myapp.app", "deviceName": "iPhone Simulator"}'
# or the name of a JSON file
--default-capabilities /path/to/file.json
```

**Windows users** will need to escape the quotes: `--default-capabilities "{\"app\": \"myapp.app\"}"`
**Windows users** will need to escape the quotes in JSON passed on the command line: `--default-capabilities "{\"app\": \"myapp.app\"}"`



Expand Down
8 changes: 4 additions & 4 deletions docs/en/writing-running-appium/server-args.md
@@ -1,10 +1,10 @@
## Appium server arguments
# Appium server arguments

Many Appium 1.5 server arguments have been deprecated in favor of the [--default-capabilities flag](/docs/en/writing-running-appium/default-capabilities-arg.md).

Usage: `node . [flags]`

### Server flags
## Server flags
All flags are optional, but some are required in conjunction with certain others.


Expand Down Expand Up @@ -43,7 +43,6 @@ All flags are optional, but some are required in conjunction with certain others
|`--chromedriver-executable`|null|ChromeDriver executable full path||
|`--show-config`|false|Show info about the appium server configuration and exit||
|`--no-perms-check`|false|Bypass Appium's checks to ensure we can read/write necessary files||
|`--command-timeout`|60|The default command timeout for the server to use for all sessions (in seconds and should be less than 2147483). Will still be overridden by newCommandTimeout cap||
|`--strict-caps`|false|Cause sessions to fail if desired caps are sent in that Appium does not recognize as valid for the selected device||
|`--isolate-sim-device`|false|Xcode 6 has a bug on some platforms where a certain simulator can only be launched without error if all other simulator devices are first deleted. This option causes Appium to delete all devices other than the one being used by Appium. Note that this is a permanent deletion, and you are responsible for using simctl or xcode to manage the categories of devices used with Appium.||
|`--tmp`|null|Absolute path to directory Appium can use to manage temporary files, like built-in iOS apps it needs to move around. On *nix/Mac defaults to /tmp, on Windows defaults to C:\Windows\Temp||
Expand All @@ -52,7 +51,8 @@ All flags are optional, but some are required in conjunction with certain others
|`--suppress-adb-kill-server`|false|(Android-only) If set, prevents Appium from killing the adb server instance||
|`--async-trace`|false|Add long stack traces to log entries. Recommended for debugging only.||
|`--webkit-debug-proxy-port`|27753|(IOS-only) Local port used for communication with ios-webkit-debug-proxy|`--webkit-debug-proxy-port 27753`|
|`--default-capabilities`|{}|Set the default desired capabilities, which will be set on each session unless overridden by received capabilities. [More infomation](/docs/en/writing-running-appium/default-capabilities-arg.md). |`--default-capabilities '{"app": "myapp.app", "deviceName": "iPhone Simulator"}'`|
|`-dc`, `--default-capabilities`|{}|Set the default desired capabilities, which will be set on each session unless overridden by received capabilities.|`--default-capabilities [ '{"app": "myapp.app", "deviceName": "iPhone Simulator"}' | /path/to/caps.json ]`|
|`--command-timeout`|60|[DEPRECATED] No effect. This used to be the default command timeout for the server to use for all sessions (in seconds and should be less than 2147483). Use newCommandTimeout cap instead||
|`-k`, `--keep-artifacts`|false|[DEPRECATED] - no effect, trace is now in tmp dir by default and is cleared before each run. Please also refer to the --trace-dir flag.||
|`--platform-name`|null|[DEPRECATED] - Name of the mobile platform: iOS, Android, or FirefoxOS|`--platform-name iOS`|
|`--platform-version`|null|[DEPRECATED] - Version of the mobile platform|`--platform-version 7.1`|
Expand Down
23 changes: 20 additions & 3 deletions lib/parser.js
@@ -1,3 +1,4 @@
import fs from 'fs';
import path from 'path';
import _ from 'lodash';
import { ArgumentParser } from 'argparse';
Expand Down Expand Up @@ -334,12 +335,13 @@ const args = [
help: '(IOS-only) Local port used for communication with ios-webkit-debug-proxy'
}],

[['--default-capabilities'], {
[['-dc', '--default-capabilities'], {
dest: 'defaultCapabilities',
defaultValue: {},
type: JSON.parse,
type: parseDefaultCaps,
required: false,
example: '{"app": "myapp.app", "deviceName": "iPhone Simulator"}',
example: '[ \'{"app": "myapp.app", "deviceName": "iPhone Simulator"}\' ' +
'| /path/to/caps.json ]',
help: 'Set the default desired capabilities, which will be set on each ' +
'session unless overridden by received capabilities.'
}],
Expand Down Expand Up @@ -731,6 +733,21 @@ function updateParseArgsForDefaultCapabilities (parser) {
};
}

function parseDefaultCaps (caps) {
try {
if (fs.statSync(caps).isFile()) {
caps = fs.readFileSync(caps, 'utf8');
}
} catch (err) {
// not a file, or not readable
}
caps = JSON.parse(caps);
if (!_.isPlainObject(caps)) {
throw 'Invalid format for default capabilities';
}
return caps;
}

function getParser () {
let parser = new ArgumentParser({
version: pkgObj.version,
Expand Down
3 changes: 3 additions & 0 deletions test/fixtures/caps.json
@@ -0,0 +1,3 @@
{
"a": "b"
}
17 changes: 15 additions & 2 deletions test/parser-specs.js
Expand Up @@ -7,6 +7,7 @@ const should = chai.should();

describe('Parser', () => {
let p = getParser();
p.debug = true; // throw instead of exit on error; pass as option instead?
it('should return an arg parser', () => {
should.exist(p.parseArgs);
p.parseArgs([]).should.have.property('port');
Expand All @@ -20,14 +21,26 @@ describe('Parser', () => {
}
});
it('should throw an error with unknown argument', () => {
(() => {p.parseArgs(['--apple']);}).should.throw;
(() => {p.parseArgs(['--apple']);}).should.throw();
});
it('should parse default capabilities correctly', () => {
it('should parse default capabilities correctly from a string', () => {
let defaultCapabilities = {a: 'b'};
let args = p.parseArgs(['--default-capabilities',
JSON.stringify(defaultCapabilities)]);
args.defaultCapabilities.should.eql(defaultCapabilities);
});
it('should parse default capabilities correctly from a file', () => {
let defaultCapabilities = {a: 'b'};
let args = p.parseArgs(['--default-capabilities',
'test/fixtures/caps.json']);
args.defaultCapabilities.should.eql(defaultCapabilities);
});
it('should throw an error with invalid arg to default capabilities', () => {
(() => {p.parseArgs(['-dc', '42']);}).should.throw();
(() => {p.parseArgs(['-dc', 'false']);}).should.throw();
(() => {p.parseArgs(['-dc', 'null']);}).should.throw();
(() => {p.parseArgs(['-dc', 'does/not/exist.json']);}).should.throw();
});
it('should parse args that are caps into default capabilities', () => {
let defaultCapabilities = {localizableStringsDir: '/my/dir'};
let args = p.parseArgs(['--localizable-strings-dir', '/my/dir']);
Expand Down

0 comments on commit 734a96b

Please sign in to comment.