Cypress deep equal断言行为异常及数组操作问题求助
问题原因分析与解决方案
核心问题:Cypress异步执行模型与同步代码的冲突
你的代码矛盾点根源在于Cypress命令是异步排队执行的,但变量声明、expect断言这类同步代码会先于所有Cypress命令运行,导致断言时数组还未被填充数据,而你看到的cy.task('log')输出是数组填充后才执行的,所以出现了“log有数据但断言没报错”的错位现象。
1. 为什么断言没报错?
代码实际执行顺序如下:
- 同步代码优先执行:声明空数组
unsortedItemPrices和sortedItemPrices,对空数组执行sort().reverse()(空数组操作后仍为空)。 - 所有
cy.get()、cy.task()命令被加入Cypress异步命令队列,此时数组还未被each()填充数据。 - 最后一行
sortedItemPrices.to.deep.equal(unsortedItemPrices.sort().reverse())是同步断言,此时两个数组都是空数组[],自然断言通过。 - 之后Cypress才开始执行命令队列中的
each(),填充数组,再执行cy.task('log')输出填充后的数组——你看到的log数据是断言执行后才生成的。
2. 修改log语句后为什么出现奇怪错误?
你修改的log语句:
cy.task('log', unsortedItemPrices.sort((a, b) => parseFloat(a) - parseFloat(b)).reverse().push(1));
这里有两个关键问题:
push()方法返回的是数组新长度,而非修改后的数组本身,所以你传给cy.task('log')的是数字(比如空数组push(1)后返回1),不是数组。sort()和reverse()都是原地修改数组的方法,执行这行代码时(同步计算log参数),会把1推进unsortedItemPrices数组。此时断言已经执行过,但同步修改数组后,后续可能触发的断言(或Cypress的异步校验)会检测到sortedItemPrices是空数组,而unsortedItemPrices.sort().reverse()变成了[1],因此抛出expected [] to deeply equal [1]的错误。
正确写法(修复异步问题)
要确保断言在数组填充完成后执行,必须把断言放在Cypress的异步命令链里,用.then()等待前置命令完成:
it('Validate Price High - Low sorting', () => { // 先获取未排序的价格数据 cy.get(inventoryPage.itemsPrice).then(($items) => { // 将元素转换为价格数组 const unsortedItemPrices = $items.map((index, item) => { return Cypress.$(item).text().replace('$', ''); }).get(); // 把jQuery对象转为原生数组 // 生成预期的降序排序结果(用数组副本避免修改原数组) const expectedSortedPrices = [...unsortedItemPrices].sort((a, b) => { return parseFloat(b) - parseFloat(a); // 直接降序,无需reverse }); // 执行排序操作 cy.get(inventoryPage.sortDropdown) .should('have.length', 4) .select('hilo'); // 获取排序后的价格并断言 cy.get(inventoryPage.itemsPrice).then(($sortedItems) => { const sortedItemPrices = $sortedItems.map((index, item) => { return Cypress.$(item).text().replace('$', ''); }).get(); cy.task('log', unsortedItemPrices); cy.task('log', sortedItemPrices); expect(sortedItemPrices).to.deep.equal(expectedSortedPrices); }); }); });
关键修复点:
- 用
.then()包裹数据获取与断言,确保在cy.get()完成后再处理数组。 - 用
[...unsortedItemPrices]创建数组副本,避免sort()原地修改原数组影响后续逻辑。 - 直接使用降序排序逻辑
parseFloat(b) - parseFloat(a),比升序后reverse()更直观。 - 用jQuery的
.map().get()转换元素数组,比.each()+push()更简洁可靠。
内容的提问来源于stack exchange,提问作者Constantin Suiu
相关产品推荐
相关产品推荐

