使用Nightwatch编写异步自定义命令

时间:2020-08-03 14:07:24

标签: javascript promise async-await nightwatch.js nightwatch

过去3天,我一直在尝试获得一个我正在使用的函数,该函数用于获取适合某个选择器的元素列表的CSS选择器路径,并在Nightwatch JS中作为自定义命令使用。

>

命令内容:

browser.getUniqueCssSelector('.note');

输出应为:

['HTML> BODY> SECTION.upper-container > DIV.notes:nth-child(1) > DIV.note:nth-child(1)',
'HTML> BODY> SECTION.upper-container > DIV.notes:nth-child(1) > DIV.note:nth-child(2)',
'HTML> BODY> SECTION.upper-container > DIV.notes:nth-child(2) > DIV.note:nth-child(1)',
'HTML> BODY> SECTION.bottom-container > DIV.inner > DIV.notes:nth-child(1) > DIV.note'
'HTML> BODY> SECTION.bottom-container > DIV.inner > DIV.notes:nth-child(2) > DIV.note']

等等。

我尝试了许多不同的方法来实现它,但没有成功,我对Async / Await还是很陌生,所以我没有很多运气,也无法在Nightwatch.js上关联示例指南(https://nightwatchjs.org/guide/extending-nightwatch/#writing-custom-commands)。

我使用How to generate unique css selector for DOM element?中的代码段编写了以下内容 :

// getUniqueCssSelector.js file
exports.command = async function(selector) {
        var browser = this;
     let result = browser.execute(function (selector) {

            const nodes = Array.from(document.querySelectorAll(selector))
            var nodesSelectors = [];

            nodes.forEach(node => {
                nodesSelectors.push(getCssSelectorShort(node));
            });
            return nodesSelectors;

            
            function getCssSelectorShort(el) {
                let path = [], parent;
                while (parent = el.parentNode) {
                let tag = el.tagName, siblings;
                path.unshift(
                    el.id ? `#${el.id}` : (
                    siblings = parent.children,
                    [].filter.call(siblings, sibling => sibling.tagName === tag).length === 1 ? tag :
                    `${tag}:nth-child(${1+[].indexOf.call(siblings, el)})`
                    )
                );
                el = parent;
                };
                return `${path.join(' > ')}`;
            };
            
            

        }, [selector], function(res) {
            console.log('************INSIDE COMMAND RETURN CALLBACK ');
            return res;

        })

        return result;

    }


从那里,我希望在调用此自定义命令的测试代码中能够await。该命令将必须在多个元素上调用,因此使其成为回调函数,虽然可以正常工作,但也将我的代码放入永恒的回调堆栈中,这使它看起来非常难看,非常快。

理想情况下,我希望代码变成这样:

// nwtest.js file
 let nodeSelectorsList= await browser.getUniqueCssSelectors('.note');
            console.log(nodeSelectorsList); // Would bring me back the entire set I posted above.

nodeSelectorsList.forEach(async (noteElement)=> {
                 let resultSingle = await browser.element('css selector', noteElement);
                 console.log(resultSingle); // Should print the elements returned individually
             })

不幸的是,我总是得到undefined作为我努力的成果。 :/

在长达近一周的时间里,我花了几天的时间来绞尽脑汁,尝试了Promise和Event的实现,但是这个实现超出了我的范围,因此我呼吁SO的帮助。任何帮助将不胜感激!。

1 个答案:

答案 0 :(得分:0)

我认为您可以将其包装为Promise,然后从外面等待,

// getUniqueCssSelector.js文件

exports.command = function (selector) {
    var browser = this;
    return new Promise(function (resolve, reject) {

        browser.execute(function (selector) {

            const nodes = Array.from(document.querySelectorAll(selector))
            var nodesSelectors = [];

            nodes.forEach(node => {
                nodesSelectors.push(getCssSelectorShort(node));
            });
            return nodesSelectors;


            function getCssSelectorShort(el) {
                let path = [],
                    parent;
                while (parent = el.parentNode) {
                    let tag = el.tagName,
                        siblings;
                    path.unshift(
                        el.id ? `#${el.id}` : (
                            siblings = parent.children,
                            [].filter.call(siblings, sibling => sibling.tagName === tag).length === 1 ? tag :
                            `${tag}:nth-child(${1+[].indexOf.call(siblings, el)})`
                        )
                    );
                    el = parent;
                };
                return `${path.join(' > ')}`;
            };



        }, [selector], function (res) {
            resolve(res);
        });
    });
}

// nwtest.js文件

let nodeSelectorsList = await browser.getUniqueCssSelectors('.note');
console.log(nodeSelectorsList); // Would bring me back the entire set I posted above.

nodeSelectorsList.forEach(async (noteElement) => {
    let resultSingle = await browser.element('css selector', noteElement);
    console.log(resultSingle); // Should print the elements returned individually
})