123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- const q = require("q");
- const webdriver = require("selenium-webdriver");
- const configParser_1 = require("./configParser");
- const logger_1 = require("./logger");
- const ptor_1 = require("./ptor");
- let logger = new logger_1.Logger('plugins');
- var PromiseType;
- (function (PromiseType) {
- PromiseType[PromiseType["Q"] = 0] = "Q";
- PromiseType[PromiseType["WEBDRIVER"] = 1] = "WEBDRIVER";
- })(PromiseType = exports.PromiseType || (exports.PromiseType = {}));
- /**
- * The plugin API for Protractor. Note that this API is unstable. See
- * plugins/README.md for more information.
- *
- * @constructor
- * @param {Object} config parsed from the config file
- */
- class Plugins {
- constructor(config) {
- /**
- * @see docs/plugins.md#writing-plugins for information on these functions
- */
- this.setup = this.pluginFunFactory('setup', PromiseType.Q);
- this.onPrepare = this.pluginFunFactory('onPrepare', PromiseType.Q);
- this.teardown = this.pluginFunFactory('teardown', PromiseType.Q);
- this.postResults = this.pluginFunFactory('postResults', PromiseType.Q);
- this.postTest = this.pluginFunFactory('postTest', PromiseType.Q);
- this.onPageLoad = this.pluginFunFactory('onPageLoad', PromiseType.WEBDRIVER);
- this.onPageStable = this.pluginFunFactory('onPageStable', PromiseType.WEBDRIVER);
- this.waitForPromise = this.pluginFunFactory('waitForPromise', PromiseType.WEBDRIVER);
- this.waitForCondition = this.pluginFunFactory('waitForCondition', PromiseType.WEBDRIVER, true);
- this.pluginObjs = [];
- this.assertions = {};
- this.resultsReported = false;
- if (config.plugins) {
- config.plugins.forEach((pluginConf, i) => {
- let path;
- if (pluginConf.path) {
- path = configParser_1.ConfigParser.resolveFilePatterns(pluginConf.path, true, config.configDir)[0];
- if (!path) {
- throw new Error('Invalid path to plugin: ' + pluginConf.path);
- }
- }
- else {
- path = pluginConf.package;
- }
- let pluginObj;
- if (path) {
- pluginObj = require(path);
- }
- else if (pluginConf.inline) {
- pluginObj = pluginConf.inline;
- }
- else {
- throw new Error('Plugin configuration did not contain a valid path or ' +
- 'inline definition.');
- }
- this.annotatePluginObj(pluginObj, pluginConf, i);
- logger.debug('Plugin "' + pluginObj.name + '" loaded.');
- this.pluginObjs.push(pluginObj);
- });
- }
- }
- ;
- /**
- * Adds properties to a plugin's object
- *
- * @see docs/plugins.md#provided-properties-and-functions
- */
- annotatePluginObj(obj, conf, i) {
- let addAssertion = (info, passed, message) => {
- if (this.resultsReported) {
- throw new Error('Cannot add new tests results, since they were already ' +
- 'reported.');
- }
- info = info || {};
- const specName = info.specName || (obj.name + ' Plugin Tests');
- const assertion = { passed: passed };
- if (!passed) {
- assertion.errorMsg = message;
- if (info.stackTrace) {
- assertion.stackTrace = info.stackTrace;
- }
- }
- this.assertions[specName] = this.assertions[specName] || [];
- this.assertions[specName].push(assertion);
- };
- obj.name = obj.name || conf.name || conf.path || conf.package || ('Plugin #' + i);
- obj.config = conf;
- obj.addFailure = (message, info) => {
- addAssertion(info, false, message);
- };
- obj.addSuccess = (options) => {
- addAssertion(options, true);
- };
- obj.addWarning = (message, options) => {
- options = options || {};
- logger.warn('Warning ' +
- (options.specName ? 'in ' + options.specName : 'from "' + obj.name + '" plugin') + ': ' +
- message);
- };
- }
- printPluginResults(specResults) {
- const green = '\x1b[32m';
- const red = '\x1b[31m';
- const normalColor = '\x1b[39m';
- const printResult = (message, pass) => {
- logger.info(pass ? green : red, '\t', pass ? 'Pass: ' : 'Fail: ', message, normalColor);
- };
- for (const specResult of specResults) {
- const passed = specResult.assertions.map(x => x.passed).reduce((x, y) => (x && y), true);
- printResult(specResult.description, passed);
- if (!passed) {
- for (const assertion of specResult.assertions) {
- if (!assertion.passed) {
- logger.error('\t\t' + assertion.errorMsg);
- if (assertion.stackTrace) {
- logger.error('\t\t' + assertion.stackTrace.replace(/\n/g, '\n\t\t'));
- }
- }
- }
- }
- }
- }
- /**
- * Gets the tests results generated by any plugins
- *
- * @see lib/frameworks/README.md#requirements for a complete description of what
- * the results object must look like
- *
- * @return {Object} The results object
- */
- getResults() {
- const results = { failedCount: 0, specResults: [] };
- for (const specName in this.assertions) {
- results.specResults.push({ description: specName, assertions: this.assertions[specName] });
- results.failedCount +=
- this.assertions[specName].filter(assertion => !assertion.passed).length;
- }
- this.printPluginResults(results.specResults);
- this.resultsReported = true;
- return results;
- }
- ;
- /**
- * Returns true if any loaded plugin has skipAngularStability enabled.
- *
- * @return {boolean}
- */
- skipAngularStability() {
- const result = this.pluginObjs.some(pluginObj => pluginObj.skipAngularStability);
- return result;
- }
- ;
- /**
- * Calls a function from a plugin safely. If the plugin's function throws an
- * exception or returns a rejected promise, that failure will be logged as a
- * failed test result instead of crashing protractor. If the tests results have
- * already been reported, the failure will be logged to the console.
- *
- * @param {Object} pluginObj The plugin object containing the function to be run
- * @param {string} funName The name of the function we want to run
- * @param {*[]} args The arguments we want to invoke the function with
- * @param {PromiseType} promiseType The type of promise (WebDriver or Q) that
- * should be used
- * @param {boolean} resultsReported If the results have already been reported
- * @param {*} failReturnVal The value to return if the function fails
- *
- * @return {webdriver.promise.Promise|Q.Promise} A promise which resolves to the
- * function's return value
- */
- safeCallPluginFun(pluginObj, funName, args, promiseType, failReturnVal) {
- const resolver = (done) => {
- const logError = (e) => {
- if (this.resultsReported) {
- this.printPluginResults([{
- description: pluginObj.name + ' Runtime',
- assertions: [{
- passed: false,
- errorMsg: 'Failure during ' + funName + ': ' + (e.message || e),
- stackTrace: e.stack
- }]
- }]);
- }
- else {
- pluginObj.addFailure('Failure during ' + funName + ': ' + e.message || e, { stackTrace: e.stack });
- }
- done(failReturnVal);
- };
- try {
- const result = pluginObj[funName].apply(pluginObj, args);
- if (webdriver.promise.isPromise(result)) {
- result.then(done, logError);
- }
- else {
- done(result);
- }
- }
- catch (e) {
- logError(e);
- }
- };
- if (promiseType == PromiseType.Q) {
- return q.Promise(resolver);
- }
- else if (ptor_1.protractor.browser.controlFlowIsEnabled()) {
- return new webdriver.promise.Promise(resolver);
- }
- else {
- return new Promise(resolver);
- }
- }
- pluginFunFactory(funName, promiseType, failReturnVal) {
- return (...args) => {
- const promises = this.pluginObjs.filter(pluginObj => typeof pluginObj[funName] === 'function')
- .map(pluginObj => this.safeCallPluginFun(pluginObj, funName, args, promiseType, failReturnVal));
- return promiseType == PromiseType.Q ? q.all(promises) : webdriver.promise.all(promises);
- };
- }
- }
- exports.Plugins = Plugins;
- //# sourceMappingURL=plugins.js.map
|