Skip to content

Commit

Permalink
chore(docs): SELENIUM_PROMISE_MANAGER docs + reorganize tests + fix p…
Browse files Browse the repository at this point in the history
…lugin docs

* Adding `SELENIUM_PROMISE_MANAGER` docs
  * Added information in `/docs/control-flow.md` about SELENIUM_PROMISE_MANAGER,
    including pointing people to `/spec/ts/` for examples.
  * Made `/docs/async-await.md`, which redirects to
    `/exampleTypescript/asyncAwait/README.md`.
  * Made `docs/typescript.md`, which redirects to `/exampleTypescript/`.
  * Added information about `@types/jasminewd2` to `exampleTypescript/README.md`.
  * Website updates to come in a future change
  * Closes angular#3692
* Reorganizing typescript tests
  * Moved our `/spec/install/noCF/` tests back to `/spec/ts` and restored
    `ts_spec_config.json`.
    * It turns out that typescript@~2.0.0 does support `-p config_file.json`.
      The thing it doesn't support is pointing `include` to a folder.  So rather
      than moving everything in angular#4062, we just needed to use globs.
  * Split `smokeSpec.ts` into `is_disabled_spec.ts` and `element_spec.ts`.
  * Renamed `noCFSmokeConf.ts` to `noCFBasicConf.ts` so it is more clearly
    analogous to `basicConf.js`.
  * Added test using blocking proxy for `noCFBasicConf.ts`.
* Fixing plugin docs
  * Removed redundent information in `/docs/plugins.md`.  Now redirects to
    `/lib/plugins.ts`.
  * Comment cleanup in `/lib/plugins.ts`
  * Export some necessary types in `/lib/index.ts`
  * Added compiled `/exampleTypescript/` files to `.npmignore`
  • Loading branch information
sjelin committed Feb 7, 2017
1 parent 0ad2381 commit da210ec
Show file tree
Hide file tree
Showing 23 changed files with 160 additions and 350 deletions.
3 changes: 3 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ spec/
stress/
testapp/
website/
exampleTypescript/*.js
exampleTypescript/node_modules/
exampleTypescript/tmp/

# Development files

Expand Down
4 changes: 4 additions & 0 deletions docs/async-await.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
`async`/`await`
===============

Please see [our TypeScript examples which use `async`/`await`](/exampleTypescript/asyncAwait/).
16 changes: 16 additions & 0 deletions docs/control-flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,22 @@ which are managed by a [control flow](https://github.com/SeleniumHQ/selenium/wik
and adapted for [Jasmine](http://jasmine.github.io/2.3/introduction.html).
A short summary about how Protractor interacts with the control flow is presented below.

Disabling the Control Flow
--------------------------

In the future, the control flow is being removed (see
[SeleniumHQ's github issue](https://github.com/SeleniumHQ/selenium/issues/2969)
for details). To disable the control flow in your tests, you can use the
`SELENIUM_PROMISE_MANAGER: false` [config option](/lib/config.ts#L644).

Instead of the control flow, you can synchronize your commands
with promise chaining or the upcomming ES7 feature `async`/`await`. See
[`/spec/ts/`](/spec/ts/) for examples of tests with the control flow disabled.

Because `async`/`await` uses native promises, it will make the Control Flow
unreliable. As such, if you're writing a library or plugin which needs to work
whether or not the Control Flow is enabled, you'll need to handle
synchronization using promise chaining.

Promises and the Control Flow
-----------------------------
Expand Down
274 changes: 19 additions & 255 deletions docs/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,6 @@ exports.config = {
};
```

An example of using the 'ngHint' plugin is shown below.

```javascript
plugins: [{
path: 'node_modules/protractor/plugins/ngHint',
}]
```

If your plugin is a node module, you may use it with the `package` option. For
example, if you did `npm install example-protractor-plugin` your config would
look like:
Expand All @@ -56,8 +48,8 @@ look like:
}]
```

Finally, if you are writing a small plugin which will only be used by one config
file, you can write the plugin inline into the config:
If you are writing a small plugin which will only be used by one config file,
you can write the plugin inline into the config:

```javascript
plugins: [{
Expand All @@ -69,253 +61,25 @@ file, you can write the plugin inline into the config:
}]
```

When using plugins, you should specify exactly one of `path`, `package`, or
`inline`.

Writing Plugins
---------------

Plugins are designed to work with any test framework (Jasmine, Mocha, etc),
so they use generic hooks which Protractor provides. Plugins may change
the output of Protractor by returning a results object.

Plugins are node modules which export an object with the following API:

```js
/**
* Sets up plugins before tests are run. This is called after the WebDriver
* session has been started, but before the test framework has been set up.
*
* @this {Object} bound to module.exports
*
* @throws {*} If this function throws an error, a failed assertion is added to
* the test results.
*
* @return {q.Promise=} Can return a promise, in which case protractor will wait
* for the promise to resolve before continuing. If the promise is
* rejected, a failed assertion is added to the test results.
*/
exports.setup = function() {};

