You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nightwatch测试如何将嵌套函数封装为页面自定义命令循环操作元素

问题根源

你遇到的报错核心是this指向丢失,外加2处小的笔误/用法错误:

  1. 嵌套的普通函数会重置this指向,导致回调内部的this不再指向页面对象实例,自然找不到elements这类页面对象内置方法
  2. counterOfItemsInList的定位策略属性名写错了,你写的是locatorStrategy,正确属性是locateStrategy
  3. 用@前缀引用已定义的页面元素时,不需要额外指定定位策略,Nightwatch会自动读取你在元素配置里写的定位规则

修正后的productFuntionalityListPage.js完整代码

module.exports = {
    elements: {
        counterOfItemsInList: {
            // 修正属性名错误
            locateStrategy: 'css selector',
            selector: "input[data-id='counter']",
        },
        expandCollapseBtn: {
            locateStrategy: 'css selector',
            selector: '.expand_collapse_btn',
        },
        listOfItems: {
            locateStrategy: 'css selector',
            selector: '.list_of_items',
        }
    },
    commands: [{
        displayFunctionsList: function () {
            // 箭头函数保留外层this指向(即页面对象实例)
            const displayFunctionsList = (elems) => {
                // forEach的回调也用箭头函数,不改变this指向
                elems.value.forEach((element) => {
                    this.elementIdClick(element.ELEMENT)
                        .waitForElementVisible('@listOfItems')
                        .pause(2000)
                })
            }
            // 用@别名不需要传定位策略,直接传元素别名即可
            this.elements('@expandCollapseBtn', displayFunctionsList, 5000)
            // 支持链式调用
            return this
        },
        closeFunctionsList: function () {
            const closeFunctionsList = (elems) => {
                elems.value.forEach((element) => {
                    this.elementIdClick(element.ELEMENT)
                        .waitForElementVisible('@counterOfItemsInList')
                        .pause(2000)
                })
            }
            this.elements('@expandCollapseBtn', closeFunctionsList, 5000)
            return this
        }
    }]
}

可选替代方案(不习惯箭头函数可采用)

如果不想用箭头函数,也可以在自定义命令开头提前存储页面对象引用,所有内部调用都用存储的变量替代this即可,效果完全一致:

displayFunctionsList: function () {
    // 提前存储页面对象引用
    const self = this
    function displayFunctionsList(elems) {
        elems.value.forEach(function (element) {
            self.elementIdClick(element.ELEMENT)
                .waitForElementVisible('@listOfItems')
                .pause(2000)
        })
    }
    self.elements('@expandCollapseBtn', displayFunctionsList, 5000)
    return self
}

你现有的测试调用代码不需要做任何修改,直接运行即可正常执行。

内容的提问来源于stack exchange,提问作者Estefania Lomonaco

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 06:21:02