diff --git a/e2e/uj-11-home-conversion.spec.ts b/e2e/uj-11-home-conversion.spec.ts new file mode 100644 index 0000000..e626827 --- /dev/null +++ b/e2e/uj-11-home-conversion.spec.ts @@ -0,0 +1,197 @@ +import { test, expect, type Page } from '@playwright/test'; + +/** + * UJ-11: 首页转化旅程(设计优化专项) + * + * 覆盖首页 Vibe Design 优化后的关键转化路径,作为封版验收依据: + * UJ-11a: 首屏说服链路 — Hero 产品视觉 + 单一 CTA + 数据条 → 信任层(可验证信号)→ 叙事区 → 转化 CTA + * UJ-11b: 信任验证旅程 — 数据来源标注 + 首批客户共创标签 → 联系转化 + * UJ-11c: 移动端首屏转化旅程 — 390px 下 CTA 首屏可见、无横向滚动 + * + * 关联设计优化计划:docs/plans/2026-08-18-vibe-design-optimization-plan.md + * 关联 critique:.impeccable/critique/ + */ + +test.setTimeout(90000); + +// ==================== 辅助函数 ==================== + +async function closeCookieBanner(page: Page) { + const acceptAllButton = page.locator('button:has-text("接受所有")').first(); + if ((await acceptAllButton.count()) > 0 && (await acceptAllButton.isVisible())) { + await acceptAllButton.click(); + await page.waitForTimeout(500); + } +} + +/** + * 断言页面无横向滚动(scrollWidth <= clientWidth + 1px 容差) + */ +async function expectNoHorizontalOverflow(page: Page) { + const overflow = await page.evaluate(() => { + const doc = document.documentElement; + return { scrollWidth: doc.scrollWidth, clientWidth: doc.clientWidth }; + }); + expect(overflow.scrollWidth).toBeLessThanOrEqual(overflow.clientWidth + 1); +} + +// ==================== UJ-11a: 首屏说服链路 ==================== +test.describe('UJ-11a: 首屏说服链路(Hero → 信任 → 叙事 → CTA)', () => { + test('@journey @critical 首页首屏产品视觉、单一 CTA、数据条渲染正常', async ({ page }) => { + await page.goto('/', { waitUntil: 'domcontentloaded', timeout: 30000 }); + await page.waitForTimeout(2500); + await closeCookieBanner(page); + + // === L1 Hero:产品视觉 Mockup 可见(设计优化核心交付) === + const productVisual = page.locator('[data-testid="hero-product-visual"]').first(); + await expect(productVisual).toBeVisible({ timeout: 15000 }); + + // 诚实标签「产品界面示意」「示例数据」存在(零编造原则) + const visualText = await productVisual.textContent(); + expect(visualText).toContain('产品界面示意'); + expect(visualText).toContain('示例数据'); + + // 产品视觉含可识别产品模块命名 + expect(visualText).toContain('经营驾驶舱'); + + // === 单一主 CTA === + const primaryCta = page.locator('[data-testid="hero-primary-cta"]').first(); + await expect(primaryCta).toBeVisible(); + await expect(primaryCta).toHaveAttribute('href', '/contact'); + + // 次级 CTA 降级为文字链接 + const secondaryLink = page.locator('[data-testid="hero-secondary-link"]').first(); + await expect(secondaryLink).toBeVisible(); + + // === 主标题可见 === + const heroTitle = page.locator('h1').first(); + await expect(heroTitle).toBeVisible(); + + // 无横向滚动 + await expectNoHorizontalOverflow(page); + }); + + test('@journey @critical 首页信任层展示可验证信号与来源标注', async ({ page }) => { + await page.goto('/', { waitUntil: 'domcontentloaded', timeout: 30000 }); + await page.waitForTimeout(2500); + await closeCookieBanner(page); + + // 滚动到信任层 + const trustSection = page.locator('[data-testid="trust-section"]').first(); + await trustSection.scrollIntoViewIfNeeded(); + await expect(trustSection).toBeVisible({ timeout: 10000 }); + + const trustText = await trustSection.textContent(); + // 可验证信任信号存在(私有化部署 / 本地化 / 全流程 / 共创) + expect(trustText).toContain('100%'); + expect(trustText).toContain('成都'); + expect(trustText).toContain('全流程'); + expect(trustText).toContain('共创'); + // 数据来源标注存在(零编造,可追溯) + expect(trustText).toContain('数据来源'); + }); + + test('@journey @critical 首页叙事区按 01/02/03 章节呈现问题→方法→结果', async ({ page }) => { + await page.goto('/', { waitUntil: 'domcontentloaded', timeout: 30000 }); + await page.waitForTimeout(2500); + await closeCookieBanner(page); + + const narrativeSection = page.locator('[data-testid="narrative-section"]').first(); + await narrativeSection.scrollIntoViewIfNeeded(); + await expect(narrativeSection).toBeVisible({ timeout: 10000 }); + + const narrativeText = await narrativeSection.textContent(); + // 三幕章节编号存在 + expect(narrativeText).toContain('01'); + expect(narrativeText).toContain('02'); + expect(narrativeText).toContain('03'); + // 叙事主题存在 + expect(narrativeText).toContain('诊断现状'); + expect(narrativeText).toContain('设计路径'); + expect(narrativeText).toContain('交付成果'); + // 每章保留详情入口 + const narrativeLinks = narrativeSection.locator('a'); + expect(await narrativeLinks.count()).toBeGreaterThanOrEqual(3); + }); +}); + +// ==================== UJ-11b: 信任验证旅程 ==================== +test.describe('UJ-11b: 信任验证旅程(共创标签 → 转化)', () => { + test('@journey @critical 首页首批客户共创标签引导至联系转化', async ({ page }) => { + await page.goto('/', { waitUntil: 'domcontentloaded', timeout: 30000 }); + await page.waitForTimeout(2500); + await closeCookieBanner(page); + + // 首批客户共创横幅存在(无虚构客户,如实标注) + const earlyAccessBanner = page.locator('[data-testid="early-access-banner"]').first(); + await earlyAccessBanner.scrollIntoViewIfNeeded(); + await expect(earlyAccessBanner).toBeVisible({ timeout: 10000 }); + + const bannerText = await earlyAccessBanner.textContent(); + expect(bannerText).toContain('首批客户共创中'); + + // 引导至联系转化 + const cta = earlyAccessBanner.locator('a[href="/contact"]').first(); + await expect(cta).toBeVisible(); + await expect(cta).toHaveAttribute('href', '/contact'); + }); + + test('@journey @critical 空案例区呈现共创内容块而非裸空态', async ({ page }) => { + await page.goto('/', { waitUntil: 'domcontentloaded', timeout: 30000 }); + await page.waitForTimeout(2500); + await closeCookieBanner(page); + + const bodyText = await page.locator('body').textContent(); + // 无「暂无案例数据」裸空态 + expect(bodyText).not.toContain('暂无案例数据'); + // 出现「共创进行时」前瞻内容块 + expect(bodyText).toContain('共创进行时'); + // 共创块包含转化 CTA + expect(bodyText).toContain('成为首批共创客户'); + }); +}); + +// ==================== UJ-11c: 移动端首屏转化旅程 ==================== +test.describe('UJ-11c: 移动端首屏转化旅程', () => { + test('@mobile @journey @critical 移动端 CTA 首屏可见且无横向滚动', async ({ page }) => { + // 模拟移动端视口 + await page.setViewportSize({ width: 390, height: 844 }); + await page.goto('/', { waitUntil: 'domcontentloaded', timeout: 30000 }); + await page.waitForTimeout(2500); + await closeCookieBanner(page); + + // 无横向滚动 + await expectNoHorizontalOverflow(page); + + // CTA 首屏可达(在当前视口内可见) + const primaryCta = page.locator('[data-testid="hero-primary-cta"]').first(); + await expect(primaryCta).toBeVisible({ timeout: 15000 }); + + // 产品视觉渲染正常 + const productVisual = page.locator('[data-testid="hero-product-visual"]').first(); + await expect(productVisual).toBeVisible(); + }); + + test('@mobile @journey @critical 移动端信任层与叙事区单列堆叠无溢出', async ({ page }) => { + await page.setViewportSize({ width: 390, height: 844 }); + await page.goto('/', { waitUntil: 'domcontentloaded', timeout: 30000 }); + await page.waitForTimeout(2500); + await closeCookieBanner(page); + + // 信任层 + const trustSection = page.locator('[data-testid="trust-section"]').first(); + await trustSection.scrollIntoViewIfNeeded(); + await expect(trustSection).toBeVisible(); + const trustText = await trustSection.textContent(); + expect(trustText).toContain('数据来源'); + + // 叙事区 + const narrativeSection = page.locator('[data-testid="narrative-section"]').first(); + await narrativeSection.scrollIntoViewIfNeeded(); + await expect(narrativeSection).toBeVisible(); + expect(await narrativeSection.textContent()).toContain('01'); + + // 全程无横向滚动 + await expectNoHorizontalOverflow(page); + }); +}); diff --git a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/about-fullpage-visual-chromium-desktop.png b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/about-fullpage-visual-chromium-desktop.png index d24c35a..c06da12 100644 Binary files a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/about-fullpage-visual-chromium-desktop.png and b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/about-fullpage-visual-chromium-desktop.png differ diff --git a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/contact-fullpage-visual-chromium-desktop.png b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/contact-fullpage-visual-chromium-desktop.png index 85bcbd0..288070f 100644 Binary files a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/contact-fullpage-visual-chromium-desktop.png and b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/contact-fullpage-visual-chromium-desktop.png differ diff --git a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/footer-section-visual-chromium-desktop.png b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/footer-section-visual-chromium-desktop.png index 72227ca..127176c 100644 Binary files a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/footer-section-visual-chromium-desktop.png and b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/footer-section-visual-chromium-desktop.png differ diff --git a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/home-fullpage-visual-chromium-desktop.png b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/home-fullpage-visual-chromium-desktop.png index 27fb130..cf4fdc4 100644 Binary files a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/home-fullpage-visual-chromium-desktop.png and b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/home-fullpage-visual-chromium-desktop.png differ diff --git a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/news-detail-fullpage-visual-chromium-desktop.png b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/news-detail-fullpage-visual-chromium-desktop.png index 68af482..9ad2662 100644 Binary files a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/news-detail-fullpage-visual-chromium-desktop.png and b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/news-detail-fullpage-visual-chromium-desktop.png differ diff --git a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/news-fullpage-visual-chromium-desktop.png b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/news-fullpage-visual-chromium-desktop.png index 615ef8b..4015f86 100644 Binary files a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/news-fullpage-visual-chromium-desktop.png and b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/news-fullpage-visual-chromium-desktop.png differ diff --git a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/product-erp-fullpage-visual-chromium-desktop.png b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/product-erp-fullpage-visual-chromium-desktop.png index 9a69c5d..330cf17 100644 Binary files a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/product-erp-fullpage-visual-chromium-desktop.png and b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/product-erp-fullpage-visual-chromium-desktop.png differ diff --git a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/products-fullpage-visual-chromium-desktop.png b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/products-fullpage-visual-chromium-desktop.png index b6eadba..8ffcaef 100644 Binary files a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/products-fullpage-visual-chromium-desktop.png and b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/products-fullpage-visual-chromium-desktop.png differ diff --git a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/service-software-fullpage-visual-chromium-desktop.png b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/service-software-fullpage-visual-chromium-desktop.png index 3cffe40..aad5ef7 100644 Binary files a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/service-software-fullpage-visual-chromium-desktop.png and b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/service-software-fullpage-visual-chromium-desktop.png differ diff --git a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/services-fullpage-visual-chromium-desktop.png b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/services-fullpage-visual-chromium-desktop.png index ca31daf..214310a 100644 Binary files a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/services-fullpage-visual-chromium-desktop.png and b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/services-fullpage-visual-chromium-desktop.png differ diff --git a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/solution-manufacturing-fullpage-visual-chromium-desktop.png b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/solution-manufacturing-fullpage-visual-chromium-desktop.png index 30d1d99..b49ac4d 100644 Binary files a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/solution-manufacturing-fullpage-visual-chromium-desktop.png and b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/solution-manufacturing-fullpage-visual-chromium-desktop.png differ diff --git a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/solutions-fullpage-visual-chromium-desktop.png b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/solutions-fullpage-visual-chromium-desktop.png index 27c8257..e39a010 100644 Binary files a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/solutions-fullpage-visual-chromium-desktop.png and b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/solutions-fullpage-visual-chromium-desktop.png differ diff --git a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/team-fullpage-visual-chromium-desktop.png b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/team-fullpage-visual-chromium-desktop.png index e89141a..d34fa01 100644 Binary files a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/team-fullpage-visual-chromium-desktop.png and b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/team-fullpage-visual-chromium-desktop.png differ diff --git a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/theme-dark-main-visual-chromium-desktop.png b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/theme-dark-main-visual-chromium-desktop.png index 27fb130..cf4fdc4 100644 Binary files a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/theme-dark-main-visual-chromium-desktop.png and b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/theme-dark-main-visual-chromium-desktop.png differ diff --git a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/theme-light-main-visual-chromium-desktop.png b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/theme-light-main-visual-chromium-desktop.png index 27fb130..cf4fdc4 100644 Binary files a/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/theme-light-main-visual-chromium-desktop.png and b/e2e/visual-snapshots/visual-chromium-desktop/visual-regression.spec.ts/theme-light-main-visual-chromium-desktop.png differ diff --git a/src/app/(marketing)/about/about-content-v4.tsx b/src/app/(marketing)/about/about-content-v4.tsx index d0eaf46..b9caff8 100644 --- a/src/app/(marketing)/about/about-content-v4.tsx +++ b/src/app/(marketing)/about/about-content-v4.tsx @@ -173,8 +173,14 @@ function WhoWeAreSection({ data }: { data: AboutData }) { transition={{ duration: 0.8, ease: EASE_OUT }} className="lg:col-span-5" > -
{children}
+ ), + span: ({ children, className, ...props }: any) => ( + {children} + ), + a: ({ children, href, className, ...props }: any) => ( + {children} + ), + }, + useInView: jest.fn(() => true), + AnimatePresence: ({ children }: any) => <>{children}>, +})); + +jest.mock('next/image', () => ({ + __esModule: true, + default: ({ src, alt, className }: any) => ( + // eslint-disable-next-line @next/next/no-img-element +,
+ },
{
subtitle: 'Data Intelligence',
title: '数据智能与 AI 应用',
@@ -53,21 +66,23 @@ const FALLBACK_SERVICES = [
{ value: '6', label: '行业场景覆盖' },
{ value: '99.9%', label: '系统可用性' },
],
- href: '/services/solution',
+ href: '/services/solutions',
icon: {item.desc}
++ {EARLY_ACCESS.desc} +
++ {act.desc} +
+ -{item.desc}
暂无案例数据
+
+ 我们正与首批客户共同打磨产品与方案,以真实运营数据验证业务改善。
+
+ 公开案例将在验证后发布——合作成果,经得起衡量。
+
{EARLY_ACCESS.desc}
++
{product.scenario || product.description}
{children}
+ ), + span: ({ children, className, ...props }: any) => ( + {children} + ), + a: ({ children, href, className, ...props }: any) => ( + {children} + ), + }, + useInView: jest.fn(() => true), + AnimatePresence: ({ children }: any) => <>{children}>, +})); + +jest.mock('@/components/ui/static-link', () => ({ + StaticLink: ({ children, href, className, ...props }: any) => ( + {children} + ), +})); + +jest.mock('lucide-react', () => { + const mockIcon = (name: string) => { + const Icon = (props: any) => ; + Icon.displayName = name; + return Icon; + }; + return { + ArrowUpRight: mockIcon('arrow-up-right'), + CheckCircle2: mockIcon('check-circle2'), + }; +}); + +const mockServices: Service[] = [ + { + id: 'consulting', + title: '数字化转型战略咨询', + description: '从业务诊断到数字化路线图', + icon: 'Lightbulb', + overview: '战略咨询概述', + features: ['业务诊断'], + benefits: ['ROI 评估'], + process: ['诊断'], + heroThemeId: 'consulting', + caseStudies: [], + dataProofs: [], + capabilities: ['业务诊断', '数字化蓝图'], + metrics: [{ value: '40%', label: '运营效率提升' }], + }, + { + id: 'data', + title: '数据智能与 AI 应用', + description: '构建企业级数据平台', + icon: 'Database', + overview: '数据智能概述', + features: ['数据中台'], + benefits: ['数据驱动'], + process: ['建模'], + heroThemeId: 'data', + caseStudies: [], + dataProofs: [], + capabilities: ['数据中台', 'AI 建模'], + metrics: [{ value: '98%', label: '数据质量达标率' }], + }, +]; + +describe('ServicesContentV3 - 非对称服务卡片', () => { + it('makes the first service a featured full-width card', () => { + render({children}
+ ), + span: ({ children, className, ...props }: any) => ( + {children} + ), + a: ({ children, href, className, ...props }: any) => ( + {children} + ), + }, + useInView: jest.fn(() => true), + AnimatePresence: ({ children }: any) => <>{children}>, +})); + +jest.mock('@/components/ui/scroll-reveal', () => ({ + ScrollReveal: ({ children, className }: any) => ( ++ {study.challenge} +
+{children}
+ ), + span: ({ children, className, ...props }: any) => ( + {children} + ), + a: ({ children, href, className, ...props }: any) => ( + {children} + ), + }, + useInView: jest.fn(() => true), + AnimatePresence: ({ children }: any) => <>{children}>, +})); + +jest.mock('@/components/ui/static-link', () => ({ + StaticLink: ({ children, href, className, ...props }: any) => ( + {children} + ), +})); + +jest.mock('lucide-react', () => { + const mockIcon = (name: string) => { + const Icon = (props: any) => ; + Icon.displayName = name; + return Icon; + }; + return { + ArrowUpRight: mockIcon('arrow-up-right'), + Factory: mockIcon('factory'), + ShoppingCart: mockIcon('shopping-cart'), + Heart: mockIcon('heart'), + GraduationCap: mockIcon('graduation-cap'), + Shield: mockIcon('shield'), + Truck: mockIcon('truck'), + }; +}); + +const mockSolutions: Solution[] = [ + { + id: 'manufacturing', + industry: '制造业', + title: '智能制造数字化转型方案', + subtitle: '端到端制造数字化', + description: '面向制造企业的整体转型方案', + challenges: ['数据孤岛', '库存积压'], + solutions: ['ERP 集成', 'BI 分析'], + relatedProducts: ['erp', 'bi'], + valueProposition: { + headline: '价值主张', + points: [{ icon: 'Factory', title: '降本增效', description: '描述' }], + }, + suiteCombination: { + primaryProducts: ['erp'], + complementaryServices: ['consulting'], + rationale: '理由', + }, + painPoints: ['数据孤岛'], + outcomes: [{ value: '30%', label: '效率提升' }], + recommendedProducts: ['erp', 'bi'], + }, + { + id: 'retail', + industry: '贸易零售', + title: '零售数字化解决方案', + subtitle: '全渠道零售数字化', + description: '面向零售企业的数字化方案', + challenges: ['渠道割裂'], + solutions: ['CRM 统一'], + relatedProducts: ['crm', 'bi'], + valueProposition: { + headline: '价值主张', + points: [{ icon: 'ShoppingCart', title: '提升转化', description: '描述' }], + }, + suiteCombination: { + primaryProducts: ['crm'], + complementaryServices: ['consulting'], + rationale: '理由', + }, + painPoints: ['渠道割裂'], + outcomes: [{ value: '3x', label: '转化率提升' }], + recommendedProducts: ['crm', 'bi'], + }, +]; + +const mockProducts: Product[] = [ + { + id: 'erp', + title: '睿新ERP管理系统', + description: 'ERP', + image: '/erp.png', + category: '企业旗舰系列', + categoryId: 'enterprise', + status: '已发布', + overview: '概述', + features: [], + benefits: [], + process: [], + specs: [], + tags: [], + heroThemeId: 'erp', + caseStudies: [], + dataProofs: [], + certifications: [], + bundle: 'enterprise', + }, +]; + +describe('SolutionsContentV3 - 非对称方案卡片', () => { + it('makes the first solution a featured full-width card', () => { + render(