зеркало из https://github.com/xamarin/appium.old.git
Update Contributing Docs (#10165)
* Update contributing docs * Fix some links and examples * Address comments
This commit is contained in:
Родитель
77fe650dd6
Коммит
be2acb207c
|
@ -8,7 +8,7 @@ Note that no matter how you contribute, your participation is governed by our
|
|||
### Make changes to the Appium code or docs
|
||||
|
||||
Fork the project, make a change, and send a pull request! Please have a look at
|
||||
our [Style Guide](/docs/en/contributing-to-appium/style-guide-2.0.md) before
|
||||
our [Style Guide](/docs/en/contributing-to-appium/style-guide.md) before
|
||||
getting to work. Please make sure the unit and functional tests pass before
|
||||
sending a pull request; for more information on how to run tests, keep reading!
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
你想从源码运行Appium并帮助修复BUG和添加功能吗?
|
||||
真棒!只需要fork工程,添加一个修改,然后发送pull请求即可!
|
||||
在开始之前请阅读我们的代码风格指南([Style Guide](style-guide-2.0.md)。
|
||||
在开始之前请阅读我们的代码风格指南([Style Guide](style-guide.md)。
|
||||
在发送pull请求前请确保通过单元和功能测试;关于如何运行测试等更多信息,请继续阅读!
|
||||
|
||||
首先,确保你阅读README文件且按照设置说明走。
|
||||
|
|
|
@ -63,7 +63,7 @@ node.js的原生支持,Appium代码是_被移植_到ES5(JS更为广泛支持
|
|||
### 排查和代码风格
|
||||
|
||||
对于所有Appium的JS而言,代码外观和使用感觉同样重要。这包括样式常规,编码模式以及我们解决各种问题时使用的
|
||||
库。你应该熟悉我们新的[ES2015 风格指南](/docs/cn/contributing-to-appium/style-guide-2.0.md)。
|
||||
库。你应该熟悉我们新的[ES2015 风格指南](/docs/cn/contributing-to-appium/style-guide.md)。
|
||||
当转化时,Appium包将自动运行JSHint或其他lint工具,并在代码不符合我们规范的时候提供警告或错误反馈。
|
||||
这些工具不一定能顾全我们关心的种种风格问题,所以我们在review代码的时候也应该注意代码规范问题。这不是
|
||||
吹毛求疵,而是为了有一个整洁,一致并且可读的代码库。
|
||||
|
@ -102,7 +102,7 @@ _FORCE_LOGS=1 <command> # 显示测试运行期间的模块日志输出
|
|||
任何非Appium主包的发布流程都是非常简洁明了的(请注意:如果你想要发布它,你需要成为一个NPM的所有者。
|
||||
所有权由Appium提交者管理; 如果你对所有者有任何疑问,请联系@jlipps 或者 @imurchie)。
|
||||
|
||||
0. `rm -rf node_modules && npm install` 并运行测试以确保全新安装正常工作
|
||||
0. `rm -rf node_modules && rm -rf package-lock.json && npm install` 并运行测试以确保全新安装正常工作
|
||||
0. 根据[SemVer](http://semver.org/) 规则决定我们是否需要发布一个补丁(漏洞修复),微调(功能)或者是主要(迭代)(请参考 [how SemVer works with NPM](https://docs.npmjs.com/getting-started/semantic-versioning).
|
||||
0. 通过任何适当的更改和提交来更新CHANGELOG以README文件。大多数子包没有CHANGELOG。
|
||||
0. 通过适当的版本类型运行 `npm version <version-type>`
|
||||
|
@ -121,8 +121,8 @@ _FORCE_LOGS=1 <command> # 显示测试运行期间的模块日志输出
|
|||
因此有必要在发布过程中手动管理它。 它需要与对`package.json`的更改一起提交到GitHub。
|
||||
|
||||
0. 如果 NPM shrinkwrap JSON 文件存在,请移除.
|
||||
0. `rm -rf node_modules && npm install` 并运行测试以确保全新安装正常工作
|
||||
0. `rm -rf node_modules && npm install --production` 以获取仅production部分.
|
||||
0. `rm -rf node_modules && rm -rf package-lock.json && npm install` 并运行测试以确保全新安装正常工作
|
||||
0. `rm -rf node_modules && rm -rf package-lock.json && npm install --production` 以获取仅production部分.
|
||||
0. `npm shrinkwrap` 来编写新的 NPM shrinkwrap JSON 文件.
|
||||
0. 根据SemVer来决定我们是否需要发布一个补丁(漏洞修复),微调(功能)或者是主要(迭代)
|
||||
0. 用合适的新版本信息来更新`package.json`
|
||||
|
|
|
@ -2,11 +2,20 @@
|
|||
|
||||
So you want to run Appium from source and help fix bugs and add features?
|
||||
Great! Just fork the project, make a change, and send a pull request! Please
|
||||
have a look at our [Style Guide](style-guide-2.0.md) before getting to work.
|
||||
have a look at our [Style Guide](style-guide.md) before getting to work.
|
||||
Please make sure the unit and functional tests pass before sending a pull
|
||||
request; for more information on how to run tests, keep reading!
|
||||
|
||||
Make sure you read and follow the setup instructions in the README first.
|
||||
### Node.js
|
||||
|
||||
Appium is written in JavaScript, and run with the [Node.js](https://nodejs.org/) engine. Currently
|
||||
version 6+ is supported. While Node.js can be installed globally on the system,
|
||||
a version manager is _highly_ recommended.
|
||||
* NVM - [https://github.com/creationix/nvm](https://github.com/creationix/nvm)
|
||||
* N - [https://github.com/tj/n](https://github.com/tj/n)
|
||||
|
||||
Your Node.js installation will include the [NPM](https://www.npmjs.com/) package manager, which Appium
|
||||
will need in order to manage dependencies. Appiums supports NPM version 3+.
|
||||
|
||||
### Setting up Appium from Source
|
||||
|
||||
|
@ -17,57 +26,43 @@ instance of an Appium server, and then run your test.
|
|||
|
||||
The quick way to get started:
|
||||
|
||||
```center
|
||||
```
|
||||
git clone https://github.com/appium/appium.git
|
||||
cd appium
|
||||
npm install
|
||||
gulp transpile # requires gulp, see below
|
||||
npm install -g authorize-ios # for ios only
|
||||
authorize-ios # for ios only
|
||||
npm run build
|
||||
node .
|
||||
```
|
||||
|
||||
### Hacking on Appium
|
||||
|
||||
Make sure you have `ant`, `maven`, `adb` installed and added to system `PATH`, also you
|
||||
would need the android-16 sdk (for Selendroid) and android-19 sdk installed.
|
||||
From your local repo's command prompt, install the following packages using the
|
||||
following commands (if you didn't install `node` using Homebrew, you might have
|
||||
to run `npm` with sudo privileges):
|
||||
|
||||
```center
|
||||
npm install -g mocha
|
||||
npm install -g gulp
|
||||
npm install -g gulp-cli
|
||||
npm install -g appium-doctor && appium-doctor --dev
|
||||
npm install
|
||||
gulp transpile
|
||||
Install the [appium-doctor](https://github.com/appium/appium-doctor) tool, and run it to verify all of the
|
||||
dependencies are set up correctly (since dependencies for building Appium
|
||||
are different from those for simply running it):
|
||||
```
|
||||
npm install -g appium-doctor
|
||||
appium-doctor --dev
|
||||
```
|
||||
Install the Node.js dependencies:
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
The first two commands install test and build tools (`sudo` may not be
|
||||
necessary if you installed node.js via Homebrew). The third command verifies
|
||||
that all of the dependencies are set up correctly (since dependencies for
|
||||
building Appium are different from those for simply running Appium) and fourth
|
||||
command installs all app dependencies and builds supporting binaries and test
|
||||
apps. The final command transpiles all the code so that `node` can run it.
|
||||
|
||||
When pulling new code from GitHub, if there are changes to `package.json` it
|
||||
is necessary to remove the old dependencies and re-run `npm install`:
|
||||
|
||||
```center
|
||||
rm -rf node_modules
|
||||
npm install
|
||||
gulp transpile
|
||||
```
|
||||
rm -rf node_modules && rm -rf package-lock.json && npm install
|
||||
```
|
||||
|
||||
At this point, you will be able to start the Appium server:
|
||||
|
||||
```center
|
||||
```
|
||||
node .
|
||||
```
|
||||
|
||||
See [the server documentation](/docs/en/writing-running-appium/server-args.md)
|
||||
for a full list of arguments.
|
||||
for a full list of command line arguments that can be used.
|
||||
|
||||
#### Hacking with Appium for iOS
|
||||
|
||||
|
@ -80,36 +75,37 @@ have to modify your `/etc/authorization` file in one of two ways:
|
|||
2. Run the following command which automatically modifies your
|
||||
`/etc/authorization` file for you:
|
||||
|
||||
```center
|
||||
```
|
||||
npm install -g authorize-ios
|
||||
sudo authorize-ios
|
||||
```
|
||||
|
||||
At this point, run:
|
||||
|
||||
```center
|
||||
rm -rf node-modules
|
||||
npm install
|
||||
gulp transpile
|
||||
```
|
||||
rm -rf node_modules && rm -rf package-lock.json && npm install
|
||||
```
|
||||
|
||||
Now your Appium instance is ready to go. Run `node .` to kick up the Appium server.
|
||||
|
||||
#### Hacking with Appium for Android
|
||||
|
||||
To work on Android, make sure you have `ant`, `maven`, and `adb` installed
|
||||
and added to system `PATH` environment variable. Also you would need the
|
||||
android-16 sdk (for `Selendroid`) and android-19+ sdk installed.
|
||||
From your local repo's command prompt, install/run the following:
|
||||
|
||||
Set up Appium by running:
|
||||
|
||||
```center
|
||||
rm -rf node-modules
|
||||
npm install
|
||||
gulp transpile
|
||||
```
|
||||
rm -rf node_modules && rm -rf package-lock.json && npm install
|
||||
```
|
||||
|
||||
Make sure you have one and only one Android emulator or device running, e.g.,
|
||||
by running this command in another process (assuming the `emulator` command is
|
||||
on your path):
|
||||
|
||||
```center
|
||||
```
|
||||
emulator -avd <MyAvdName>
|
||||
```
|
||||
|
||||
|
@ -123,11 +119,43 @@ update everything necessary. You will also need to do this when Appium bumps
|
|||
its version up. Prior to running `npm install` it is recommended to remove
|
||||
all the old dependencies in the `node_modules` directory:
|
||||
|
||||
```center
|
||||
rm -rf node-modules
|
||||
npm install
|
||||
gulp transpile
|
||||
```
|
||||
rm -rf node_modules && rm -rf package-lock.json && npm install
|
||||
```
|
||||
|
||||
### Different packages
|
||||
|
||||
Appium is made up of a number of different packages. While it is often possible
|
||||
to work in a single package, it is also often the case that work, whether fixing
|
||||
a bug or adding a new feature, requires working on multiple packages simultaneously.
|
||||
|
||||
Unfortunately the dependencies installed when running `npm install` are those that
|
||||
have already been published, so some work is needed to link together local development
|
||||
versions of the packages that are being worked on.
|
||||
|
||||
In the case where one package, `A`, depends on another package, `B`, the following steps
|
||||
are necessary to link the two:
|
||||
1. In one terminal, enter into package `B`
|
||||
```
|
||||
cd B
|
||||
```
|
||||
2. Use [NPM link](https://docs.npmjs.com/cli/link) to create symbolic link to this package
|
||||
```
|
||||
npm link
|
||||
```
|
||||
3. In another terminal, enter into package `A`
|
||||
```
|
||||
cd A
|
||||
```
|
||||
4. Use [NPM link](https://docs.npmjs.com/cli/link) to link the dependent package `B` to the development version
|
||||
```
|
||||
npm link B
|
||||
```
|
||||
|
||||
Now the version of `B` that `A` uses will be your local version. Remember, however, that
|
||||
changes made to the JavaScript will only be available when they have been transpiled, so
|
||||
when you are going to test from package `A`, run `npm run build` in the directory for
|
||||
package `B`.
|
||||
|
||||
### Running Tests
|
||||
|
||||
|
@ -138,16 +166,23 @@ system is set up properly for the platforms you desire to test on.
|
|||
Once your system is set up and your code is up to date, you can run unit tests
|
||||
with:
|
||||
|
||||
```center
|
||||
gulp once
|
||||
```
|
||||
npm run test
|
||||
```
|
||||
|
||||
You can run functional tests for all supported platforms (after ensuring that
|
||||
Appium is running in another window with `node .`) with:
|
||||
|
||||
```center
|
||||
gulp e2e-test
|
||||
```
|
||||
npm run e2e-test
|
||||
```
|
||||
|
||||
Before committing code, please run `gulp once` to execute some basic tests and
|
||||
check your changes against code quality standards.
|
||||
### Committing code
|
||||
|
||||
Each Appium package installs a pre-commit hook which will run the [linter](https://eslint.org/) and
|
||||
the unit tests before the commit is made. Any error in either of these will stop
|
||||
the commit from occurring.
|
||||
|
||||
Once code is committed and a [pull request](https://help.github.com/articles/about-pull-requests/)
|
||||
is made to the correct Appium respository on [GitHub](https://github.com/), Appium build system
|
||||
will run all of the functional tests.
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
## Appium development commands
|
||||
|
||||
Each Appium package has a number of NPM scripts that are used to automate
|
||||
development tasks:
|
||||
|
||||
| Task | Description |
|
||||
|------------------|--------------------------------------------------------|
|
||||
| npm run build | Transpile code into the `build` directory |
|
||||
| npm run lint | Runs ESLint |
|
||||
| npm run test | Cleans, lints, transpiles, and runs unit tests |
|
||||
| npm run e2e-test | Tranpiles and runs functional tests |
|
||||
| npm run watch | Automatically runs `test` command when code is changed |
|
||||
| npm run mocha | Gives access to `mocha` test runner |
|
||||
|
||||
In addition, the main Appium package has a task `npm generate-docs` which generates
|
||||
the command documentation.
|
|
@ -93,7 +93,7 @@ Most Appium packages have this as the default behavior when running `gulp`.
|
|||
It's important for all of Appium's JS to look and feel the same. This includes
|
||||
style conventions as well as coding patterns and which libraries we use to
|
||||
solve various problems. You should get familiar with our new [ES2015 Style
|
||||
Guide](/docs/en/contributing-to-appium/style-guide-2.0.md). When transpiling,
|
||||
Guide](/docs/en/contributing-to-appium/style-guide.md). When transpiling,
|
||||
Appium packages will automatically run ESLint or other lint tools and provide
|
||||
warning or error feedback if the code doesn't conform to our style. These tools
|
||||
are not necessarily exhaustive of the kinds of style issues we care about, so
|
||||
|
@ -147,12 +147,12 @@ package if you want to publish it. Ownership is managed by the Appium
|
|||
committers; talk to @jlipps or @imurchie if you believe you should be an owner
|
||||
and are not):
|
||||
|
||||
0. `rm -rf node_modules && npm install` and run tests to make sure a clean install works.
|
||||
0. Determine whether we have a patch (bugfix), minor (feature), or major (breaking) release according to the principles of [SemVer](http://semver.org/) (see also this explanation of [how SemVer works with NPM](https://docs.npmjs.com/getting-started/semantic-versioning)).
|
||||
0. Update the `CHANGELOG` and/or `README` with any appropriate changes and commit. Most subpackages don't have a `CHANGELOG`.
|
||||
0. Run `npm version <version-type>` with the appropriate version type.
|
||||
0. Push the appropriate branch to GitHub, and don't forget to include the `--tags` flag to include the tag just created by `npm version`.
|
||||
0. Run `npm publish` (with `--tag beta` if this isn't an official release).
|
||||
1. `rm -rf node_modules && rm -rf package-lock.json && npm install` and run tests to make sure a clean install works.
|
||||
1. Determine whether we have a patch (bugfix), minor (feature), or major (breaking) release according to the principles of [SemVer](http://semver.org/) (see also this explanation of [how SemVer works with NPM](https://docs.npmjs.com/getting-started/semantic-versioning)).
|
||||
1. Update the `CHANGELOG` and/or `README` with any appropriate changes and commit. Most subpackages don't have a `CHANGELOG`.
|
||||
1. Run `npm version <version-type>` with the appropriate version type.
|
||||
1. Push the appropriate branch to GitHub, and don't forget to include the `--tags` flag to include the tag just created by `npm version`.
|
||||
1. Run `npm publish` (with `--tag beta` if this isn't an official release).
|
||||
|
||||
For the main Appium packages, all the above steps must be taken, but with
|
||||
several changes. One reason is that for the main package we use NPM shrinkwrap
|
||||
|
@ -175,20 +175,20 @@ checked in to GitHub along with changes to `package.json`. With npm 5+ there is
|
|||
also a `package-lock.json` file produced. During the shrinkwrap process this is
|
||||
converted into the `npm-shrinkwrap.json` file.
|
||||
|
||||
0. Remove the NPM shrinkwrap and package-lock JSON files if they exists.
|
||||
0. `rm -rf node_modules && npm install` and run tests to make sure a clean install works.
|
||||
0. Determine whether we have a `patch` (bugfix), `minor` (feature), or `major` (breaking) release according to the principles of SemVer.
|
||||
0. Update `package.json` with the appropriate new version.
|
||||
0. Update the CHANGELOG/README with appropriate changes and submit for review as a PR, along with shrinkwrap and `package.json` changes. Wait for it to be merged, then pull it into the release branch.
|
||||
0. `rm -rf node_modules && npm install --production` to get just the production dependencies.
|
||||
0. `npm shrinkwrap` to write the new NPM shrinkwrap JSON file, and commit this file.
|
||||
0. Create a tag of the form `v<version>` on the release branch (usually a minor branch like `1.5` or `1.4`), with: `git tag -a v<version>`, e.g., `git tag -a v1.5.0`. This is not necessary for beta versions.
|
||||
0. Push the tag to upstream: `git push --tags <remote> <branch>`
|
||||
0. Install dev dependencies (or at least `gulp` and `appium-gulp-plugins`), and undo the changes to the NPM shrinkwrap JSON file (e.g., `git checkout -- npm-shrinkwrap.json`).
|
||||
0. Run `npm publish` (with `--tag beta` if this isn't an official release).
|
||||
0. Remove the NPM shrinkwrap JSON file from Git and push the changes
|
||||
0. Update the docs at appium.io. Check out the appium.io repo from github, check out the `gh-pages` branch and pull latest. Run `rake publish`.
|
||||
0. Create a new release on GitHub: go to `https://github.com/appium/appium/releases/tag/v<VERSION>` and hit "Edit Tag". Make the release name `<VERSION>` (e.g., `2.0.5`), then paste in the changelog (but not the changelog header for this version). If it's a beta release, mark as pre-release.
|
||||
0. Create a new post on discuss.appium.io announcing the release. Post it in the "News" category. Paste in the changelog and any choice comments. Pin it and unpin the previous release post.
|
||||
0. Begin process of releasing `appium-desktop`.
|
||||
0. Notify @jlipps to so he can tweet a link to the discuss post.
|
||||
1. Remove the NPM shrinkwrap and package-lock JSON files if they exists.
|
||||
1. `rm -rf node_modules && npm install` and run tests to make sure a clean install works.
|
||||
1. Determine whether we have a `patch` (bugfix), `minor` (feature), or `major` (breaking) release according to the principles of SemVer.
|
||||
1. Update `package.json` with the appropriate new version.
|
||||
1. Update the CHANGELOG/README with appropriate changes and submit for review as a PR, along with shrinkwrap and `package.json` changes. Wait for it to be merged, then pull it into the release branch.
|
||||
1. `rm -rf node_modules && npm install --production` to get just the production dependencies.
|
||||
1. `npm shrinkwrap` to write the new NPM shrinkwrap JSON file, and commit this file.
|
||||
1. Create a tag of the form `v<version>` on the release branch (usually a minor branch like `1.5` or `1.4`), with: `git tag -a v<version>`, e.g., `git tag -a v1.5.0`. This is not necessary for beta versions.
|
||||
1. Push the tag to upstream: `git push --tags <remote> <branch>`
|
||||
1. Install dev dependencies (or at least `gulp` and `appium-gulp-plugins`), and undo the changes to the NPM shrinkwrap JSON file (e.g., `git checkout -- npm-shrinkwrap.json`).
|
||||
1. Run `npm publish` (with `--tag beta` if this isn't an official release).
|
||||
1. Remove the NPM shrinkwrap JSON file from Git and push the changes
|
||||
1. Update the docs at appium.io. Check out the appium.io repo from github, check out the `gh-pages` branch and pull latest. Run `rake publish`.
|
||||
1. Create a new release on GitHub: go to `https://github.com/appium/appium/releases/tag/v<VERSION>` and hit "Edit Tag". Make the release name `<VERSION>` (e.g., `2.0.5`), then paste in the changelog (but not the changelog header for this version). If it's a beta release, mark as pre-release.
|
||||
1. Create a new post on discuss.appium.io announcing the release. Post it in the "News" category. Paste in the changelog and any choice comments. Pin it and unpin the previous release post.
|
||||
1. Begin process of releasing `appium-desktop`.
|
||||
1. Notify @jlipps to so he can tweet a link to the discuss post.
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
## Appium gulp commands
|
||||
|
||||
[Gulp](http://gulpjs.com) is like `make` for Node.js! We use it to automate all
|
||||
kinds of appium dev tasks. Here's what you can do:
|
||||
|
||||
|Task|Description|
|
||||
|----|-----------|
|
||||
|gulp once|Cleans, lints, transpiles and runs unit tests|
|
||||
|gulp watch|Automatically runs `gulp once` when code changes|
|
||||
|gulp lint|Runs JSLint|
|
||||
|gulp jshint|Runs JSHint|
|
||||
|gulp transpile|Transpiles our ES7/ES2015 code to ES5, generates `/build` directory + contents|
|
||||
|gulp unit-test|Runs unit tests|
|
||||
|gulp e2e-test|Runs e2e tests|
|
||||
|gulp docs|Generates docs/en/writing-running-appium/server-args.md doc|
|
|
@ -44,10 +44,10 @@ files in `docs/en/commands` and then they need to be committed and pushed.
|
|||
|
||||
### Adding Documents to Appium.io
|
||||
|
||||
Markdown files in `docs/` aren't automatically added to the site. To add a document to https://appium.io
|
||||
Markdown files in `docs/` aren't automatically added to the site. To add a document to [appium.io](https://appium.io)
|
||||
you need to add it as an entry in the appropriate location in the table of
|
||||
contents, [toc.js](https://github.com/appium/appium/blob/master/docs/toc.js)
|
||||
|
||||
#### Publishing
|
||||
|
||||
To publish documentation on appium.io see [appium.io](https://github.com/appium/appium.io).
|
||||
To publish documentation on [appium.io](https://appium.io) see [appium.io (Github)](https://github.com/appium/appium.io).
|
||||
|
|
|
@ -1,256 +0,0 @@
|
|||
## Style guide for contributors
|
||||
|
||||
Thanks for your contribution to Appium! Here are the principles we use when
|
||||
writing javascript. Please conform to these so we can merge your pull request
|
||||
without going back and forth about style. The main principle is: *make your
|
||||
code look like the surrounding code*.
|
||||
|
||||
### Rebasing
|
||||
|
||||
Commits in a pull request should consist of [logical changes](https://github.com/appium/appium/pull/920#issuecomment-21588553).
|
||||
If there are multiple authors, make sure each author has their own commit.
|
||||
It's not a good idea to modify author information. Merge commits should be
|
||||
rebased out of pull requests.
|
||||
|
||||
### Linting
|
||||
|
||||
All code (except for code in `bootstrap.js` which uses proprietary Apple
|
||||
methods) must pass JSLint. To check your code, you can simply run `grunt
|
||||
lint` from the Appium repo dir. If you've created a new .js file,
|
||||
please make sure it is covered by the wildcards in `grunt.js` or that it is
|
||||
added specifically.
|
||||
|
||||
It's easy to have your code linted as you type, which makes the whole process
|
||||
much smoother. We like [jshint](http://www.jshint.com),
|
||||
which has integrations with a lot of source code editors. The file `
|
||||
.jshintrc` is checked into the repo, so by adding jshint to your editor, you'll
|
||||
take advantage of the linting.
|
||||
|
||||
Since jshint does not enforce code style anymore, we also use
|
||||
[jscs](https://github.com/mdevils/node-jscs), for which it also exists some
|
||||
source editor integrations.
|
||||
|
||||
These configuration files define the warnings you will see in your favorite
|
||||
editor. See [this page for jshint](http://www.jshint.com/platforms/) and
|
||||
[this page for jscs](https://github.com/mdevils/node-jscs#friendly-packages) to
|
||||
get the list of editors and platforms supported and how setup your editor for
|
||||
automatic linting.
|
||||
|
||||
### Style notes
|
||||
|
||||
We use a future version of JavaScript and take advantage of the Babel
|
||||
transpiler to render it down to what is supported by current versions of
|
||||
Node.js. We use ES2015 (link needed) (formerly called ES6) with some
|
||||
not-yet-standard features, namely `async/await` (link needed). This style guide
|
||||
must be followed diligently in all Appium contributions!
|
||||
|
||||
* Use two spaces for indentation, *no tabs*
|
||||
* Use single spaces around operators
|
||||
|
||||
```javascript
|
||||
var x = 1;
|
||||
```
|
||||
not
|
||||
```javascript
|
||||
var x=1;
|
||||
```
|
||||
|
||||
* Spaces after commas and colons in lists, objects, function calls, etc...
|
||||
|
||||
```javascript
|
||||
var x = myFunc("lol", {foo: bar, baz: boo});
|
||||
```
|
||||
not
|
||||
```javascript
|
||||
var x = myFunc("lol",{foo:bar,baz:boo});
|
||||
```
|
||||
|
||||
* Always end statements with semicolons
|
||||
* Comma-first
|
||||
|
||||
```javascript
|
||||
var x = {
|
||||
foo: 'bar'
|
||||
, baz: 'boo'
|
||||
, wuz: 'foz'
|
||||
};
|
||||
```
|
||||
|
||||
* Brackets for `function`, `if`, etc... go on same line, `else` gets sandwiched
|
||||
|
||||
```javascript
|
||||
if (foo === bar) {
|
||||
// do something
|
||||
} else {
|
||||
// do something else
|
||||
}
|
||||
```
|
||||
|
||||
* Space after `if`, `for`, and `function`:
|
||||
|
||||
```javascript
|
||||
if (foo === bar) {
|
||||
```
|
||||
```javascript
|
||||
for (var i = 0; i < 10; i ++) {
|
||||
```
|
||||
```javascript
|
||||
var lol = function (foo) {
|
||||
```
|
||||
not
|
||||
```javascript
|
||||
if(foo === bar) {
|
||||
```
|
||||
```javascript
|
||||
for(var i = 0; i < 10; i ++) {
|
||||
```
|
||||
```javascript
|
||||
var lol = function(foo) {
|
||||
```
|
||||
|
||||
* Avoid bracketless `if` for one-liners:
|
||||
|
||||
```javascript
|
||||
if (foo === bar) {
|
||||
foo++;
|
||||
}
|
||||
```
|
||||
not
|
||||
```javascript
|
||||
if (foo === bar)
|
||||
foo++;
|
||||
```
|
||||
except in the case of short-circuiting to a callback in the event of an error
|
||||
```javascript
|
||||
if (err) return cb(err);
|
||||
```
|
||||
|
||||
* Use `===`, not `==`, and `!==`, not `!=` for no surprises
|
||||
* Line length shouldn't be longer than 79 characters
|
||||
* Break up long strings like this:
|
||||
|
||||
```javascript
|
||||
myFunc("This is a really long string that's longer " +
|
||||
"than 79 characters so I broke it up, woo");
|
||||
```
|
||||
|
||||
* Comments should line up with code
|
||||
|
||||
```javascript
|
||||
if (foo === 5) {
|
||||
myFunc(foo);
|
||||
// foo++;
|
||||
}
|
||||
```
|
||||
not
|
||||
```javascript
|
||||
if (foo === 5) {
|
||||
myFunc(foo);
|
||||
//foo++;
|
||||
}
|
||||
```
|
||||
|
||||
* Subclassing by extending prototypes
|
||||
|
||||
```javascript
|
||||
var _ = require('underscore');
|
||||
|
||||
var SuperClass = function () {
|
||||
this.init();
|
||||
};
|
||||
|
||||
SuperClass.prototype.init = function () {
|
||||
// initialize
|
||||
};
|
||||
|
||||
// Create a subclass
|
||||
|
||||
var SubClass = function () {
|
||||
this.init();
|
||||
};
|
||||
|
||||
_.extend(SubClass.prototype, SuperClass.prototype);
|
||||
```
|
||||
|
||||
* Callbacks are always last in function definitions
|
||||
|
||||
```javascript
|
||||
var foo = function (arg1, arg2, cb) {
|
||||
...
|
||||
};
|
||||
```
|
||||
|
||||
* Define functions as variables
|
||||
|
||||
```javascript
|
||||
var myFunc = function (a, b, c) {};
|
||||
```
|
||||
not
|
||||
```javascript
|
||||
function myFunc (a, b, c) {}
|
||||
```
|
||||
|
||||
* Variable names should be camelCased:
|
||||
|
||||
```javascript
|
||||
var myVariable = 42;
|
||||
```
|
||||
not
|
||||
```javascript
|
||||
var my_variable = 42;
|
||||
```
|
||||
|
||||
* Check for undefined
|
||||
|
||||
```javascript
|
||||
typeof myVariable === "undefined"
|
||||
```
|
||||
not
|
||||
```javascript
|
||||
myVariable === undefined
|
||||
```
|
||||
|
||||
* Define a variable with a default value
|
||||
|
||||
```javascript
|
||||
var x = y || z;
|
||||
```
|
||||
not
|
||||
```javascript
|
||||
var x = y ? y : z;
|
||||
```
|
||||
|
||||
### Test Style:
|
||||
|
||||
Keep on the same line if it makes sense semantically and length is not an issue:
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
driver.elementByTagName('el1').should.become("123")
|
||||
.nodeify(done);
|
||||
|
||||
driver
|
||||
.elementsByTagName('el1').should.eventually.have.length(0)
|
||||
.nodeify(done);
|
||||
```
|
||||
|
||||
Alternatively use extra indents to improve readability:
|
||||
|
||||
```javascript
|
||||
h.driver
|
||||
.elementById('comments')
|
||||
.clear()
|
||||
.click()
|
||||
.keys("hello world")
|
||||
.getValue()
|
||||
.should.become("hello world")
|
||||
.elementById('comments')
|
||||
.getValue().should.become("hello world")
|
||||
.nodeify(done);
|
||||
|
||||
h.driver
|
||||
.execute("'nan'--")
|
||||
.should.be.rejectedWith("status: 13")
|
||||
.nodeify(done);
|
||||
```
|
|
@ -2,8 +2,17 @@
|
|||
|
||||
Thanks for your contribution to Appium! Here are the principles we use when
|
||||
writing javascript. Please conform to these so we can merge your pull request
|
||||
without going back and forth about style. The main principle is: *make your
|
||||
code look like the surrounding code*.
|
||||
without going back and forth about style. The main principle is: *make your
|
||||
code look like the surrounding code*.
|
||||
|
||||
### JavaScript
|
||||
|
||||
With the exception of the code that runs on the devices themselves
|
||||
([appium-uiautomator2-server](https://github.com/appium/appium-uiautomator2-server) for
|
||||
Android, [WebDriverAgent](https://github.com/appium/WebDriverAgent) for iOS), Appium is written in [Node.js](https://nodejs.org/). If you are
|
||||
not familiar with JavaScript, please familiarize yourself before attempting
|
||||
to modify the code. There are plenty of good, free resources (see, for example,
|
||||
[You Don't Know JavaScript](https://github.com/getify/You-Dont-Know-JS)).
|
||||
|
||||
### Rebasing
|
||||
|
||||
|
@ -14,266 +23,187 @@ rebased out of pull requests.
|
|||
|
||||
### Linting
|
||||
|
||||
All code (except for code in `bootstrap.js` which uses proprietary Apple
|
||||
methods) must pass JSLint. To check your code, you can simply run `grunt
|
||||
lint` from the Appium repo dir. If you've created a new .js file,
|
||||
please make sure it is covered by the wildcards in `grunt.js` or that it is
|
||||
added specifically.
|
||||
All code must pass [ESLint](https://eslint.org/). To check your code, you can simply run `npm run lint`
|
||||
from the Appium repo dir. The configuration is specified in the
|
||||
[eslint-config-appium](https://github.com/appium/eslint-config-appium) package.
|
||||
|
||||
It's easy to have your code linted as you type, which makes the whole process
|
||||
much smoother. We like [jshint](http://www.jshint.com),
|
||||
which has integrations with a lot of source code editors. The file `
|
||||
.jshintrc` is checked into the repo, and its contents are:
|
||||
|
||||
```json
|
||||
{
|
||||
"laxcomma": true,
|
||||
"strict": true,
|
||||
"undef": true,
|
||||
"unused": true,
|
||||
"node": true,
|
||||
"eqeqeq": true,
|
||||
"trailing": true,
|
||||
"indent": 2
|
||||
}
|
||||
```
|
||||
|
||||
Since jshint does not enforce code style anymore, we also use
|
||||
[jscs](https://github.com/mdevils/node-jscs), for which it also exists some
|
||||
source editor integrations. The configuration file is:
|
||||
|
||||
```json
|
||||
{
|
||||
"excludeFiles": ["submodules/**", "node_modules/**",
|
||||
"./lib/server/static/**", "./lib/devices/firefoxos/atoms/*.js",
|
||||
"./test/harmony/**/*.js", "./sample-code/examples/node/**/*-yiewd.js",
|
||||
"./sample-code/apps/**", "./sample-code/examples/php/vendor/**"],
|
||||
"requireCurlyBraces": ["for", "while", "do", "try", "catch"],
|
||||
"requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch",
|
||||
"return", "try", "catch", "function"],
|
||||
"disallowMixedSpacesAndTabs": true,
|
||||
"disallowTrailingWhitespace": true,
|
||||
"requireSpacesInFunctionExpression": {
|
||||
"beforeOpeningCurlyBrace": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
These configuration files define the warnings you will see in your favorite
|
||||
editor. See [this page for jshint](http://www.jshint.com/platforms/) and
|
||||
[this page for jscs](https://github.com/mdevils/node-jscs#friendly-packages) to
|
||||
get the list of editors and platforms supported and how setup your editor for
|
||||
automatic linting.
|
||||
Most modern editors have integration with ESLint. See [here](https://eslint.org/docs/user-guide/integrations) for details.
|
||||
|
||||
### Style notes
|
||||
|
||||
We use a future version of JavaScript and take advantage of the [Babel](https://babeljs.io/)
|
||||
transpiler to render it down to what is supported by current versions of
|
||||
[Node.js](https://nodejs.org/). We use [ES2015](https://babeljs.io/learn-es2015/) (formerly called ES6) with some
|
||||
not-yet-standard features, namely [async/await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function). This style guide
|
||||
must be followed diligently in all Appium contributions! Luckily, linting
|
||||
will enforce most of these rules!
|
||||
|
||||
* Use two spaces for indentation, *no tabs*
|
||||
* Use single spaces around operators
|
||||
|
||||
```javascript
|
||||
var x = 1;
|
||||
```js
|
||||
let x = 1;
|
||||
```
|
||||
not
|
||||
```javascript
|
||||
var x=1;
|
||||
```js
|
||||
let x=1;
|
||||
```
|
||||
|
||||
* Spaces after commas and colons in lists, objects, function calls, etc...
|
||||
|
||||
```javascript
|
||||
var x = myFunc("lol", {foo: bar, baz: boo});
|
||||
```js
|
||||
let x = myFunc('lol', {foo: bar, baz: boo});
|
||||
```
|
||||
not
|
||||
```javascript
|
||||
var x = myFunc("lol",{foo:bar,baz:boo});
|
||||
```
|
||||
|
||||
* Always end statements with semicolons
|
||||
* Comma-first
|
||||
|
||||
```javascript
|
||||
var x = {
|
||||
foo: 'bar'
|
||||
, baz: 'boo'
|
||||
, wuz: 'foz'
|
||||
};
|
||||
```js
|
||||
let x = myFunc('lol',{foo:bar,baz:boo});
|
||||
```
|
||||
|
||||
* Always end statements with semicolons (see, for example, [Kent Dodds](https://blog.kentcdodds.com/semicolons-in-javascript-a-preference-dd8fc8b80895))
|
||||
* Brackets for `function`, `if`, etc... go on same line, `else` gets sandwiched
|
||||
|
||||
```javascript
|
||||
```js
|
||||
if (foo === bar) {
|
||||
// do something
|
||||
} else {
|
||||
// do something else
|
||||
}
|
||||
```
|
||||
not
|
||||
```js
|
||||
if (foo === bar)
|
||||
{
|
||||
// do something
|
||||
}
|
||||
else
|
||||
{
|
||||
// do something else
|
||||
}
|
||||
```
|
||||
|
||||
* Space after `if`, `for`, and `function`:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
if (foo === bar) {
|
||||
```
|
||||
```javascript
|
||||
for (var i = 0; i < 10; i ++) {
|
||||
```js
|
||||
for (let i = 0; i < 10; i ++) {
|
||||
```
|
||||
```javascript
|
||||
var lol = function (foo) {
|
||||
```js
|
||||
let lol = function (foo) {
|
||||
```
|
||||
not
|
||||
```javascript
|
||||
```js
|
||||
if(foo === bar) {
|
||||
```
|
||||
```javascript
|
||||
for(var i = 0; i < 10; i ++) {
|
||||
```js
|
||||
for(let i = 0; i < 10; i ++) {
|
||||
```
|
||||
```javascript
|
||||
var lol = function(foo) {
|
||||
```js
|
||||
let lol = function(foo) {
|
||||
```
|
||||
|
||||
* Avoid bracketless `if` for one-liners:
|
||||
|
||||
```javascript
|
||||
```js
|
||||
if (foo === bar) {
|
||||
foo++;
|
||||
}
|
||||
```
|
||||
not
|
||||
```javascript
|
||||
```js
|
||||
if (foo === bar)
|
||||
foo++;
|
||||
```
|
||||
except in the case of short-circuiting to a callback in the event of an error
|
||||
```javascript
|
||||
if (err) return cb(err);
|
||||
except in the case of short-circuiting to return/error
|
||||
```js
|
||||
if (err) return;
|
||||
```
|
||||
```js
|
||||
if (err) throw new Error(err);
|
||||
```
|
||||
|
||||
* Use `===`, not `==`, and `!==`, not `!=` for no surprises
|
||||
* Use `===`, not `==`, and `!==`, not `!=` for [no surprises](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness)
|
||||
* Line length shouldn't be longer than 79 characters
|
||||
* Break up long strings like this:
|
||||
|
||||
```javascript
|
||||
myFunc("This is a really long string that's longer " +
|
||||
"than 79 characters so I broke it up, woo");
|
||||
myFunc('This is a really long string that's longer ' +
|
||||
'than 79 characters so I broke it up, woo');
|
||||
```
|
||||
|
||||
* Comments should line up with code
|
||||
|
||||
```javascript
|
||||
```js
|
||||
if (foo === 5) {
|
||||
myFunc(foo);
|
||||
// foo++;
|
||||
}
|
||||
```
|
||||
not
|
||||
```javascript
|
||||
```js
|
||||
if (foo === 5) {
|
||||
myFunc(foo);
|
||||
//foo++;
|
||||
}
|
||||
```
|
||||
|
||||
* Subclassing by extending prototypes
|
||||
|
||||
```javascript
|
||||
var _ = require('underscore');
|
||||
|
||||
var SuperClass = function () {
|
||||
this.init();
|
||||
};
|
||||
|
||||
SuperClass.prototype.init = function () {
|
||||
// initialize
|
||||
};
|
||||
|
||||
// Create a subclass
|
||||
|
||||
var SubClass = function () {
|
||||
this.init();
|
||||
};
|
||||
|
||||
_.extend(SubClass.prototype, SuperClass.prototype);
|
||||
```
|
||||
|
||||
* Callbacks are always last in function definitions
|
||||
|
||||
```javascript
|
||||
var foo = function (arg1, arg2, cb) {
|
||||
...
|
||||
};
|
||||
```
|
||||
|
||||
* Define functions as variables
|
||||
|
||||
```javascript
|
||||
var myFunc = function (a, b, c) {};
|
||||
```
|
||||
not
|
||||
```javascript
|
||||
function myFunc (a, b, c) {}
|
||||
```
|
||||
|
||||
* Variable names should be camelCased:
|
||||
|
||||
```javascript
|
||||
var myVariable = 42;
|
||||
```js
|
||||
let myVariable = 42;
|
||||
```
|
||||
not
|
||||
```javascript
|
||||
var my_variable = 42;
|
||||
```js
|
||||
let my_variable = 42;
|
||||
```
|
||||
|
||||
* Check for undefined
|
||||
* Check for `undefined` using Appium's [appium-support](https://github.com/appium/appium-support) package
|
||||
|
||||
```javascript
|
||||
typeof myVariable === "undefined"
|
||||
```
|
||||
not
|
||||
```javascript
|
||||
myVariable === undefined
|
||||
```js
|
||||
util.hasValue(myVariable)
|
||||
```
|
||||
|
||||
* Define a variable with a default value
|
||||
|
||||
```javascript
|
||||
var x = y || z;
|
||||
```js
|
||||
let x = y || z;
|
||||
```
|
||||
not
|
||||
```javascript
|
||||
var x = y ? y : z;
|
||||
```js
|
||||
let x = y ? y : z;
|
||||
```
|
||||
|
||||
### Test Style:
|
||||
|
||||
Tests are written using [mocha](https://mochajs.org/) and [chai](http://chaijs.com/). The WebDriver
|
||||
library used is [wd](https://github.com/admc/wd).
|
||||
|
||||
Keep on the same line if it makes sense semantically and length is not an issue:
|
||||
|
||||
Examples:
|
||||
|
||||
```javascript
|
||||
driver.elementByTagName('el1').should.become("123")
|
||||
.nodeify(done);
|
||||
```js
|
||||
driver.elementByTagName('el1').should.become('123');
|
||||
|
||||
driver
|
||||
.elementsByTagName('el1').should.eventually.have.length(0)
|
||||
.nodeify(done);
|
||||
driver
|
||||
.elementsByTagName('el1').should.eventually.have.length(0);
|
||||
```
|
||||
|
||||
Alternatively use extra indents to improve readability:
|
||||
|
||||
```javascript
|
||||
h.driver
|
||||
```js
|
||||
driver
|
||||
.elementById('comments')
|
||||
.clear()
|
||||
.click()
|
||||
.keys("hello world")
|
||||
.keys('hello world')
|
||||
.getValue()
|
||||
.should.become("hello world")
|
||||
.should.become('hello world')
|
||||
.elementById('comments')
|
||||
.getValue().should.become("hello world")
|
||||
.nodeify(done);
|
||||
.getValue().should.become('hello world');
|
||||
|
||||
h.driver
|
||||
.execute("'nan'--")
|
||||
.should.be.rejectedWith("status: 13")
|
||||
.nodeify(done);
|
||||
driver
|
||||
.execute("'NaN'--")
|
||||
.should.be.rejectedWith('status: 13');
|
||||
```
|
||||
|
|
|
@ -28,27 +28,27 @@ The versioning and release model shape how we set Appium milestones. The next mi
|
|||
For Appium, the basic flow looks like this:
|
||||
|
||||
1. All PRs go to `master` (aka `trunk`).
|
||||
2. Whoever is leading a release acts as the "release engineer" (RE). When the release is ready to be shared (“Beta" status or better), the RE creates a new branch `v[Major].[Minor].[Patch]-branch`.
|
||||
3. PRs continue to go to `master`.
|
||||
4. If the release requires fixes committed to `master`, the RE cherrypicks those commits into the release branch.
|
||||
5. The release branch can be amended with hotfixes for subsequent patch releases. This allows the team to carefully scope small changesets for quick release. Fixes can also be pulled into previous release branches branches when needed.
|
||||
6. Rinse, repeat.
|
||||
1. Whoever is leading a release acts as the "release engineer" (RE). When the release is ready to be shared (“Beta" status or better), the RE creates a new branch `v[Major].[Minor].[Patch]-branch`.
|
||||
1. PRs continue to go to `master`.
|
||||
1. If the release requires fixes committed to `master`, the RE cherrypicks those commits into the release branch.
|
||||
1. The release branch can be amended with hotfixes for subsequent patch releases. This allows the team to carefully scope small changesets for quick release. Fixes can also be pulled into previous release branches branches when needed.
|
||||
1. Rinse, repeat.
|
||||
|
||||
Developers can maintain working branches however they like. These are strictly for personal use. All “official” branches should conform to the model defined above.
|
||||
|
||||
### Example
|
||||
|
||||
1. It’s 1 June. The Appium team plans on releasing 20.1-beta on 15 July and the full 20.1 release on 1 August.
|
||||
2. For the next six weeks, the team commits their work to `master`.
|
||||
3. On 15 July, the acting RE creates `20.1-branch`. The first node is tagged “20.1.0 Beta”.
|
||||
4. One team member begins fixing bugs in the beta. The fixes are committed to `master`.
|
||||
5. Other contributors begin committing changes that are planned for 20.2. These also go to `master`.
|
||||
6. The RE cherrypicks the fixes into `20.1-branch`, leaving the other changes on `master`.
|
||||
7. The team celebrates that all the beta bugs are fixed for the 1 August release.
|
||||
8. The RE tags HEAD of `20.1-branch` as `20.1.0` and publishes the release.
|
||||
9. A few weeks later, a crash is discovered in `20.1.0` and users need a fix NOW.
|
||||
10. The acting RE pulls the crash fix from master into `20.1-branch`, tags HEAD as `20.1.1`, and publishes the hotfix.
|
||||
11. The cycle repeats once the `20.2` release is ready.
|
||||
1. For the next six weeks, the team commits their work to `master`.
|
||||
1. On 15 July, the acting RE creates `20.1-branch`. The first node is tagged “20.1.0 Beta”.
|
||||
1. One team member begins fixing bugs in the beta. The fixes are committed to `master`.
|
||||
1. Other contributors begin committing changes that are planned for 20.2. These also go to `master`.
|
||||
1. The RE cherrypicks the fixes into `20.1-branch`, leaving the other changes on `master`.
|
||||
1. The team celebrates that all the beta bugs are fixed for the 1 August release.
|
||||
1. The RE tags HEAD of `20.1-branch` as `20.1.0` and publishes the release.
|
||||
1. A few weeks later, a crash is discovered in `20.1.0` and users need a fix NOW.
|
||||
1. The acting RE pulls the crash fix from master into `20.1-branch`, tags HEAD as `20.1.1`, and publishes the hotfix.
|
||||
1. The cycle repeats once the `20.2` release is ready.
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -239,8 +239,8 @@ module.exports = {
|
|||
["Contributing", ["contributing-to-appium",
|
||||
["Running Appium from Source", "appium-from-source.md"],
|
||||
["Developer Overview", "developers-overview.md"],
|
||||
["Standard Gulp Commands", "gulp.md"],
|
||||
["Appium Style Guide", "style-guide-2.0.md"],
|
||||
["Standard Dev Commands", "dev-tools.md"],
|
||||
["Appium Style Guide", "style-guide.md"],
|
||||
["How to Write Docs", "how-to-write-docs.md"],
|
||||
["Appium Package Structure", "appium-packages.md"],
|
||||
["Credits", "credits.md"]]]
|
||||
|
|
|
@ -74,7 +74,8 @@
|
|||
"precommit-test": "REPORTER=dot gulp once",
|
||||
"lint": "gulp eslint",
|
||||
"coverage": "gulp coveralls",
|
||||
"generate-docs": "babel-node ./commands-yml/parse.js"
|
||||
"generate-docs": "babel-node ./commands-yml/parse.js",
|
||||
"clean": "rm -rf node_modules && rm -rf package-lock.json && npm install"
|
||||
},
|
||||
"pre-commit": [
|
||||
"precommit-msg",
|
||||
|
|
Загрузка…
Ссылка в новой задаче