Skip to content
This repository has been archived by the owner on Jul 29, 2024. It is now read-only.

Commit

Permalink
feat(plugins): Changed and expanded the plugin API
Browse files Browse the repository at this point in the history
* Changed the plugin API so that it is more uniform (see docs/plugins.md)
* Updated existing plugins to the new API
* Added the `onPageLoad` and `onPageSync` entry points for plugins for modifying `browser.get`
* Added the `waitForPromise` and `waitForCondition` entry points for plugins for modifying `waitForAngular`
* Added tests

This closes #2126 and helps out @andresdominguez
  • Loading branch information
sjelin committed Jun 26, 2015
1 parent aded26b commit f2a11a7
Show file tree
Hide file tree
Showing 17 changed files with 673 additions and 359 deletions.
191 changes: 168 additions & 23 deletions docs/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,64 +85,209 @@ 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.
*
* @param {Object} config The plugin configuration object. Note that
* this is not the entire Protractor config object, just the
* entry in the plugins array for this plugin.
* @this {Object} bound to module.exports
*
* @throws {*} If this function throws an error, a failed assertion is added to
* the test results.
*
* @return Object If an object is returned, it is merged with the Protractor
* result object. May return a promise.
* @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(config) {};
exports.setup = function() {};

/*
/**
* This is called after the tests have been run, but before the WebDriver
* session has been terminated.
*
* @param {Object} config The plugin configuration object.
* @this {Object} bound to module.exports
*
* @throws {*} If this function throws an error, a failed assertion is added to
* the test results.
*
* @return Object If an object is returned, it is merged with the Protractor
* result object. May return a promise.
* @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(config) {};
exports.teardown = function() {};

/*
/**
* Called after the test results have been finalized and any jobs have been
* updated (if applicable).
*
* @param {Object} config The plugin configuration object.
* @this {Object} bound to module.exports
*
* @throws {*} If this function throws an error, it is outputted to the console
*
* @return Return values are ignored.
* @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(config) {};
exports.postResults = function() {};

/**
* Called after each test block (in Jasmine, this means an `it` block)
* completes.
*
* @param {Object} config The plugin configuration object.
* @param {boolean} passed True if the test passed.
* @param {Object} testInfo information about the test which just ran.
*
* @return Object If an object is returned, it is merged with the Protractor
* result object. May return a promise.
* @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.postTest = function(config, passed, testInfo) {};
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 = '';
```

Each of these exported properties are totally optional.
Each of these exported properties are optional.

### 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);
```

The protractor results object follows the format specified in
the [Framework documentation](../lib/frameworks/README.md).
If you specify any of these properties in your plugin file, they will be
overwritten.

Accessibility Plugin
--------------------
Expand Down
14 changes: 8 additions & 6 deletions lib/frameworks/jasmine.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@ exports.run = function(runner, specs) {
};
RunnerReporter.prototype.reportSpecResults = function(spec) {
var specInfo = {
name: spec.suite.getFullName(),
category: spec.description
name: spec.description,
category: spec.suite.getFullName()
};
if (spec.results().passedCount) {
this.emitter.emit('testPass', specInfo);
} else if (spec.results().failedCount) {
this.emitter.emit('testFail', specInfo);
if (!spec.results().skipped) {
if (spec.results().passed()) {
this.emitter.emit('testPass', specInfo);
} else {
this.emitter.emit('testFail', specInfo);
}
}

var entry = {
Expand Down
Loading

0 comments on commit f2a11a7

Please sign in to comment.