| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- /**
- * Abstract assertion class that will subclass all defined Chai assertions
- *
- * All assertions must implement the following api:
- *
- * - @type {function}
- * executeCommand
- * - @type {string}
- * elementFound
- * - @type {function}
- * elementNotFound
- * - @type {function}
- * retryCommand
- * - @type {string}
- * expected
- * - @type {string}
- * actual
- * - @type {string}
- * message
- * - @type {boolean}
- * passed
- *
- * @constructor
- */
- var util = require('util');
- var events = require('events');
- var Assertion = require('../../core/assertion.js');
- var chai = require('chai-nightwatch');
- var flag = chai.flag;
- var Utils = require('../../util/utils.js');
- function BaseAssertion() {
- }
- BaseAssertion.ASSERT_FLAGS = [
- 'be',
- 'that',
- 'have',
- 'which',
- 'equal',
- 'contains',
- 'matches',
- 'before',
- 'after',
- 'waitFor'
- ];
- /**
- * @override
- */
- BaseAssertion.prototype.executeCommand = function(callback) {};
- BaseAssertion.prototype.setAssertion = function(assertion) {
- this.assertion = assertion;
- return this;
- };
- BaseAssertion.prototype.flag = function(key, value) {
- if (typeof value == 'undefined') {
- return flag(this.assertion, key);
- }
- flag(this.assertion, key, value);
- return this;
- };
- BaseAssertion.prototype.setClient = function(client) {
- this.client = client;
- return this;
- };
- BaseAssertion.prototype.setProtocol = function(protocol) {
- this.protocol = protocol;
- return this;
- };
- BaseAssertion.prototype.init = function() {
- this.promise = this.flag('promise');
- this.element = this.flag('element');
- this.selector = this.flag('selector');
- this.setNegate();
- this.waitForMs = this.client.api.globals.waitForConditionTimeout || null;
- if (this.waitForMs) {
- this.flag('waitFor', this.waitForMs);
- }
- this.retryInterval = this.client.api.globals.waitForConditionPollInterval || 500;
- this.retries = 0;
- this.messageParts = [];
- this.abortOnFailure = typeof this.client.api.globals.abortOnAssertionFailure == 'undefined' || this.client.api.globals.abortOnAssertionFailure;
- this.passed = false;
- this.expected = null;
- this.elementResult = null;
- this.flags = [];
- };
- BaseAssertion.prototype.start = function() {
- this.promise.then(this.onPromiseResolved.bind(this), this.onPromiseRejected.bind(this));
- };
- BaseAssertion.prototype.onPromiseResolved = function(elementResult) {
- if (elementResult) {
- this.elementResult = elementResult;
- }
- this.executeCommand(function(result) {
- this.resultValue = result.value;
- this.resultStatus = result.status;
- this.resultErrorStatus = result.errorStatus;
- this.processFlags();
- this.elementFound();
- if (!this.passed && this.shouldRetry()) {
- this.scheduleRetry();
- } else {
- this.done();
- }
- }.bind(this));
- };
- BaseAssertion.prototype.onPromiseRejected = function(response) {
- this.processFlags();
- if (this.shouldRetry() && !this.negate) {
- this.scheduleRetry();
- return;
- }
- this.messageParts.push(' - element was not found');
- this.actual = 'not present';
- this.expected = 'present';
- this.elementNotFound();
- this.done();
- };
- BaseAssertion.prototype.processFlags = function() {
- BaseAssertion.ASSERT_FLAGS.forEach(function(entry) {
- var value = this.flag(entry);
- if ((typeof value != 'undefined') && (typeof this['@' + entry + 'Flag'] == 'function')) {
- this.flags.push([entry, value]);
- this['@' + entry + 'Flag'](value);
- }
- }.bind(this));
- };
- BaseAssertion.prototype.hasFlag = function(type) {
- return this.flags.some(function(flag) {
- return flag[0] === type;
- });
- };
- /**
- * @override
- */
- BaseAssertion.prototype.elementFound = function() {};
- /**
- * @override
- */
- BaseAssertion.prototype.elementNotFound = function() {};
- BaseAssertion.prototype.done = function() {
- this.formatMessage();
- var stackTrace = this.flag('element')._stackTrace;
- Assertion.assert(
- this.passed,
- this.actual,
- this.expected,
- this.message,
- this.abortOnFailure,
- stackTrace
- );
- this.element.emitter.emit('complete');
- };
- BaseAssertion.prototype.getResult = function(value, fn) {
- var result = fn.call(this);
- this.setNegate();
- return this.negate ? !result : result;
- };
- BaseAssertion.prototype.shouldRetryLocateElement = function() {
- return (!this.elementResult || this.resultStatus === 10 || this.resultErrorStatus === 10);
- };
- BaseAssertion.prototype.shouldRetry = function() {
- if (!this.waitForMs) {
- return false;
- }
- this.elapsedTime = this.getElapsedTime();
- return (this.elapsedTime < this.waitForMs);
- };
- BaseAssertion.prototype.getElapsedTime = function() {
- var timeNow = new Date().getTime();
- return timeNow - this.element.startTime;
- };
- BaseAssertion.prototype.scheduleRetry = function() {
- this.retries++;
- setTimeout(this.retryCommand.bind(this), this.retryInterval);
- };
- BaseAssertion.prototype.formatMessage = function() {
- this.message = Utils.format(this.message || this.message, this.selector);
- this.message += this.messageParts.join('');
- };
- BaseAssertion.prototype['@containsFlag'] = function(value) {
- var verb = (this.hasFlag('that') || this.hasFlag('which')) ? 'contains' : 'contain';
- this.conditionFlag(value, function() {
- return this.resultValue ? this.resultValue.indexOf(value) > -1 : false;
- }, [
- 'not ' + verb,
- verb
- ]);
- return this;
- };
- BaseAssertion.prototype['@equalFlag'] = function(value) {
- var verb;
- if (this.hasFlag('have')) {
- verb = (this.hasFlag('that') || this.hasFlag('which')) ? 'equals' : 'equal to';
- } else {
- verb = 'equal';
- }
- this.conditionFlag(value, function() {
- return this.resultValue == value;
- }, [
- 'not ' + verb,
- verb
- ]);
- return this;
- };
- BaseAssertion.prototype['@matchesFlag'] = function(re) {
- var adverb = this.hasFlag('that') || this.hasFlag('which');
- var verb = adverb ? 'matches' : 'match';
- this.conditionFlag(re, function() {
- return re.test(this.resultValue);
- }, [
- (adverb ? 'does ' : '') + 'not match',
- verb
- ]);
- return this;
- };
- BaseAssertion.prototype.conditionFlag = function(value, conditionFn, arrverb) {
- this.passed = this.getResult(value, conditionFn);
- var verb = this.negate ? arrverb[0]: arrverb[1];
- this.expected = verb + ' \'' + value + '\'';
- this.actual = this.resultValue;
- if (this.retries > 0) {
- return;
- }
- var needsSpace = this.messageParts.length === 0 ? true : this.messageParts[this.messageParts.length-1].slice(-1) != ' ';
- if (needsSpace) {
- verb = ' ' + verb;
- }
- if (!this.customMessage) {
- this.messageParts.push(
- verb,
- ': "', value, '"'
- );
- }
- };
- BaseAssertion.prototype.setNegate = function() {
- this.negate = this.flag('negate') || false;
- return this;
- };
- BaseAssertion.prototype['@beforeFlag'] = function(value) {};
- BaseAssertion.prototype['@afterFlag'] = function(value) {};
- BaseAssertion.prototype['@haveFlag'] = function(value) {};
- BaseAssertion.prototype['@waitForFlag'] = function(value) {
- if (this.waitForMs !== value) {
- this.waitForMs = value;
- if (!this.customMessage) {
- this.messageParts.push(this.checkWaitForMsg(this.waitForMs));
- }
- }
- };
- BaseAssertion.prototype['@thatFlag'] = function() {
- if (this.retries > 0) {
- return;
- }
- if (!this.customMessage) {
- this.messageParts.push(' that ');
- }
- return this;
- };
- BaseAssertion.prototype['@whichFlag'] = function() {
- if (this.retries > 0) {
- return;
- }
- if (!this.customMessage) {
- this.messageParts.push(' which ');
- }
- return this;
- };
- BaseAssertion.prototype['@beFlag'] = function() {};
- BaseAssertion.prototype.hasCondition = function() {
- return (this.hasFlag('contains') || this.hasFlag('equal') || this.hasFlag('matches'));
- };
- BaseAssertion.prototype.checkWaitForMsg = function(waitFor) {
- var preposition = this.flag('before') && 'in' ||
- this.flag('after') && 'after' ||
- 'in';
- return ' ' + preposition +' ' + waitFor + 'ms';
- };
- BaseAssertion.prototype.retryCommand = function() {
- if (this.shouldRetryLocateElement()) {
- this.promise = this.element.createPromise();
- this.promise.then(this.onPromiseResolved.bind(this), this.onPromiseRejected.bind(this));
- this.element.locate();
- } else {
- this.onPromiseResolved();
- }
- };
- module.exports = BaseAssertion;
|