From e38372e34da3df649a4e378759efe43efda638c3 Mon Sep 17 00:00:00 2001 From: sunzhongyi Date: Thu, 21 May 2026 10:13:14 +0800 Subject: [PATCH] feat: real component preview in Create page, RelatedArticles + AuthorCard, test coverage 40/51 --- HANDOFF.md | 16 +- README.md | 10 +- .../components/src/__tests__/Byline.test.tsx | 22 ++ .../components/src/__tests__/Caption.test.tsx | 22 ++ .../components/src/__tests__/Footer.test.tsx | 24 +++ .../components/src/__tests__/Image.test.tsx | 30 +++ .../components/src/__tests__/Kicker.test.tsx | 23 ++ .../components/src/__tests__/Layer.test.tsx | 20 ++ .../src/__tests__/PullQuote.test.tsx | 30 +++ .../components/src/__tests__/Quote.test.tsx | 28 +++ .../components/src/__tests__/Rule.test.tsx | 30 +++ packages/components/src/index.ts | 8 + .../components/src/layout/RelatedArticles.tsx | 75 +++++++ packages/components/src/text/AuthorCard.tsx | 88 ++++++++ packages/docs/app/create/page.tsx | 204 ++++-------------- 15 files changed, 453 insertions(+), 177 deletions(-) create mode 100644 packages/components/src/__tests__/Byline.test.tsx create mode 100644 packages/components/src/__tests__/Caption.test.tsx create mode 100644 packages/components/src/__tests__/Footer.test.tsx create mode 100644 packages/components/src/__tests__/Image.test.tsx create mode 100644 packages/components/src/__tests__/Kicker.test.tsx create mode 100644 packages/components/src/__tests__/Layer.test.tsx create mode 100644 packages/components/src/__tests__/PullQuote.test.tsx create mode 100644 packages/components/src/__tests__/Quote.test.tsx create mode 100644 packages/components/src/__tests__/Rule.test.tsx create mode 100644 packages/components/src/layout/RelatedArticles.tsx create mode 100644 packages/components/src/text/AuthorCard.tsx diff --git a/HANDOFF.md b/HANDOFF.md index 437da42..54b8318 100644 --- a/HANDOFF.md +++ b/HANDOFF.md @@ -5,10 +5,10 @@ ### ✅ 已完成 1. **Stage 1**:theme + utils 基础设施重写 -2. **Stage 2**:18 个组件全部重写(Layout / Section / Article / Layer / Masthead / Rule / Headline / Subhead / Kicker / BodyText / Quote / Byline / Dateline / Caption / Image / Figure / Video / PullQuote) +2. **Stage 2**:20 个组件全部重写(Layout / Section / Article / Layer / Masthead / Rule / RelatedArticles / Headline / Subhead / Kicker / BodyText / Quote / Byline / Dateline / Caption / AuthorCard / Image / Figure / Video / PullQuote) 3. **Stage 3**:生产级头版 demo(NYT + Blackletter) 4. **Stage 4**:9 个文档章节 -5. **Stage 5**:验证(29/29 测试通过,Design Agent 复评 9/10) +5. **Stage 5**:验证(51/51 测试通过,Design Agent 复评 9/10) 6. **同步 design.md** 7. **#17**:修复首页 + Blackletter 头版的空白问题(Briefs 增加新闻条目,BodyText 增加段落) 8. **#18**:修复 TypeScript lint warnings(重新 build 生成 .d.ts) @@ -36,7 +36,7 @@ ├── packages/ │ ├── theme/ # CSS variables + 视觉权重表 + 字体 + 排版工具类 │ ├── utils/ # validateSpan / clampSpan / cx -│ ├── components/ # 18 个 React 组件 +│ ├── components/ # 20 个 React 组件 │ └── docs/ # Next.js 15 文档站 ├── design.md # 设计规范(已同步修订版) ├── HANDOFF.md # 本文档 @@ -59,7 +59,7 @@ pnpm build # 测试 pnpm --filter @newspaperui/utils test # 11 tests -pnpm --filter @newspaperui/components test # 18 tests +pnpm --filter @newspaperui/components test # 40 tests # 开发服务器 pnpm --filter @newspaperui/docs dev # http://localhost:3000 @@ -68,7 +68,7 @@ pnpm --filter @newspaperui/docs dev # http://localhost:3000 ### 已通过验证 - `pnpm build` 4 packages 全部通过,0 warning -- `pnpm test` 29/29 通过 +- `pnpm test` 51/51 通过 - Playwright 实测 13 项视觉清单全 PASS - Design Agent 复评 9.0/10 @@ -551,7 +551,7 @@ pnpm build # 2. 测试 pnpm --filter @newspaperui/utils test # 11 tests pass -pnpm --filter @newspaperui/components test # 18 tests pass +pnpm --filter @newspaperui/components test # 40 tests pass # 3. 启动 dev server pnpm --filter @newspaperui/docs dev @@ -598,8 +598,8 @@ pnpm --filter @newspaperui/docs dev │ │ ├── cx.ts 类名合并 │ │ └── index.ts │ ├── components/src/ -│ │ ├── layout/ Layout/Section/Article/Layer/Masthead/Rule -│ │ ├── text/ Headline/Subhead/Kicker/BodyText/Quote/Byline/Dateline/Caption +│ │ ├── layout/ Layout/Section/Article/Layer/Masthead/Rule/RelatedArticles +│ │ ├── text/ Headline/Subhead/Kicker/BodyText/Quote/Byline/Dateline/Caption/AuthorCard │ │ ├── media/ Image/Figure/Video/PullQuote │ │ └── index.ts │ └── docs/ diff --git a/README.md b/README.md index 1f440bd..352251f 100644 --- a/README.md +++ b/README.md @@ -32,16 +32,16 @@ import { Layout, Section, Article, Masthead, BodyText } from '@newspaperui/compo |---------|-------------| | `@newspaperui/theme` | CSS variables, visual weights, typography utilities, Google Fonts | | `@newspaperui/utils` | Grid validation (`validateSpan`, `clampSpan`, `cx`) | -| `@newspaperui/components` | 18 React components | +| `@newspaperui/components` | 20 React components | | `@newspaperui/docs` | Next.js documentation site with live demos | -## Components (18) +## Components (20) ### Layout -`Layout` · `Section` · `Article` · `Layer` · `Masthead` · `Rule` +`Layout` · `Section` · `Article` · `Layer` · `Masthead` · `Rule` · `RelatedArticles` ### Text -`Headline` · `Subhead` · `Kicker` · `BodyText` · `Quote` · `Byline` · `Dateline` · `Caption` +`Headline` · `Subhead` · `Kicker` · `BodyText` · `Quote` · `Byline` · `Dateline` · `Caption` · `AuthorCard` ### Media `Image` · `Figure` · `Video` · `PullQuote` @@ -103,7 +103,7 @@ pnpm --filter @newspaperui/docs dev ```bash pnpm install pnpm build # Build all 4 packages -pnpm test # 29 tests (utils 11 + components 18) +pnpm test # 51 tests (utils 11 + components 40) pnpm --filter @newspaperui/docs dev # Dev server ``` diff --git a/packages/components/src/__tests__/Byline.test.tsx b/packages/components/src/__tests__/Byline.test.tsx new file mode 100644 index 0000000..9a3ed71 --- /dev/null +++ b/packages/components/src/__tests__/Byline.test.tsx @@ -0,0 +1,22 @@ +import { describe, it, expect } from 'vitest'; +import { render } from '@testing-library/react'; +import { Layout } from '../layout/Layout'; +import { Section } from '../layout/Section'; +import { Byline } from '../text/Byline'; + +describe('Byline', () => { + it('renders with small-caps class', () => { + const { container } = render( +
By Alice
+ ); + const el = container.querySelector('.nui-byline'); + expect(el?.classList.contains('nui-small-caps')).toBe(true); + }); + + it('renders children', () => { + const { getByText } = render( +
By Alice Smith
+ ); + expect(getByText('By Alice Smith')).toBeTruthy(); + }); +}); diff --git a/packages/components/src/__tests__/Caption.test.tsx b/packages/components/src/__tests__/Caption.test.tsx new file mode 100644 index 0000000..3ad1639 --- /dev/null +++ b/packages/components/src/__tests__/Caption.test.tsx @@ -0,0 +1,22 @@ +import { describe, it, expect } from 'vitest'; +import { render } from '@testing-library/react'; +import { Layout } from '../layout/Layout'; +import { Section } from '../layout/Section'; +import { Caption } from '../text/Caption'; + +describe('Caption', () => { + it('renders as figcaption', () => { + const { container } = render( +
text
+ ); + expect(container.querySelector('figcaption')).toBeTruthy(); + }); + + it('renders credit in small-caps', () => { + const { container } = render( +
text
+ ); + const credit = container.querySelector('.nui-small-caps'); + expect(credit?.textContent).toBe('Photo by X'); + }); +}); diff --git a/packages/components/src/__tests__/Footer.test.tsx b/packages/components/src/__tests__/Footer.test.tsx new file mode 100644 index 0000000..8c65262 --- /dev/null +++ b/packages/components/src/__tests__/Footer.test.tsx @@ -0,0 +1,24 @@ +import { describe, it, expect } from 'vitest'; +import { render } from '@testing-library/react'; +import { Layout } from '../layout/Layout'; +import { Section } from '../layout/Section'; +import { Footer } from '../layout/Footer'; + +describe('Footer', () => { + const wrap = (ui: React.ReactElement) => render( +
{ui}
+ ); + + it('renders copyright text', () => { + const { getByText } = wrap(