简体   繁体   English

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

[英]Writing Async Custom command with Nightwatch

I have been trying for the past 3 days without success to get a function i'm using to get the CSS Selector paths of a list of elements fitting a certain selector, to work as a custom command in Nightwatch JS.在过去的 3 天里,我一直在尝试获得一个 function,但没有成功,我正在使用它来获取适合某个选择器的元素列表的 CSS 选择器路径,以在 Nightwatch JS 中作为自定义命令工作。

What you give to the command:你给命令的内容:

browser.getUniqueCssSelector('.note');

What the output should be: output 应该是什么:

['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']

And so and so.等等。

I have tried lots of different ways to implement it but with no success, I am fairly new to Async/Await so I have not been having alot of luck and haven't been able to relate the examples on the Nightwatch.js guide ( https://nightwatchjs.org/guide/extending-nightwatch/#writing-custom-commands ) to my issue.我尝试了很多不同的方法来实现它,但没有成功,我对 Async/Await 还很陌生,所以我运气不好,也无法关联 Nightwatch.js 指南( https)上的示例://nightwatchjs.org/guide/extending-nightwatch/#writing-custom-commands )到我的问题。

I have written the following using the code segment found in How to generate unique css selector for DOM element?我使用如何为 DOM 元素生成唯一的 css 选择器中的代码段编写了以下内容? :

// 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;

    }


From there, I want in my test code which calls this custom command, to be able to await it.从那里,我希望在调用此自定义命令的测试代码中能够await它。 This command will have to be called on multiple elements so making it a callback function, while would work, would also put my code in an eternal callback stack which would make it look very ugly, very fast.这个命令必须在多个元素上调用,所以使它成为一个回调 function,虽然可以工作,但也会把我的代码放在一个永恒的回调堆栈中,这会让它看起来非常难看,非常快。

ideally, I want the code to become something like this:理想情况下,我希望代码变成这样:

// 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
             })

Unfortunately, I always get undefined as the fruit of my efforts.不幸的是,我总是undefined自己努力的成果。 :/ :/

I have been wrecking my brain over this for several days up to almost a week and tried both Promise and Event implementations, but this one was abit beyond me so I call on the help of SO.几天到将近一周,我一直在为此绞尽脑汁,并尝试了 Promise 和 Event 实现,但这一点超出了我的范围,所以我求助于 SO。 Any help would be massively appreciated..任何帮助将不胜感激..

I think you can wrap it as a Promise and then await from the outside,我认为您可以将其包装为 Promise 然后从外面等待,

// getUniqueCssSelector.js file // 获取UniqueCssSelector.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 file // 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 })

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM