У меня есть страница учетной записи с разделом адресной книги.Я запускаю тест, например, создаю и обновляю адрес, а затем в gherkin у меня в конце есть эта команда:
And I delete all the addresses
В common-steps.js у меня есть:
Then(/^I delete all the addresses$/,function(){
return client.addressBookCleaner();
})
Этофункция уже была там, и я пытаюсь выяснить, как она работает: в основном она работает рекурсивно и удаляет все адреса:
var addressBookCleaner = function () {
function clickMyLink() {
this
.click('[data-ctrl="addressbook.removeButton"]')
.waitForElementVisible('[data-action="confirm"]', 190000)
.pause(500)
.click('[data-action="confirm"]')
.waitForElementVisible('.uiLayer-removeButton .mfp-close', 190000)
.pause(500)
.click('.uiLayer-removeButton .mfp-close')
.pause(500);
}
function isDeleteFormVisible(callback) {
this
.pause(1000)
.isVisible('[data-ctrl="addressbook.removeButton"]', function (result) {
callback(result.status === 0 && result.value.length);
});
}
function verifyDeleteFormIsNotVisible(actual, message) {
this.verify.ok(!actual, message);
}
this
.waitForElementVisible('body', 190000)
.pause(1000)
.clickUntilNotVisible(clickMyLink.bind(this), isDeleteFormVisible.bind(this), verifyDeleteFormIsNotVisible.bind(this), 190000);
};
exports.command = function () {
debugger;
addressBookCleaner.call(this);
};
, как вы можете видеть, вызываемая функция - clickUntilNotVisible
:
exports.command = function (clickElementFunction, getVisibilityFunction, assertion, timeout, message) {
function clickAndGetVisiblity (callback) {
//debugger;
clickElementFunction();
getVisibilityFunction(callback);
}
function isTrue (actual) {
return !!actual;
}
return this.waitUntil(clickAndGetVisiblity, isTrue, assertion, timeout, message);
};
, который вызывает функцию waitUntil:
var util = require('util');
var events = require('events');
var TIMEOUT_RETRY_INTERVAL = 100;
function waitUntil() {
events.EventEmitter.call(this);
this.startTimeInMilliseconds = null;
}
util.inherits(waitUntil, events.EventEmitter);
/**
* The purpose of this command is to serve as a base for waitUntil_ commands. It will run the getActual function until
* the predicate funciton returns true or the timeout is reached. At that point, the assertion funciton will be called.
* @param getActual {Function} - should passe the found value to its callback. The callback will be passed as the only
* argument.
* @param predicate {Function} - the wait will end when this returns true. The actual value is passed as the only
* argument.
* @param assertion {Function} - the assertion to make. The assertion should pass when the predicate returns true. This
* function will be passed the actual value and the message.
* @param timeoutInMilliseconds {number} - the number of milliseconds to wait before timing out and failing.
* @param message {string} - the message to attach to the assertion. The elapsed time will be appended to this.
* @returns custom command waitUntil, which can be accessed as browser.waitUntil(args);
*/
waitUntil.prototype.command = function (getActual, predicate, assertion, timeoutInMilliseconds, message) {
message = message || 'waitUntil';
this.startTimeInMilliseconds = new Date().getTime();
var self = this;
this.check(getActual, predicate, function (actual, loadedTimeInMilliseconds) {
if (predicate(actual)) {
message += ': true after ' +
(loadedTimeInMilliseconds - self.startTimeInMilliseconds) + ' ms.';
} else {
message += ': timed out after ' + timeoutInMilliseconds + ' ms.';
}
assertion(actual, message);
self.emit('complete');
}, timeoutInMilliseconds);
return this;
};
waitUntil.prototype.check = function (getActual, predicate, callback, maxTimeInMilliseconds) {
var self = this;
getActual(function (result) {
// If the argument passed to the callback is an object, it is assumed that the format is of the argument passed
// to callbacks by the Nightwatch API, in which the object has a "value" attribute with the actual information.
var resultValue;
if (typeof result !== 'object') {
resultValue = result;
} else if (result.hasOwnProperty('value')) {
resultValue = result.value;
} else {
self.error('Result object does not have a value.');
return;
}
var now = new Date().getTime();
if (predicate(resultValue)) {
callback(resultValue, now);
} else if (now - self.startTimeInMilliseconds < maxTimeInMilliseconds) {
setTimeout(function () {
self.check(getActual, predicate, callback, maxTimeInMilliseconds);
}, TIMEOUT_RETRY_INTERVAL);
} else {
callback(resultValue, null);
}
});
};
module.exports = waitUntil;
Я не могу полностью понять, как это работает, в основном это работает рекурсивно, удаляя все адреса, а затем выдает ошибку (потому что, я полагаю, этоне находит никаких адресов): поэтому мне нужно изменить функцию, чтобы остановить ее.
Я изменил одну из функций модуля addressBookCleaner следующим образом:
function isDeleteFormVisible(callback) {
var self = this;
this
.pause(1000)
.element('css selector', '[data-ytos-ctrl="addressbook.removeButton"]', function (result) {
if(result.status === -1){
return self.pause(4000)
.verify.attributeContains('[data-ctrl="addressbook.addressesCount"]','data-address-count','0')
} else {
callback(result.status === 0 && result.value.length);
}
});
}
Это нене выдает никакой ошибки, но тест не заканчивается вообще, у меня есть это сообщение в консоли:
√ Testing if attribute data-address-count of <[data-ctrl="addressbook.addressesCount"]> contains "0".
Если я изменяю значение, передаваемое от 0 до другого числа, я получаю ошибку и тестне удается, но если это сorrect it not.
Если я добавлю функцию end () после проверки, браузер закроется, но я не получу никакого сообщения «тест пройден»