- Replace fabricated 12-year/500+/8+ team experience claims with 2026 founding, first-client co-creation, professional team wording - Remove fake case studies and unverified certifications from seeds, cases page, products and ERP upgrade page - Enable Next.js standalone output and production hybrid deployment (Dockerfile.prod, docker-compose.server.yml, Nginx nextjs upstream) - Add linux-musl Prisma engine target and production crypto key build - Sync production CMS database with cleaned seed content
211 lines
6.5 KiB
TypeScript
211 lines
6.5 KiB
TypeScript
import { describe, it, expect, jest } from '@jest/globals';
|
|
import { render, screen } from '@testing-library/react';
|
|
import '@testing-library/jest-dom';
|
|
|
|
type MotionProps = { children: React.ReactNode; className?: string; [key: string]: unknown };
|
|
|
|
jest.mock('framer-motion', () => ({
|
|
motion: {
|
|
div: ({ children, className, ...props }: MotionProps) => (
|
|
<div className={className} {...props}>
|
|
{children}
|
|
</div>
|
|
),
|
|
section: ({ children, className, ...props }: MotionProps) => (
|
|
<section className={className} {...props}>
|
|
{children}
|
|
</section>
|
|
),
|
|
span: ({ children, className, ...props }: MotionProps) => (
|
|
<span className={className} {...props}>
|
|
{children}
|
|
</span>
|
|
),
|
|
h1: ({ children, className, ...props }: MotionProps) => (
|
|
<h1 className={className} {...props}>
|
|
{children}
|
|
</h1>
|
|
),
|
|
h2: ({ children, className, ...props }: MotionProps) => (
|
|
<h2 className={className} {...props}>
|
|
{children}
|
|
</h2>
|
|
),
|
|
},
|
|
AnimatePresence: ({ children }: { children: React.ReactNode }) => <>{children}</>,
|
|
useInView: () => [null, true],
|
|
}));
|
|
|
|
jest.mock('next/link', () => {
|
|
const MockLink = ({ children, href, ...props }: { children: React.ReactNode; href: string; [key: string]: unknown }) => (
|
|
<a href={href} {...props}>
|
|
{children}
|
|
</a>
|
|
);
|
|
MockLink.displayName = 'MockLink';
|
|
return MockLink;
|
|
});
|
|
|
|
jest.mock('lucide-react', () => ({
|
|
Lightbulb: () => <span data-testid="lightbulb-icon" />,
|
|
Users: () => <span data-testid="users-icon" />,
|
|
Target: () => <span data-testid="target-icon" />,
|
|
Award: () => <span data-testid="award-icon" />,
|
|
MapPin: () => <span data-testid="map-pin-icon" />,
|
|
Mail: () => <span data-testid="mail-icon" />,
|
|
Phone: () => <span data-testid="phone-icon" />,
|
|
Trophy: () => <span data-testid="trophy-icon" />,
|
|
Shield: () => <span data-testid="shield-icon" />,
|
|
Zap: () => <span data-testid="zap-icon" />,
|
|
ArrowUpRight: () => <span data-testid="arrow-up-right-icon" />,
|
|
}));
|
|
|
|
jest.mock('@/components/ui/card', () => {
|
|
const Card = ({ children, className, ...props }: { children: React.ReactNode; className?: string; [key: string]: unknown }) => (
|
|
<div className={className} {...props}>
|
|
{children}
|
|
</div>
|
|
);
|
|
const CardContent = ({ children, className, ...props }: { children: React.ReactNode; className?: string; [key: string]: unknown }) => (
|
|
<div className={className} {...props}>
|
|
{children}
|
|
</div>
|
|
);
|
|
Card.displayName = 'Card';
|
|
CardContent.displayName = 'CardContent';
|
|
return { Card, CardContent };
|
|
});
|
|
|
|
jest.mock('@/components/ui/flip-clock', () => {
|
|
const FlipClock = ({ years, months, days }: { years: number; months: number; days: number }) => (
|
|
<div data-testid="flip-clock">
|
|
{years}年 {months}月 {days}天
|
|
</div>
|
|
);
|
|
FlipClock.displayName = 'FlipClock';
|
|
return { FlipClock };
|
|
});
|
|
|
|
jest.mock('@/components/layout/page-nav', () => ({
|
|
PageNav: ({ items }: { items: Array<{ label: string }> }) => (
|
|
<nav data-testid="page-nav">
|
|
{items.map((item, i) => <span key={i}>{item.label}</span>)}
|
|
</nav>
|
|
),
|
|
}));
|
|
|
|
jest.mock('date-fns', () => ({
|
|
differenceInYears: () => 0,
|
|
differenceInMonths: () => 0,
|
|
differenceInDays: () => 0,
|
|
subYears: (d: Date) => d,
|
|
subMonths: (d: Date) => d,
|
|
}));
|
|
|
|
jest.mock('./about-content-v4', () => {
|
|
const MockAboutContentV4 = () => (
|
|
<div className="min-h-screen" data-testid="about-content">
|
|
<h1>关于我们</h1>
|
|
<section>
|
|
<h2>发展历程</h2>
|
|
<h2>核心价值观</h2>
|
|
<h2>团队组建</h2>
|
|
<h2>联系我们</h2>
|
|
<span>研发产品</span>
|
|
</section>
|
|
</div>
|
|
);
|
|
MockAboutContentV4.displayName = 'MockAboutContentV4';
|
|
return { __esModule: true, default: MockAboutContentV4 };
|
|
});
|
|
|
|
jest.mock('@/lib/constants', () => ({
|
|
COMPANY_INFO: {
|
|
name: '四川睿新致远科技有限公司',
|
|
shortName: '睿新致遠',
|
|
displayName: '睿新致远',
|
|
description: '以智慧连接数字趋势,以伙伴身份陪您成长',
|
|
address: '四川省成都市龙泉驿区',
|
|
email: 'contact@novalon.cn',
|
|
phone: '028-88888888',
|
|
},
|
|
STATS: [
|
|
{ value: '6', label: '研发产品' },
|
|
{ value: '5+', label: '行业覆盖' },
|
|
{ value: '10+', label: '团队成员' },
|
|
{ value: '2026', label: '年成立' },
|
|
],
|
|
}));
|
|
|
|
jest.mock('@/lib/cms/data-server', () => ({
|
|
getPublishedItems: jest.fn(() => Promise.resolve([{ data: {} }])),
|
|
}));
|
|
|
|
import AboutPage from './page';
|
|
|
|
describe('AboutPage', () => {
|
|
beforeEach(() => {
|
|
jest.clearAllMocks();
|
|
});
|
|
|
|
describe('Rendering', () => {
|
|
it('should render about page', async () => {
|
|
const pageElement = await AboutPage();
|
|
const { container } = render(pageElement);
|
|
const pageContainer = container.querySelector('.min-h-screen');
|
|
expect(pageContainer).toBeInTheDocument();
|
|
});
|
|
|
|
it('should render company introduction', async () => {
|
|
const pageElement = await AboutPage();
|
|
render(pageElement);
|
|
const intros = screen.getAllByText(/关于我们/i);
|
|
expect(intros.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
it('should render company history', async () => {
|
|
const pageElement = await AboutPage();
|
|
render(pageElement);
|
|
const history = screen.getByText(/发展历程/i);
|
|
expect(history).toBeInTheDocument();
|
|
});
|
|
|
|
it('should render company culture', async () => {
|
|
const pageElement = await AboutPage();
|
|
render(pageElement);
|
|
const culture = screen.getByText(/核心价值观/i);
|
|
expect(culture).toBeInTheDocument();
|
|
});
|
|
|
|
it('should render team members', async () => {
|
|
const pageElement = await AboutPage();
|
|
render(pageElement);
|
|
const team = screen.getByText(/团队组建/i);
|
|
expect(team).toBeInTheDocument();
|
|
});
|
|
|
|
it('should render contact information', async () => {
|
|
const pageElement = await AboutPage();
|
|
render(pageElement);
|
|
const contact = screen.getByText(/联系我们/i);
|
|
expect(contact).toBeInTheDocument();
|
|
});
|
|
|
|
it('should render statistics', async () => {
|
|
const pageElement = await AboutPage();
|
|
render(pageElement);
|
|
const stats = screen.getByText(/研发产品/i);
|
|
expect(stats).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
describe('Accessibility', () => {
|
|
it('should have proper heading hierarchy', async () => {
|
|
const pageElement = await AboutPage();
|
|
render(pageElement);
|
|
const h1 = screen.getByRole('heading', { level: 1 });
|
|
expect(h1).toBeInTheDocument();
|
|
});
|
|
});
|
|
});
|