Files
novalon-website/src/components/sections/services-section.integration.test.tsx
T
张翔 ac2672729f feat: 实现内容管理API及相关功能
refactor(services-section): 重构服务展示组件使用API数据
refactor(news-section): 重构新闻展示组件使用API数据
refactor(products-section): 重构产品展示组件使用API数据

test: 添加API客户端和服务钩子的单元测试
test(e2e): 添加配置验证和API响应格式的端到端测试

ci: 更新Playwright测试配置
2026-03-13 18:55:25 +08:00

348 lines
8.4 KiB
TypeScript

import { describe, it, expect, beforeEach, afterEach, jest } from '@jest/globals';
import { render, screen, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';
import { ServicesSection } from './services-section';
jest.mock('framer-motion', () => ({
motion: {
div: ({ children, ...props }: any) => <div {...props}>{children}</div>,
},
useInView: () => true,
}));
jest.mock('next/link', () => {
return ({ children, href }: any) => <a href={href}>{children}</a>;
});
jest.mock('@/hooks/use-services', () => ({
useServices: jest.fn(),
}));
const { useServices } = require('@/hooks/use-services');
describe('ServicesSection Integration', () => {
beforeEach(() => {
jest.clearAllMocks();
});
afterEach(() => {
jest.restoreAllMocks();
});
describe('Data Loading States', () => {
it('should show loading state when data is loading', () => {
useServices.mockReturnValue({
services: [],
loading: true,
error: null,
refetch: jest.fn(),
});
render(<ServicesSection />);
expect(screen.getByText('加载中...')).toBeInTheDocument();
});
it('should render services when data is loaded successfully', async () => {
const mockServices = [
{
id: '1',
title: '测试服务1',
description: '这是一个测试服务',
icon: 'Code',
},
{
id: '2',
title: '测试服务2',
description: '这是另一个测试服务',
icon: 'Cloud',
},
];
useServices.mockReturnValue({
services: mockServices,
loading: false,
error: null,
refetch: jest.fn(),
});
render(<ServicesSection />);
await waitFor(() => {
expect(screen.getByText('测试服务1')).toBeInTheDocument();
expect(screen.getByText('测试服务2')).toBeInTheDocument();
});
});
it('should show error message when data loading fails', async () => {
useServices.mockReturnValue({
services: [],
loading: false,
error: new Error('Failed to load services'),
refetch: jest.fn(),
});
render(<ServicesSection />);
await waitFor(() => {
expect(screen.getByText('加载服务信息失败,请稍后重试')).toBeInTheDocument();
});
});
it('should show empty state when no services are available', async () => {
useServices.mockReturnValue({
services: [],
loading: false,
error: null,
refetch: jest.fn(),
});
render(<ServicesSection />);
await waitFor(() => {
expect(screen.getByText('暂无服务信息')).toBeInTheDocument();
});
});
});
describe('Service Display', () => {
it('should render all services from API', async () => {
const mockServices = [
{
id: '1',
title: '服务A',
description: '描述A',
icon: 'Code',
},
{
id: '2',
title: '服务B',
description: '描述B',
icon: 'Cloud',
},
{
id: '3',
title: '服务C',
description: '描述C',
icon: 'BarChart3',
},
];
useServices.mockReturnValue({
services: mockServices,
loading: false,
error: null,
refetch: jest.fn(),
});
render(<ServicesSection />);
await waitFor(() => {
expect(screen.getByText('服务A')).toBeInTheDocument();
expect(screen.getByText('服务B')).toBeInTheDocument();
expect(screen.getByText('服务C')).toBeInTheDocument();
});
});
it('should display service descriptions', async () => {
const mockServices = [
{
id: '1',
title: '服务A',
description: '这是一个专业的软件开发服务',
icon: 'Code',
},
];
useServices.mockReturnValue({
services: mockServices,
loading: false,
error: null,
refetch: jest.fn(),
});
render(<ServicesSection />);
await waitFor(() => {
expect(screen.getByText('这是一个专业的软件开发服务')).toBeInTheDocument();
});
});
it('should display service icons', async () => {
const mockServices = [
{
id: '1',
title: '服务A',
description: '描述A',
icon: 'Code',
},
];
useServices.mockReturnValue({
services: mockServices,
loading: false,
error: null,
refetch: jest.fn(),
});
render(<ServicesSection />);
await waitFor(() => {
const icons = document.querySelectorAll('svg');
expect(icons.length).toBeGreaterThan(0);
});
});
});
describe('Service Filtering', () => {
it('should filter services by items config', async () => {
const mockServices = [
{
id: '1',
title: '服务A',
description: '描述A',
icon: 'Code',
},
{
id: '2',
title: '服务B',
description: '描述B',
icon: 'Cloud',
},
{
id: '3',
title: '服务C',
description: '描述C',
icon: 'BarChart3',
},
];
useServices.mockReturnValue({
services: mockServices,
loading: false,
error: null,
refetch: jest.fn(),
});
render(<ServicesSection config={{ items: ['1', '3'] }} />);
await waitFor(() => {
expect(screen.getByText('服务A')).toBeInTheDocument();
expect(screen.getByText('服务C')).toBeInTheDocument();
expect(screen.queryByText('服务B')).not.toBeInTheDocument();
});
});
it('should show all services when no items config is provided', async () => {
const mockServices = [
{
id: '1',
title: '服务A',
description: '描述A',
icon: 'Code',
},
{
id: '2',
title: '服务B',
description: '描述B',
icon: 'Cloud',
},
];
useServices.mockReturnValue({
services: mockServices,
loading: false,
error: null,
refetch: jest.fn(),
});
render(<ServicesSection />);
await waitFor(() => {
expect(screen.getByText('服务A')).toBeInTheDocument();
expect(screen.getByText('服务B')).toBeInTheDocument();
});
});
});
describe('Navigation', () => {
it('should link to service detail pages', async () => {
const mockServices = [
{
id: '1',
title: '服务A',
description: '描述A',
icon: 'Code',
},
];
useServices.mockReturnValue({
services: mockServices,
loading: false,
error: null,
refetch: jest.fn(),
});
render(<ServicesSection />);
await waitFor(() => {
const serviceLink = screen.getByRole('link', { name: /服务A/ });
expect(serviceLink).toHaveAttribute('href', '/services/1');
});
});
it('should link to all services page', async () => {
const mockServices = [
{
id: '1',
title: '服务A',
description: '描述A',
icon: 'Code',
},
];
useServices.mockReturnValue({
services: mockServices,
loading: false,
error: null,
refetch: jest.fn(),
});
render(<ServicesSection />);
await waitFor(() => {
const allServicesLink = screen.getByRole('link', { name: /查看全部服务/ });
expect(allServicesLink).toHaveAttribute('href', '/services');
});
});
});
describe('Accessibility', () => {
it('should maintain accessibility with dynamic data', async () => {
const mockServices = [
{
id: '1',
title: '服务A',
description: '描述A',
icon: 'Code',
},
];
useServices.mockReturnValue({
services: mockServices,
loading: false,
error: null,
refetch: jest.fn(),
});
render(<ServicesSection />);
await waitFor(() => {
const section = screen.getByRole('region');
expect(section).toBeInTheDocument();
expect(section).toHaveAttribute('aria-labelledby', 'services-heading');
});
});
});
});