/**
* This is called before the test have been run but after the test framework has
* been set up. Analogous to a config file's `onPreare`.
*
* Very similar to using `setup`, but allows you to access framework-specific
* variables/funtions (e.g. `jasmine.getEnv().addReporter()`)
*
* @throws {*} If this function throws an error, a failed assertion is added to
* the test results.
*
* @return {Q.Promise=} Can return a promise, in which case protractor will wait
* for the promise to resolve before continuing. If the promise is
* rejected, a failed assertion is added to the test results.
*/
exports.onPrepare = function() {};

/**
* This is called after the tests have been run, but before the WebDriver
* session has been terminated.
*
* @this {Object} bound to module.exports
*
* @throws {*} If this function throws an error, a failed assertion is added to
* the test results.
*
* @return {q.Promise=} Can return a promise, in which case protractor will wait
* for the promise to resolve before continuing. If the promise is
* rejected, a failed assertion is added to the test results.
*/
exports.teardown = function() {};

/**
* Called after the test results have been finalized and any jobs have been
* updated (if applicable).
*
* @this {Object} bound to module.exports
*
* @throws {*} If this function throws an error, it is outputted to the console
*
* @return {q.Promise=} Can return a promise, in which case protractor will wait
* for the promise to resolve before continuing. If the promise is
* rejected, an error is logged to the console.
*/
exports.postResults = function() {};

/**
* Called after each test block (in Jasmine, this means an `it` block)
* completes.
*
* @param {boolean} passed True if the test passed.
* @param {Object} testInfo information about the test which just ran.
*
* @this {Object} bound to module.exports
*
* @throws {*} If this function throws an error, a failed assertion is added to
* the test results.
*
* @return {q.Promise=} Can return a promise, in which case protractor will wait
* for the promise to resolve before outputting test results. Protractor
* will *not* wait before executing the next test, however. If the promise
* is rejected, a failed assertion is added to the test results.
*/
exports.postTest = function(passed, testInfo) {};

/**
* This is called inside browser.get() directly after the page loads, and before
* angular bootstraps.
*
* @this {Object} bound to module.exports
*
* @throws {*} If this function throws an error, a failed assertion is added to
* the test results.
*
* @return {q.Promise=} Can return a promise, in which case protractor will wait
* for the promise to resolve before continuing. If the promise is
* rejected, a failed assertion is added to the test results.
*/
exports.onPageLoad = function() {};

/**
* This is called inside browser.get() directly after angular is done
* bootstrapping/synchronizing. If browser.ignoreSynchronization is true, this
* will not be called.
*
* @this {Object} bound to module.exports
*
* @throws {*} If this function throws an error, a failed assertion is added to
* the test results.
*
* @return {q.Promise=} Can return a promise, in which case protractor will wait
* for the promise to resolve before continuing. If the promise is
* rejected, a failed assertion is added to the test results.
*/
exports.onPageStable = function() {};

/**
* Between every webdriver action, Protractor calls browser.waitForAngular() to
* make sure that Angular has no outstanding $http or $timeout calls.
* You can use waitForPromise() to have Protractor additionally wait for your
* custom promise to be resolved inside of browser.waitForAngular().
*
* @this {Object} bound to module.exports
*
* @throws {*} If this function throws an error, a failed assertion is added to
* the test results.
*
* @return {q.Promise=} Can return a promise, in which case protractor will wait
* for the promise to resolve before continuing. If the promise is
* rejected, a failed assertion is added to the test results, and protractor
* will continue onto the next command. If nothing is returned or something
* other than a promise is returned, protractor will continue onto the next
* command.
*/
exports.waitForPromise = function() {};

/**
* Between every webdriver action, Protractor calls browser.waitForAngular() to
* make sure that Angular has no outstanding $http or $timeout calls.
* You can use waitForCondition() to have Protractor additionally wait for your
* custom condition to be truthy.
*
* @this {Object} bound to module.exports
*
* @throws {*} If this function throws an error, a failed assertion is added to
* the test results.
*
* @return {q.Promise<boolean>|boolean} If truthy, Protractor will continue onto
* the next command. If falsy, webdriver will continuously re-run this
* function until it is truthy. If a rejected promise is returned, a failed
* assertion is added to the test results, and protractor will continue onto
* the next command.
*/
exports.waitForCondition = function() {};

/**
* Used when reporting results.
*
* If you do not specify this property, it will be filled in with something
* reasonable (e.g. the plugin's path)
*
* @type {string}
*/
exports.name = '';


