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

首次调用selectPupil方法正常,第二次传参为何变为undefined?

Cypress 10.10.0中第二次调用selectPupil参数变为undefined的问题解决

问题描述

使用Cypress 10.10.0编写测试时,首次调用programs.selectPupil方法传入batchEnrollerChildId和batchEnrollerChildName参数时正常运行,但第二次调用该方法时,参数childId和childName变为undefined,触发断言错误。

测试代码

const programs = new require('../actions/programs.action')

describe('Batch Enroller tests', () => {
    const batchEnrollerChildId = 43607
    const batchEnrollerChildName = 'Child, Batch Enroller'

    it.only('Enroll and Unenroll student', () => {
        const programsTable = [['Universal Program', 'Universal Group', 'Universal', '$0.00'],
                               ['Custom Program', 'Custom Group', 'Custom', '$100.00'],
                               ['Monthly Program', 'Monthly Group', 'Monthly', '$50.00'], 
                               ['Monthly Dynamic Program', 'Monthly Group', 'Monthly Dynamic', '$10.00']]
        programs.goToProgramsPage()
        programs.openBatchEnrollerTab()
        programs.selectPupil(batchEnrollerChildId, batchEnrollerChildName)
        programs.selectPrograms(programsTable)
        programs.checkProgramTable(programsTable)
        programs.enroll()
        programs.goToProgramsPage()
        programs.openBatchEnrollerTab()
        programs.selectPupil(batchEnrollerChildId, batchEnrollerChildName)
        programsTable.forEach(function(program) {
            const programName = program[0] 
            programs.isProgramSelected(programName)
        })
        programs.checkProgramTable(programsTable)
        programs.unenroll()
    }) 

方法定义

const pupilsList = 'pupils_list'
const selectProgramField = '[value="Select program"]'

export function clickPupilCheckbox(childId) {
    cy.get(`[value="${childId}"]`)
      .parent()
      .click()
}

export function selectPupil(childId, childName) {
    cy.get(`[href="#${pupilsList}"]`).click()
      .parent()
      .should('have.class', 'active')
    cy.get(`[id="${pupilsList}"]`).should('be.visible')
    cy.get(`[data-id="${childId}"]`)
      .as('childName')
      .should('have.text', childName)
    clickPupilCheckbox(childId)
    cy.get('@childName')
      .parent()
      .should('have.class', 'selected_pupils')
}

错误日志

Console was cleared
index.656179c6.js:99332 Command:   assert
index.656179c6.js:99332 Message:   expected [data-id="undefined"] to have text undefined, but the text was ''
index.656179c6.js:99332 Error:     AssertionError: expected '[data-id="undefined"]' to have text undefined, but the text was '' 

原因分析

  1. 核心问题:错误的模块实例化方式
    测试代码中使用new require('../actions/programs.action')是错误写法。require返回的是模块导出的普通对象(包含多个函数),而非构造函数。使用new关键字会导致programs对象的方法上下文被异常修改,第一次调用可能因临时缓存正常执行,但第二次调用时参数传递机制失效,导致childId和childName变为undefined。

  2. 潜在问题:全局别名冲突
    Cypress的别名(如@childName)是全局作用域的,在同一条测试用例中,第二次调用selectPupil时,cy.get('@childName')会优先获取第一次设置的别名,而新的别名还未完成绑定,可能加剧断言错误,但此问题是由第一个核心问题引发的次生问题。

解决方案

1. 修正模块引用方式

去掉new关键字,直接使用require获取模块导出的对象:

// 错误写法
// const programs = new require('../actions/programs.action')

// 正确写法
const programs = require('../actions/programs.action')

如果项目使用ES模块语法,也可以改为:

import * as programs from '../actions/programs.action'

2. 优化别名避免全局冲突(可选)

为了避免同一条测试用例中全局别名的冲突,可以将别名改为局部唯一名称:

export function selectPupil(childId, childName) {
    cy.get(`[href="#${pupilsList}"]`).click()
      .parent()
      .should('have.class', 'active')
    cy.get(`[id="${pupilsList}"]`).should('be.visible')
    // 使用结合childId的唯一别名
    cy.get(`[data-id="${childId}"]`)
      .as(`childName-${childId}`)
      .should('have.text', childName)
    clickPupilCheckbox(childId)
    cy.get(`@childName-${childId}`)
      .parent()
      .should('have.class', 'selected_pupils')
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 10:05:24