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

如何用Jest测试React商品列表组件的价格筛选功能?

React商品列表组件价格筛选功能的Jest测试方案

一、能否用Jest测试该功能?

完全可以。Jest配合React Testing Library是React组件单元测试的主流方案,能够覆盖状态更新、函数逻辑、UI渲染变化等核心场景,你的价格筛选功能完全可以用这套组合测试。

二、具体实现步骤

1. 安装必要依赖

确保项目已安装以下依赖:

npm install --save-dev jest @testing-library/react @testing-library/jest-dom @testing-library/user-event

2. 创建测试文件

在组件目录下创建ProductsList.test.js文件。

3. 编写测试用例

以下是针对价格筛选功能的核心测试用例:

(1)测试基础初始化与上下文数据注入

首先需要模拟ContextProvider和useParams的返回值,因为组件依赖这两个外部数据:

import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import ProductsList from './ProductsList';
import { ContextProvider } from '../../Others/AuthContext/authContext';
import { MemoryRouter, Routes, Route } from 'react-router-dom';

// 模拟测试用商品数据
const mockProducts = [
  { _id: '1', name: '手链1', price: '100', category: 'Bracelet', img: ['img1.jpg'] },
  { _id: '2', name: '手链2', price: '500', category: 'Bracelet', img: ['img2.jpg'] },
  { _id: '3', name: '手链3', price: '1000', category: 'Bracelet', img: ['img3.jpg'] },
];

// 包裹组件的辅助函数
const renderWithProviders = (productId = 'Bracelet') => {
  return render(
    <ContextProvider value={{ data: { Bracelet: mockProducts } }}>
      <MemoryRouter initialEntries={[`/products/${productId}`]}>
        <Routes>
          <Route path="/products/:productId" element={<ProductsList />} />
        </Routes>
      </MemoryRouter>
    </ContextProvider>
  );
};

(2)测试滑块更新价格状态

验证拖动滑块时priceFrom和priceTo状态是否正确更新:

test('价格滑块拖动时更新priceFrom和priceTo状态', async () => {
  const user = userEvent.setup();
  renderWithProviders();

  // 找到滑块的两个thumb元素
  const thumbs = screen.getAllByRole('slider');
  expect(thumbs).toHaveLength(2);

  // 拖动第一个thumb到200的位置
  await user.drag(thumbs[0], { target: { value: 200 } });
  // 拖动第二个thumb到800的位置
  await user.drag(thumbs[1], { target: { value: 800 } });

  // 验证滑块显示的数值是否正确
  expect(thumbs[0]).toHaveTextContent('200');
  expect(thumbs[1]).toHaveTextContent('800');
});

(3)测试筛选功能正常工作

验证点击Apply按钮后,商品列表正确筛选:

test('点击Apply按钮后正确筛选价格区间内的商品', async () => {
  const user = userEvent.setup();
  renderWithProviders();

  // 设置价格区间
  const thumbs = screen.getAllByRole('slider');
  await user.drag(thumbs[0], { target: { value: 200 } });
  await user.drag(thumbs[1], { target: { value: 800 } });

  // 点击Apply按钮
  const applyBtn = screen.getByRole('button', { name: /apply/i });
  await user.click(applyBtn);

  // 验证只显示价格在200-800之间的商品(手链2,价格500)
  const productNames = screen.getAllByText(/手链/i);
  expect(productNames).toHaveLength(1);
  expect(productNames[0]).toHaveTextContent('手链2');
});

(4)测试无匹配商品的场景

验证当筛选无结果时,显示正确的提示:

test('筛选无匹配商品时显示"Nothing found"提示', async () => {
  const user = userEvent.setup();
  renderWithProviders();

  // 设置一个没有商品匹配的区间
  const thumbs = screen.getAllByRole('slider');
  await user.drag(thumbs[0], { target: { value: 1500 } });
  await user.drag(thumbs[1], { target: { value: 2000 } });

  // 点击Apply按钮
  const applyBtn = screen.getByRole('button', { name: /apply/i });
  await user.click(applyBtn);

  // 验证提示文本
  expect(screen.getByText(/Nothing found based on your range/i)).toBeInTheDocument();
});

(5)测试重置筛选功能

验证点击Reset按钮后,价格区间和商品列表恢复初始状态:

test('点击Reset按钮后重置价格区间和商品列表', async () => {
  const user = userEvent.setup();
  renderWithProviders();

  // 修改价格区间并应用筛选
  const thumbs = screen.getAllByRole('slider');
  await user.drag(thumbs[0], { target: { value: 200 } });
  await user.drag(thumbs[1], { target: { value: 800 } });
  const applyBtn = screen.getByRole('button', { name: /apply/i });
  await user.click(applyBtn);

  // 点击Reset按钮
  const resetBtn = screen.getByRole('button', { name: /reset/i });
  await user.click(resetBtn);

  // 验证滑块回到初始值(0和1000)
  expect(thumbs[0]).toHaveTextContent('0');
  expect(thumbs[1]).toHaveTextContent('1000');
  // 验证商品列表恢复为3个
  expect(screen.getAllByText(/手链/i)).toHaveLength(3);
});

三、替代测试方案

如果你的测试需求更侧重端到端的用户交互流程(比如从打开页面到完成筛选的完整操作),可以选择:

  • Cypress:适合编写端到端测试,模拟真实用户操作,覆盖完整流程。
  • Playwright:跨浏览器的端到端测试工具,功能强大,支持多种浏览器。

如果希望单独测试filterItem函数的逻辑,可以把该函数从组件中抽离出来,编写独立的纯函数测试,不需要依赖React组件环境:

// 抽离filterItem逻辑为纯函数
export const filterProducts = (products, priceFrom, priceTo) => {
  if (!priceFrom || !priceTo) return [];
  return products.filter(item => Number(item.price) >= priceFrom && Number(item.price) <= priceTo);
};

// 纯函数测试用例
test('filterProducts正确筛选价格区间', () => {
  const testProducts = [
    { price: '100' }, { price: '500' }, { price: '1000' }
  ];
  expect(filterProducts(testProducts, 200, 800)).toEqual([{ price: '500' }]);
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 13:37:00