mirror of
https://github.com/appium/appium.git
synced 2026-04-28 14:30:27 -05:00
Render commands markdown using YML (#9260)
* Render commands markdown using YML * Made directory 'commands-yml' which contains: * .babelrc to transpile the scripts * parse.js which renders the markdown * template.md which is a handlebars template that the yml gets passed to * validator.js which validates the yml data * The rendering works by translating the yml to js, validating the js and then passing the data to template.md (which uses handlebars) * The directory `/commands-yml/commands` gets rendered and then copied to `/docs/en/commands` as markdown * Uses babel-node to run the script * Uses validatejs to validate the javascript * Template.yml is just a sample * Infers the platform and appium support range from driver * For example, if you put in 'xcuitest: true' it will infer that platform support is 9.3+ and Appium Version is 1.6.0
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"presets": ["env"]
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
---
|
||||
name: 'Template'
|
||||
|
||||
description:
|
||||
>
|
||||
An indepth description
|
||||
of what this command does
|
||||
example_usage:
|
||||
java:
|
||||
|
|
||||
MobileElement el = driver.findElementByAccessibilityId("SomeId");
|
||||
el.click();
|
||||
python:
|
||||
|
|
||||
el = self.driver.find_element_by_accessibility_id('SomeId')
|
||||
el.click();
|
||||
javascript_wd:
|
||||
|
|
||||
await driver.status();
|
||||
javascript_wdio:
|
||||
|
|
||||
await driver.status();
|
||||
ruby:
|
||||
|
|
||||
# Ruby Code here
|
||||
php:
|
||||
|
|
||||
# PHP Code here
|
||||
csharp:
|
||||
|
|
||||
// CSharp Code here
|
||||
|
||||
client_docs:
|
||||
java: "https://seleniumhq.github.io/selenium/docs/api/java/org/openqa/selenium/WebElement.html#click--"
|
||||
python: "https://github.com/appium/python-client"
|
||||
javascript_wdio: "http://webdriver.io/index.html"
|
||||
javascript_wd: "https://github.com/admc/wd/releases"
|
||||
ruby: "https://github.com/appium/ruby_lib/releases/latest"
|
||||
php: "https://github.com/appium/php-client/releases/latest-"
|
||||
csharp: "https://github.com/appium/appium" # TODO
|
||||
|
||||
# Driver support by platform
|
||||
driver_support:
|
||||
ios:
|
||||
xcuitest:
|
||||
platform_min: '1.2'
|
||||
platform_max: '9.3'
|
||||
appium_min: '1.7'
|
||||
appium_max: '1.9'
|
||||
driver_min: '1.1'
|
||||
driver_max: '9.9'
|
||||
uiautomation:
|
||||
platform_min: '1.0'
|
||||
android:
|
||||
uiautomator2:
|
||||
platform_min: '8.0'
|
||||
uiautomator: true
|
||||
mac:
|
||||
mac:
|
||||
platform_min: '?' # TODO
|
||||
client_support:
|
||||
java:
|
||||
min: 1.2
|
||||
max: 2.1
|
||||
python:
|
||||
min: 2
|
||||
ruby: true # If true, means it supports all
|
||||
php: false # If false(y), means it is not supported
|
||||
|
||||
|
||||
# Information about the HTTP endpoints
|
||||
endpoint:
|
||||
url: /wd/hub/session/:session_id/element/:element_id/click
|
||||
method: 'POST'
|
||||
url_parameters:
|
||||
- name: session_id
|
||||
description: ID of the session
|
||||
- name: element_id
|
||||
description: ID of the element
|
||||
json_parameters:
|
||||
- name: item
|
||||
type: Object
|
||||
description: Description of Item
|
||||
- name: item.1 # Use dot notation for nested items
|
||||
type: String # Type is optional
|
||||
description: Item One description
|
||||
response:
|
||||
- name: build.version # Use dot notation for nested JSON parameters
|
||||
type: string # JS type
|
||||
description: A generic release label (i.e. "2.0rc3")
|
||||
|
||||
# Links to specifications. Should link to at least one specification
|
||||
specifications:
|
||||
w3c: https://www.w3.org/TR/webdriver/#element-click
|
||||
jsonwp: https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#sessionsessionidelementidclick
|
||||
|
||||
# Other relevant links
|
||||
links:
|
||||
- name: Google
|
||||
url: http://www.google.com
|
||||
@@ -0,0 +1,117 @@
|
||||
/* eslint-disable no-console */
|
||||
import path from 'path';
|
||||
import yaml from 'yaml-js';
|
||||
import { fs } from 'appium-support';
|
||||
import validate from 'validate.js';
|
||||
import Handlebars from 'handlebars';
|
||||
import replaceExt from 'replace-ext';
|
||||
import _ from 'lodash';
|
||||
import { asyncify } from 'asyncbox';
|
||||
import validator from './validator';
|
||||
|
||||
// What range of platforms do the driver's support
|
||||
const platformRanges = {
|
||||
xcuitest: ['9.3'],
|
||||
uiautomation: ['8.0', '9.3'],
|
||||
uiautomator2: ['?'],
|
||||
uiautomator: ['4.2'],
|
||||
windows: ['10'],
|
||||
mac: ['?'], // TODO
|
||||
};
|
||||
|
||||
// When was the driver supported in Appium?
|
||||
const appiumRanges = {
|
||||
xcuitest: ['1.6.0'],
|
||||
uiautomator2: ['1.6.0'],
|
||||
espresso: ['?'],
|
||||
windows: ['1.6.0'],
|
||||
mac: ['1.6.4'],
|
||||
};
|
||||
|
||||
|
||||
// Create Handlebars helper that shows a version range
|
||||
Handlebars.registerHelper('versions', (object, name, driverName) => {
|
||||
if (!object) {
|
||||
return 'None';
|
||||
}
|
||||
|
||||
if (!_.isObject(object)) {
|
||||
object = {};
|
||||
}
|
||||
|
||||
let min = object[name ? `${name}_min` : 'min'];
|
||||
let max = object[name ? `${name}_max` : 'max'];
|
||||
|
||||
if (!min) {
|
||||
if (name === 'appium' && appiumRanges[driverName]) {
|
||||
min = appiumRanges[driverName][0];
|
||||
} else if (name === 'platform' && platformRanges[driverName]) {
|
||||
min = platformRanges[driverName][0];
|
||||
}
|
||||
}
|
||||
|
||||
if (!max) {
|
||||
if (name === 'appium' && appiumRanges[driverName]) {
|
||||
max = appiumRanges[driverName][1];
|
||||
} else if (name === 'platform' && platformRanges[driverName]) {
|
||||
max = platformRanges[driverName][1];
|
||||
}
|
||||
}
|
||||
|
||||
if (!min && !max) {
|
||||
return 'All';
|
||||
} else if (!max) {
|
||||
return `${min}+`;
|
||||
} else if (!min) {
|
||||
return `<= ${max}`;
|
||||
}
|
||||
|
||||
return `${min} to ${max}`;
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('hyphenate', (str) => str.replace('_', '-'));
|
||||
Handlebars.registerHelper('uppercase', (str) => str.toUpperCase());
|
||||
|
||||
Handlebars.registerHelper('capitalize', (driverName) => {
|
||||
switch (driverName.toLowerCase()) {
|
||||
case 'xcuitest':
|
||||
return 'XCUITest';
|
||||
case 'uiautomation':
|
||||
return 'UIAutomation';
|
||||
case 'uiautomator2':
|
||||
return 'UiAutomator2';
|
||||
case 'uiautomator':
|
||||
return 'UiAutomator';
|
||||
default:
|
||||
return driverName.length === 0 ? driverName : driverName[0].toUpperCase() + driverName.substr(1);
|
||||
}
|
||||
});
|
||||
|
||||
async function main () {
|
||||
const commands = path.resolve(__dirname, 'commands/**/*.yml');
|
||||
console.log('Traversing YML files', commands);
|
||||
for (let filename of await fs.glob(commands)) {
|
||||
console.log('Rendering file:', filename, path.relative(__dirname, filename), path.extname(filename));
|
||||
|
||||
// Translate the YML specs to JS
|
||||
const inputYML = await fs.readFile(filename, 'utf8');
|
||||
const inputJS = yaml.load(inputYML);
|
||||
const validationErrors = validate(inputJS, validator);
|
||||
if (validationErrors) {
|
||||
throw new Error(validationErrors);
|
||||
}
|
||||
|
||||
// Pass the inputJS into our Handlebars template
|
||||
const template = Handlebars.compile(await fs.readFile(path.resolve(__dirname, 'template.md'), 'utf8'), {noEscape: true, strict: true});
|
||||
const markdown = template(inputJS);
|
||||
|
||||
// Write the markdown to its right place
|
||||
const markdownPath = replaceExt(path.relative(__dirname, filename), '.md');
|
||||
const outfile = path.resolve(__dirname, '..', 'docs', 'en', markdownPath);
|
||||
console.log('Writing file to:', outfile);
|
||||
await fs.writeFile(outfile, markdown, 'utf8');
|
||||
}
|
||||
}
|
||||
|
||||
asyncify(main);
|
||||
/* eslint-enable */
|
||||
@@ -0,0 +1,126 @@
|
||||
# {{name}}
|
||||
|
||||
{{description}}
|
||||
## Example Usage
|
||||
|
||||
```java
|
||||
// Java
|
||||
{{example_usage.java}}
|
||||
```
|
||||
```python
|
||||
# Python
|
||||
{{example_usage.python}}
|
||||
```
|
||||
```javascript
|
||||
// Javascript
|
||||
// webdriver.io example
|
||||
{{example_usage.javascript_wdio}}
|
||||
|
||||
// wd example
|
||||
{{example_usage.javascript_wd}}
|
||||
```
|
||||
```ruby
|
||||
# Ruby example
|
||||
{{example_usage.ruby}}
|
||||
```
|
||||
```php
|
||||
# PHP example
|
||||
{{example_usage.php}}
|
||||
```
|
||||
```csharp
|
||||
// C# example
|
||||
{{example_usage.csharp}}
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
{{description}}
|
||||
|
||||
## Client Docs
|
||||
|
||||
* [Java]({{client_docs.java}})
|
||||
* [Python]({{client_docs.python}})
|
||||
* [Javascript (WebdriverIO)]({{client_docs.javascript_wdio}})
|
||||
* [Javascript (WD)]({{client_docs.javascript_wd}})
|
||||
* [Ruby]({{client_docs.ruby}})
|
||||
* [PHP]({{client_docs.php}})
|
||||
* [C#]({{client_docs.csharp}})
|
||||
|
||||
## Support
|
||||
|
||||
### Appium Server
|
||||
|
||||
|Platform|Driver|Platform Versions|Appium Version|Driver Version|
|
||||
|--------|----------------|------|--------------|--------------|
|
||||
{{#each driver_support.ios}}
|
||||
| {{#if @first}}iOS{{/if}} | [{{capitalize @key}}](/docs/en/drivers/ios-{{@key}}.md) | {{versions this "platform" @key}} | {{versions this "appium" @key}} | {{versions this "driver" @key}} |
|
||||
{{/each}}
|
||||
{{#each driver_support.android}}
|
||||
| {{#if @first}}Android{{/if}} | [{{capitalize @key}}](/docs/en/drivers/android-{{@key}}.md) | {{versions this "platform" @key}} | {{versions this "appium" @key}} | {{versions this "driver" @key}} |
|
||||
{{/each}}
|
||||
{{#each driver_support.mac}}
|
||||
| {{#if @first}}Mac{{/if}} | [{{capitalize @key}}](/docs/en/drivers/{{@key}}.md) | {{versions this "platform" @key}} | {{versions this "appium" @key}} | {{versions this "driver" @key}} |
|
||||
{{/each}}
|
||||
{{#each driver_support.windows}}
|
||||
| {{#if @first}}Windows{{/if}} | [{{capitalize @key}}](/docs/en/drivers/{{@key}}.md) | {{versions this "platform" @key}} | {{versions this "appium" @key}} | {{versions this "driver" @key}} |
|
||||
{{/each}}
|
||||
|
||||
### Appium Clients
|
||||
|
||||
|Language|Support|
|
||||
|--------|-------|
|
||||
|[Java](https://github.com/appium/java-client/releases/latest)| {{versions client_support.java}} |
|
||||
|[Python](https://github.com/appium/python-client/releases/latest)| {{versions client_support.python}} |
|
||||
|[Javascript (WebdriverIO)](http://webdriver.io/index.html)| {{versions client_support.javascript_wdio}} |
|
||||
|[Javascript (WD)](https://github.com/admc/wd/releases/latest)| {{versions client_support.javascript_wd}} |
|
||||
|[Ruby](https://github.com/appium/ruby_lib/releases/latest)| {{versions client_support.ruby}} |
|
||||
|[PHP](https://github.com/appium/php-client/releases/latest)| {{versions client_support.php}} |
|
||||
|[C#](https://github.com/appium/appium-dotnet-driver/releases/tag/1.2.0.8)| {{versions client_support.csharp}} |
|
||||
|
||||
## HTTP API Specifications
|
||||
|
||||
### Endpoint
|
||||
|
||||
`{{uppercase endpoint.method}} {{endpoint.url}}`
|
||||
|
||||
### URL Parameters
|
||||
|
||||
|name|description|
|
||||
|----|-----------|
|
||||
{{#each endpoint.url_parameters}}
|
||||
|{{this.name}}|{{this.description}}|
|
||||
{{/each}}
|
||||
|
||||
|
||||
### JSON Parameters
|
||||
|
||||
{{#if endpoint.json_parameters}}
|
||||
|name|type|description|
|
||||
|----|-----------|
|
||||
{{#each endpoint.json_parameters}}
|
||||
| {{this.name}} | {{this.type}} | {{this.description}} |
|
||||
{{/each}}
|
||||
|
||||
{{else}}
|
||||
None
|
||||
{{/if}}
|
||||
|
||||
### Response
|
||||
|
||||
|name|type|description|
|
||||
|----|----|-----------|
|
||||
{{#each endpoint.response}}
|
||||
| {{this.name}} | {{this.type}} | {{this.description}} |
|
||||
{{/each}}
|
||||
|
||||
## See Also
|
||||
|
||||
{{#if specifications.w3c}}
|
||||
* [W3C Specification]({{specifications.w3c}})
|
||||
{{/if}}
|
||||
{{#if specifications.jsonwp}}
|
||||
* [JSONWP Specification]({{specifications.jsonwp}})
|
||||
{{/if}}
|
||||
{{#each links}}
|
||||
* [{{this.name}}]({{this.url}})
|
||||
{{/each}}
|
||||
@@ -0,0 +1,52 @@
|
||||
import validate from 'validate.js';
|
||||
import _ from 'lodash';
|
||||
|
||||
validate.validators.array = function (value, options, key, attributes) {
|
||||
if (attributes[key] && !validate.isArray(attributes[key])) {
|
||||
return `must be an array`;
|
||||
}
|
||||
};
|
||||
|
||||
validate.validators.hasAttributes = function (value, options) {
|
||||
if (!value) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_.isObject(value) && !_.isArray(value)) {
|
||||
value = [value];
|
||||
}
|
||||
|
||||
for (let item of value) {
|
||||
for (let option of options) {
|
||||
if (_.isUndefined(item[option])) {
|
||||
return `must have attributes: ${options}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
'name': {presence: true},
|
||||
'example_usage': {presence: true},
|
||||
'example_usage.java': {presence: true},
|
||||
'example_usage.javascript_wdio': {presence: true},
|
||||
'example_usage.javascript_wd': {presence: true},
|
||||
'example_usage.ruby': {presence: true},
|
||||
'example_usage.csharp': {presence: true},
|
||||
'example_usage.php': {presence: true},
|
||||
'description': {presence: true},
|
||||
'client_docs.java': {presence: true, url: true},
|
||||
'client_docs.javascript_wdio': {presence: true, url: true},
|
||||
'client_docs.javascript_wd': {presence: true, url: true},
|
||||
'client_docs.ruby': {presence: true, url: true},
|
||||
'client_docs.csharp': {presence: true, url: true},
|
||||
'client_docs.php': {presence: true, url: true},
|
||||
'endpoint': {presence: true},
|
||||
'driver_support': {presence: true},
|
||||
'endpoint.url': {presence: true},
|
||||
'endpoint.url_parameters': { 'array': true, hasAttributes: ['name', 'description'] },
|
||||
'endpoint.json_parameters': { 'array': true, hasAttributes: ['name', 'description'] },
|
||||
'endpoint.response': {presence: true, hasAttributes: ['name', 'type', 'description'] },
|
||||
'specifications': {presence: true},
|
||||
'links': { 'array': true, hasAttributes: ['name', 'url'] },
|
||||
};
|
||||
@@ -1,114 +0,0 @@
|
||||
# Template <Name of Command>
|
||||
|
||||
A brief description of the command.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```java
|
||||
// Java example
|
||||
```
|
||||
```python
|
||||
# Python example
|
||||
```
|
||||
```javascript
|
||||
// Javascript
|
||||
// webdriver.io example
|
||||
driver.status();
|
||||
|
||||
// wd example
|
||||
await driver.status();
|
||||
```
|
||||
```ruby
|
||||
# Ruby example
|
||||
```
|
||||
```php
|
||||
# PHP example
|
||||
```
|
||||
|
||||
## Description
|
||||
|
||||
An in-depth description of the command. If this is a W3C command, you can copy and paste the W3C description here and make any amendments that would apply to Appium
|
||||
|
||||
## Code samples
|
||||
|
||||
Optional section. If the command is straightforward, no need to add samples, the example usage above is good enough. This is for important/complicated things like session creation, and touch actions.
|
||||
|
||||
## Client Docs
|
||||
|
||||
* [Java](http://seleniumhq.github.io/selenium/docs/api/java/index.html)
|
||||
* [Python](http://selenium-python.readthedocs.io/api.html#selenium.webdriver.common.action_chains.ActionChains.click)
|
||||
* [Javascript (WebdriverIO)](http://webdriver.io/api/protocol/status.html)
|
||||
* [Javascript (WD)](https://github.com/admc/wd/blob/master/lib/commands.js#L1438)
|
||||
* [Ruby](http://www.rubydoc.info/gems/selenium-webdriver/0.0.28/Selenium/WebDriver/Element#click-instance_method)
|
||||
* TODO: PHP
|
||||
|
||||
## Support
|
||||
|
||||
### Appium Server
|
||||
|
||||
|Platform|Driver|Platform Versions|Appium Version|Driver Version|
|
||||
|--------|----------------|------|--------------|--------------|
|
||||
|iOS|[XCUITest](/docs/en/drivers/ios-xcuitest.md)| 9.3+ | 1.6.0+ | All |
|
||||
| |[UIAutomation](/docs/en/drivers/ios-xcuitest.md)| 8.0 to 9.3 | All | All |
|
||||
|Android|[UiAutomator2](/docs/en/drivers/android-uiautomator2.md)| ? | 1.6.0+ | All|
|
||||
| |[UiAutomator](/docs/en/drivers/android-uiautomator.md)| 4.2+ | All | All |
|
||||
| |[Espresso](/docs/en/drivers/android-espresso.md)| TBD | TBD |TBD
|
||||
|Windows|[Windows](/docs/en/drivers/windows.md)| 10+ | 1.6.0+ |All|
|
||||
|Mac|[Mac](/docs/en/drivers/mac.md)|?| 1.6.4+ |All|
|
||||
|Mac|None||||
|
||||
|
||||
### Appium Clients
|
||||
|
||||
|Language|Support|
|
||||
|--------|-------|
|
||||
|[Java](https://github.com/appium/java-client/releases/latest)|All|
|
||||
|[Python](https://github.com/appium/python-client)|All|
|
||||
|[Javascript (WebdriverIO)](http://webdriver.io/index.html)|1.12.3|
|
||||
|[Javascript (WD)](https://github.com/admc/wd/releases)|None|
|
||||
|[Ruby](https://github.com/appium/ruby_lib/releases/latest)|All|
|
||||
|[PHP](https://github.com/appium/php-client/releases/latest)|All|
|
||||
|
||||
## HTTP API Specifications
|
||||
|
||||
### Endpoint
|
||||
|
||||
`POST /wd/hub/path/to/endpoint`
|
||||
|
||||
### URL Parameters
|
||||
|
||||
|name|description|
|
||||
|----|-----------|
|
||||
|field_name_1|Description of field_name_1|
|
||||
|field_name_2|Description of field_name_2|
|
||||
|
||||
or
|
||||
|
||||
(none)
|
||||
|
||||
### JSON Parameters
|
||||
|
||||
|name|description|
|
||||
|----|-----------|
|
||||
|field_name_1|Description of field_name_1|
|
||||
|field_name_2|Description of field_name_2|
|
||||
|
||||
or
|
||||
|
||||
(none)
|
||||
|
||||
### Response
|
||||
|
||||
|name|type|description|
|
||||
|----|----|-----------|
|
||||
|field_name_1|number|Description of field_name_1|
|
||||
|field_name_2|number|Description of field_name_2|
|
||||
|object.key1|string|Description of key1|
|
||||
|object.key2|string|Description of key2|
|
||||
|
||||
## Specifications
|
||||
|
||||
|
||||
## See Also
|
||||
|
||||
* [W3C Specification](https://www.w3.org/TR/webdriver/#status) Link to the w3c spec if there is one
|
||||
* [JSONWP Specification](https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol#sessionsessionidelementidclick)
|
||||
+9
-2
@@ -70,7 +70,8 @@
|
||||
"precommit-msg": "echo 'Pre-commit checks...' && exit 0",
|
||||
"precommit-test": "REPORTER=dot gulp once",
|
||||
"lint": "gulp eslint",
|
||||
"coverage": "gulp coveralls"
|
||||
"coverage": "gulp coveralls",
|
||||
"generate-docs": "babel-node ./commands-yml/parse.js"
|
||||
},
|
||||
"pre-commit": [
|
||||
"precommit-msg",
|
||||
@@ -78,7 +79,9 @@
|
||||
],
|
||||
"devDependencies": {
|
||||
"appium-gulp-plugins": "2.x",
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-eslint": "7.x",
|
||||
"babel-preset-env": "^1.6.0",
|
||||
"chai": "3.x",
|
||||
"chai-as-promised": "5.x",
|
||||
"eslint": "3.x",
|
||||
@@ -88,10 +91,14 @@
|
||||
"eslint-plugin-mocha": "4.x",
|
||||
"eslint-plugin-promise": "3.x",
|
||||
"gulp": "3.x",
|
||||
"handlebars": "^4.0.10",
|
||||
"mocha": "2.x",
|
||||
"pre-commit": "1.x",
|
||||
"replace-ext": "^1.0.0",
|
||||
"sinon": "1.x",
|
||||
"wd": "1.x"
|
||||
"validate.js": "^0.11.1",
|
||||
"wd": "1.x",
|
||||
"yaml-js": "^0.2.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "1.x",
|
||||
|
||||
Reference in New Issue
Block a user