我是node和nightwatch的新手。我已经使用Selenium很多年了,但是我的公司已经转移到了all things node。无论如何,在nightwatch中,我试图在链接可见的时候点击它,然后循环不断地点击它,直到它不可见为止。下面是我的代码。如有任何建议,我们将不胜感激!
"Cart Cleanup": function (browser) {
browser
.url(environment + '/ShoppingBag')
.waitForElementVisible('div.cart-top-message', 190000)
.pause(3000)
.element('class name', 'delete-form', function (visible) {
while (visible.status !== -1) {
console.log(visible.status);
browser
.useXpath() //NOW USING XPATH
.click('/html/body/div[5]/div[2]/div/div[2]/div[1]/div/div[3]/div[4]/div[2]/form[2]/input')
.useCss()
.pause(3000)
.element('class name', 'delete-form', function (visible2) {
visible = visible2
})
}
})
}发布于 2015-11-11 07:13:47
解决此问题的最好方法是创建自定义命令。Nightwatch自定义命令文档:http://nightwatchjs.org/guide#writing-custom-commands
为了更容易地解决这样的问题,我创建了一个"waitUntil“自定义命令,它是其他自定义命令的基础:
// WaitUntil.js, in custom commands folder specified in nightwatch.json
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;使用此模块,可以很容易地创建waitUntilTrue、waitUntilEqual等命令。您还可以创建一个"clickUntilNotVisible“命令来解决您的问题(显然,如果这是您唯一的用例,则可以将其与上述命令结合使用并进行简化):
// clickUntilNotVisible.js, in custom commands folder specified in nightwatch.json
exports.command = function (clickElementFunction, getVisibilityFunction, assertion, timeout, message) {
var browser = this;
function clickAndGetVisiblity (callback) {
clickElementFunction();
getVisibilityFunction(callback);
}
function isTrue (actual) {
return !!actual;
}
return browser.waitUntil(clickAndGetVisiblity, isTrue, assertion, timeout, message);
};现在我们已经定义了这个clickUntilNotVisible命令,我们可以解决您的问题了:
function clickMyLink() {
browser
.useXpath() //NOW USING XPATH
.click('/html/body/div[5]/div[2]/div/div[2]/div[1]/div/div[3]/div[4]/div[2]/form[2]/input')
.useCss();
}
function isDeleteFormVisible(callback) {
browser
.pause(3000)
.elements('class name', 'delete-form', function (result) {
callback(result.status === 0 && result.value.length);
});
}
function verifyDeleteFormIsNotVisible (actual, message) {
browser.verify.ok(!actual, message);
}
module.exports = {
"Cart Cleanup": function (browser) {
browser
.url(environment + '/ShoppingBag')
.waitForElementVisible('div.cart-top-message', 190000)
.pause(3000)
.clickUntilNotVisible(clickMyLink, isDeleteFormVisible, verifyDeleteFormIsNotVisible, 190000);
}
};请注意,这使用了我所做的,可能不是你解决这个问题的最有效的方法,但希望它能给你一些如何自己解决它的想法。此外,除了waitUntil模块之外,所有这些代码都是未经测试的,因此如果不进行一点调试,它可能无法工作。
发布于 2019-06-06 15:17:11
这可能会对某些人有帮助。我需要一遍又一遍地循环测试,并成功做到了以下几点:
const doThing = () => {
browser.pause(20000);
doThing();
};
doThing();发布于 2019-06-07 22:54:59
在提供解决方案之前,先给出一些关于当前代码的反馈:
//input[@class="..."]之类的内容,或输入标记内的其他属性,因为您希望获得输入标记。pause而不使用1000,仅在异常情况下使用现在,关于您的问题,为了在元素可见时单击它,您可以使用isVisible方法:https://nightwatchjs.org/api/#isVisible
function clickWhileVisible(browser) {
browser.isVisible('css selector', '#your_element', ({ value }) => {
if (value === true) {
browser
.click('#your_element')
// you can increase/decrease pause if you want a pause between clicks
.pause(500);
clickWhileVisible(browser)
}
})}
您还可以添加重试机制,以确保它不会永远运行:
function clickWhileVisible(browser, retry) {
browser.isVisible('css selector', '#your_element', ({ value }) => {
if (value === true && retry <=10) { //retries number can be modified
browser
.click('#your_element')
.pause(500);
clickWhileVisible(browser, retry+1)
}
})https://stackoverflow.com/questions/29021729
复制相似问题