/**
* Used to turn off default checks for angular stability
*
* Normally Protractor waits for all $timeout and $http calls to be processed
* before executing the next command. This can be disabled using
* browser.ignoreSynchronization, but that will also disable any
* <Plugin>.waitForPromise or <Plugin>.waitForCondition checks. If you want to
* disable synchronization with angular, but leave in tact any custom plugin
* synchronization, this is the option for you.
*
* This is used by users who want to replace Protractor's synchronization code
* with their own.
*
* @type {boolean}
*/
exports.skipAngularStability
```

Each of these exported properties are optional.
Plugins are node modules who's `module.exports` implement the `ProtractorPlugin`
interface. Please see [`/lib/plugins.ts`](/lib/plugins.ts#L25) for a list of
hooks that are available to plugins.

### Provided properties and functions
##### Provided properties and functions

Extra properties are added to your `module.exports` when Protractor loads your
plugin. These allow your plugin to do things like access its configuration
block or add test results. They are as follows:

```js
/**
* The plugin configuration object. Note that this is not the entire
* Protractor config object, just the entry in the plugins array for this
* plugin.
*
* @type {Object}
*/
exports.config;

/**
* Adds a failed assertion to the test's results.
*
* @param {string} message The error message for the failed assertion
* @param {specName: string, stackTrace: string} options Some optional extra
* information about the assertion:
* - specName The name of the spec which this assertion belongs to.
* Defaults to `PLUGIN_NAME + ' Plugin Tests'`.
* - stackTrace The stack trace for the failure. Defaults to undefined.
* Defaults to `{}`.
*
* @throws {Error} Throws an error if called after results have been reported
*/
exports.addFailure(message, options);

/**
* Adds a passed assertion to the test's results.
*
* @param {specName: string} options Extra information about the assertion:
* - specName The name of the spec which this assertion belongs to.
* Defaults to `PLUGIN_NAME + ' Plugin Tests'`.
* Defaults to `{}`.
*
* @throws {Error} Throws an error if called after results have been reported
*/
exports.addSuccess(options);

/**
* Warns the user that something is problematic.
*
* @param {string} message The message to warn the user about
* @param {specName: string} options Extra information about the assertion:
* - specName The name of the spec which this assertion belongs to.
* Defaults to `PLUGIN_NAME + ' Plugin Tests'`.
* Defaults to `{}`.
*/
exports.addWarning(message, options);
```

If you specify any of these properties in your plugin file, they will be
overwritten.
block or add test results. See `/lib/plugins.ts` for the full list.

### Writing Plugins in TypeScript

Expand Down Expand Up @@ -372,15 +136,6 @@ First Party Plugins
github repo [angular/protractor-timeline-plugin]
(https://github.com/angular/protractor-timeline-plugin).

* ngHint Plugin

The ngHint plugin uses [Angular Hint](https://github.com/angular/angular-hint)
to generate run-time hinting and then turns these hints into Protractor tests.
It is published at the npm module [`protractor-ng-hint-plugin`]
(https://www.npmjs.com/package/protractor-ng-hint-plugin) and stored at the
github repo [angular/protractor-ng-hint-plugin]
(https://github.com/angular/protractor-ng-hint-plugin).

* Console Plugin (Chrome Only)

The console plugin checks the browser log after each test for warnings and
Expand All @@ -389,6 +144,15 @@ First Party Plugins
github repo [angular/protractor-console-plugin]
(https://github.com/angular/protractor-console-plugin).

* ngHint Plugin (NOT MAINTAINED)

The ngHint plugin uses [Angular Hint](https://github.com/angular/angular-hint)
to generate run-time hinting and then turns these hints into Protractor tests.
It is published at the npm module [`protractor-ng-hint-plugin`]
(https://www.npmjs.com/package/protractor-ng-hint-plugin) and stored at the
github repo [angular/protractor-ng-hint-plugin]
(https://github.com/angular/protractor-ng-hint-plugin).

Community Plugins
-----------------

Expand Down
4 changes: 4 additions & 0 deletions docs/typescript.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
TypeScript
==========

Please see [our TypeScript examples](/exampleTypescript/).
7 changes: 6 additions & 1 deletion exampleTypescript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,13 @@ export let config: Config = {

## Ambient typings

Protractor also uses ambient types including jasmine and node. These are brought in via the `tsconfig.json` file, which uses npm module resolution to get types from `node_modules/@types`.
Protractor also uses ambient types including jasmine, jasminewd2, and node. These are brought in via the `tsconfig.json` file, which uses npm module resolution to get types from `node_modules/@types`.

If you are using the jasmine framework for your tests, make sure to do:

```
npm install --save-dev @types/jasmine @types/jasminewd2
```

## Compiling your code

Expand Down
Loading

0 comments on commit da210ec

Please sign in to comment.