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

Cypress中调用cy.函数仅能推送数组最后一项的问题求助

问题:Cypress中数组无法正确存储多网站产品数据,仅保留最后一项

学习Cypress时,尝试从不同网站抓取产品数据存入数组并排序,但调用cy命令后,数组只能保留最后一项数据,beforeEach()和afterEach()运行正常。期望实现所有网站的产品数据都能正确推入数组并输出。

初始可正常运行的代码

describe('Compare iPhone 15 Pro between eBay and Apple Store', () => {
    let productDetails = [];

    beforeEach(() => {
        // Load the existing productDetails array from localStorage if it exists
        const storedProductDetails = localStorage.getItem('productDetails');
        if (storedProductDetails) {
            productDetails = JSON.parse(storedProductDetails);
        }
    });

    afterEach(() => {
        // Store the productDetails array back into localStorage
        localStorage.setItem('productDetails', JSON.stringify(productDetails));
    });

    it('Visit eBay and gets the product details', () => {
        // Visit eBay and get product details
        // ...
        productDetails.push({ website: 'eBay', product: 'iPhone 15 Pro 256GB', price: itemPrice, link: linkValue });
    });

    it('Visit Apple store and gets the product details', () => {
        // Visit Apple store and get product details
        // ...
        productDetails.push({ website: 'Apple Store', product: 'iPhone 15 Pro 256GB', price: itemPrice, link: linkValue });
    });

    it('Print the product details array', () => {
        // Log the product details array
        for (let i = 0; i < productDetails.length; i++) {
            cy.log('Product Details: ' + JSON.stringify(productDetails[i]));
        }
    });
});

添加cy函数后仅保留最后一项的代码

describe('Compare iPhone 15 Pro between eBay and Apple Store', () => {
    let productDetails = [];

    beforeEach(() => {
        // Load the existing productDetails array from localStorage if it exists
        const storedProductDetails = localStorage.getItem('productDetails');
        if (storedProductDetails) {
            productDetails = JSON.parse(storedProductDetails);
        }
    });

    afterEach(() => {
        // Store the productDetails array back into localStorage
        localStorage.setItem('productDetails', JSON.stringify(productDetails));
    });

    it('Visit eBay and gets the product details', () => {
        // Visit eBay and get product details
        // ...
        cy.visit('https://www.ebay.com.my/');
    
        // Search for iPhone 15 Pro 256GB
        cy.get('input.gh-tb[name="_nkw"]').type('iphone 15 pro 256gb new'); // class & attribute
        cy.get('input#gh-btn').click();
    
        cy.get('.srp-results.srp-list.clearfix').within(() => {
            cy.get('li').first().should('be.visible');
        });
    
        cy.get('li#item405343ae00 span.s-item__price span.ITALIC').invoke('text').then((price) => {
            const itemPrice = price;
            cy.log('Price: ', itemPrice);

            cy.url().then(url => {
                cy.log('Current URL:', url);
                const linkValue = url;
                productDetails.push({ website: 'eBay', product: 'iPhone 15 Pro 256GB', price: itemPrice, link: linkValue });
                localStorage.setItem('productDetails', JSON.stringify(productDetails));
                cy.log('Product Details eBay: ', productDetails);
            });
        });
        //productDetails.push({ website: 'eBay', product: 'iPhone 15 Pro 256GB', price: 'itemPrice', link: 'linkValue' });
    });

    it('Visit Apple store and gets the product details', () => {
        // Visit Apple store and get product details
        // ...
        cy.visit('https://www.apple.com/my/');
        cy.get('#globalnav-menubutton-link-search').click();

        cy.get('.globalnav-searchfield-input').type('iphone 15 pro 256gb new').type('{enter}');
        cy.get('[data-analytics-title="iPhone 15 Pro and iPhone 15 Pro Max - Apple (MY)"]').click();

        cy.title().should('eq','iPhone 15 Pro and iPhone 15 Pro Max - Apple (MY)');

        cy.contains(/Buy/i);
        cy.get('.welcome__lockup-cta.show').click();

        cy.contains(/Buy iPhone 15 Pro/i);

        cy.get('.rc-dimension-selector-group.form-selector-group .rc-dimension-selector-row.form-selector').first().click();

        cy.get('.colornav-items').within(() => {
            cy.get('li').first().click();
        });

        cy.get('.form-selector-title:contains("256")').click();

        cy.contains(/iPhone 15 Pro/i);
        cy.wait(2000);
        cy.get('.rc-prices-fullprice[data-autom="full-price"]').first().invoke('text').then((price) => {
            const itemPrice = price;
            cy.log('Price: ', itemPrice);

            cy.url().then(url => {
                cy.log('Current URL:', url);
                const linkValue = url;
                productDetails.push({website: 'Apple Store', product: 'iPhone 15 Pro 256GB', price: itemPrice, link: linkValue});
                localStorage.setItem('productDetails', JSON.stringify(productDetails));
                cy.log('Product Details: ', productDetails);
            });
        });
        //productDetails.push({ website: 'Apple Store', product: 'iPhone 15 Pro 256GB', price: 'itemPrice', link: 'linkValue' });
    });

    it('Print the product details array', () => {
        // Log the product details array
        for (let i = 0; i < productDetails.length; i++) {
            cy.log('Product Details: ' + JSON.stringify(productDetails[i]));
        }
    });
});

