首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >nightwatch js while循环

nightwatch js while循环
EN

Stack Overflow用户
提问于 2015-03-13 06:45:55
回答 3查看 4.1K关注 0票数 0

我是node和nightwatch的新手。我已经使用Selenium很多年了,但是我的公司已经转移到了all things node。无论如何,在nightwatch中,我试图在链接可见的时候点击它,然后循环不断地点击它,直到它不可见为止。下面是我的代码。如有任何建议,我们将不胜感激!

代码语言:javascript
复制
"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
                    })
            }
        })
}
EN

回答 3

Stack Overflow用户

发布于 2015-11-11 07:13:47

解决此问题的最好方法是创建自定义命令。Nightwatch自定义命令文档:http://nightwatchjs.org/guide#writing-custom-commands

为了更容易地解决这样的问题,我创建了一个"waitUntil“自定义命令,它是其他自定义命令的基础:

代码语言:javascript
复制
// 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“命令来解决您的问题(显然,如果这是您唯一的用例,则可以将其与上述命令结合使用并进行简化):

代码语言:javascript
复制
// 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命令,我们可以解决您的问题了:

代码语言:javascript
复制
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模块之外,所有这些代码都是未经测试的,因此如果不进行一点调试,它可能无法工作。

票数 4
EN

Stack Overflow用户

发布于 2019-06-06 15:17:11

这可能会对某些人有帮助。我需要一遍又一遍地循环测试,并成功做到了以下几点:

代码语言:javascript
复制
const doThing = () => {
    browser.pause(20000);
    doThing();
};

doThing();
票数 0
EN

Stack Overflow用户

发布于 2019-06-07 22:54:59

在提供解决方案之前,先给出一些关于当前代码的反馈:

  • 您的xpath非常长,并且在将来很容易失败。没有必要把绝对的部分放在上面。您可以将其替换为//input[@class="..."]之类的内容,或输入标记内的其他属性,因为您希望获得输入标记。
  • 尽量不使用pause而不使用1000,仅在异常情况下使用

现在,关于您的问题,为了在元素可见时单击它,您可以使用isVisible方法:https://nightwatchjs.org/api/#isVisible

代码语言:javascript
复制
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)
    } 
})

}

您还可以添加重试机制,以确保它不会永远运行:

代码语言:javascript
复制
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)
    } 
})
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29021729

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档