问题原因

  1. 环境隔离:Cypress测试代码运行在Node.js环境,直接调用localStorage访问的是Node环境的存储,而非测试页面的浏览器localStorage,两者完全独立,导致数据无法正确共享。
  2. 异步时序:cy命令是异步执行的,beforeEach/afterEach是同步执行的,afterEach执行时,cy回调里的数组push操作还未完成,存储的仍是初始空数组。

解决方案

改用Cypress环境变量跨用例共享数据,并通过cy.window()访问浏览器localStorage,确保数据正确累加:

describe('Compare iPhone 15 Pro between eBay and Apple Store', () => {
  beforeEach(() => {
    // 从浏览器localStorage加载数据到Cypress环境变量
    cy.window().then(win => {
      const storedDetails = win.localStorage.getItem('productDetails');
      Cypress.env('productDetails', storedDetails ? JSON.parse(storedDetails) : []);
    });
  });

  afterEach(() => {
    // 将环境变量中的数据存入浏览器localStorage
    cy.window().then(win => {
      const details = Cypress.env('productDetails') || [];
      win.localStorage.setItem('productDetails', JSON.stringify(details));
    });
  });

  it('Visit eBay and gets the product details', () => {
    cy.visit('https://www.ebay.com.my/');
    
    cy.get('input.gh-tb[name="_nkw"]').type('iphone 15 pro 256gb new');
    cy.get('input#gh-btn').click();
    
    cy.get('.srp-results.srp-list.clearfix').within(() => {
      cy.get('li').first().should('be.visible');
    });
    
    cy.get('li#item405343ae00 span.s-item__price span.ITALIC').invoke('text').then(price => {
      cy.url().then(url => {
        // 获取当前数组并添加新数据
        const currentDetails = Cypress.env('productDetails');
        currentDetails.push({ 
          website: 'eBay', 
          product: 'iPhone 15 Pro 256GB', 
          price: price, 
          link: url 
        });
        Cypress.env('productDetails', currentDetails);
        
        cy.log('Product Details eBay: ', currentDetails);
      });
    });
  });

  it('Visit Apple store and gets the product details', () => {
    cy.visit('https://www.apple.com/my/');
    cy.get('#globalnav-menubutton-link-search').click();

    cy.get('.globalnav-searchfield-input').type('iphone 15 pro 256gb new').type('{enter}');
    cy.get('[data-analytics-title="iPhone 15 Pro and iPhone 15 Pro Max - Apple (MY)"]').click();

    cy.title().should('eq','iPhone 15 Pro and iPhone 15 Pro Max - Apple (MY)');

    cy.contains(/Buy/i);
    cy.get('.welcome__lockup-cta.show').click();

    cy.contains(/Buy iPhone 15 Pro/i);

    cy.get('.rc-dimension-selector-group.form-selector-group .rc-dimension-selector-row.form-selector').first().click();

    cy.get('.colornav-items').within(() => {
      cy.get('li').first().click();
    });

    cy.get('.form-selector-title:contains("256")').click();

    cy.contains(/iPhone 15 Pro/i);
    cy.wait(2000);
    cy.get('.rc-prices-fullprice[data-autom="full-price"]').first().invoke('text').then(price => {
      cy.url().then(url => {
        const currentDetails = Cypress.env('productDetails');
        currentDetails.push({
          website: 'Apple Store', 
          product: 'iPhone 15 Pro 256GB', 
          price: price, 
          link: url 
        });
        Cypress.env('productDetails', currentDetails);
        
        cy.log('Product Details Apple: ', currentDetails);
      });
    });
  });

  it('Print and sort the product details array', () => {
    const details = Cypress.env('productDetails') || [];
    
    // 输出原始数据
    details.forEach(item => {
      cy.log('Product Details: ' + JSON.stringify(item));
    });

    // 按价格排序(处理价格字符串,去除非数字字符后转数字)
    const sortedDetails = [...details].sort((a, b) => {
      const priceA = parseFloat(a.price.replace(/[^0-9.]/g, ''));
      const priceB = parseFloat(b.price.replace(/[^0-9.]/g, ''));
      return priceA - priceB;
    });

    cy.log('Sorted Product Details (ascending price): ', sortedDetails);
  });
});

修改说明

  • 使用Cypress.env()存储数组,实现跨测试用例的数据共享,避免全局变量的异步时序问题。
  • 通过cy.window()访问浏览器的localStorage,确保和测试页面的存储环境一致。
  • 在每个异步回调中,先获取当前数组再添加新数据,保证数据正确累加。
  • 添加了价格排序逻辑,满足需求。

内容的提问来源于stack exchange,提问作者sm.chan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 10:04:52