返回 slidev
022-export-pipeline-tests.md
根目录 / plans / 022-export-pipeline-tests.md
1 # Plan 022: Test the export pipeline (characterization tests for the flagship path)
2
3 > **Executor instructions**: Follow this plan step by step. Run every
4 > verification command and confirm the expected result. If anything in "STOP
5 > conditions" occurs, stop and report. When done, update the status row in
6 > `plans/README.md`.
7 >
8 > **Drift check (run first)**: `git diff --stat c63cb120..HEAD -- packages/slidev/node/commands/export.ts`
9 > On a mismatch with the excerpts below, treat it as a STOP condition.
10
11 ## Status
12
13 - **Priority**: P1
14 - **Effort**: M
15 - **Risk**: LOW
16 - **Depends on**: none (unblocks 023; overlaps 009/016/021's helper tests)
17 - **Category**: tests
18 - **Planned at**: commit `c63cb120`, 2026-07-10
19
20 ## Why this matters
21
22 `slidev export` (PDF/PNG/PPTX) is a flagship feature (README) implemented in a
23 658-line file with **zero** tests. Regressions in page-range selection, TOC
24 outline building, or filename handling ship undetected; CI only runs `slidev
25 build` in smoke, never export. Characterization tests over the *pure* helpers
26 give a fast safety net now (no Playwright needed) and are the prerequisite for
27 safely decomposing the module (plan 023).
28
29 ## Current state
30
31 `packages/slidev/node/commands/export.ts` pure/near-pure helpers worth pinning:
32 - `getExportOptions(args, options, outFilename?)` (`:574-624`) — merges CLI args +
33 deck config into an `ExportOptions`; exported already.
34 - `addToTree` (`:51-67`) + `makeOutline` (`:69-77`) — TOC → PDF outline string
35 (module-internal; **not** currently exported). NB: plan 021 may move `addToTree`
36 into `@slidev/parser` as `buildTocTree` — if 021 has landed, test the shared
37 builder instead and only test `makeOutline` here.
38 - `parseRangeString` (from `@slidev/parser`) drives page selection at `:189` — its
39 own tests are plan 009; here, assert `getExportOptions`/range interplay.
40 - The `gen*` render functions need Playwright + a running preview → out of scope
41 for unit tests; covered by the optional smoke in Step 3.
42
43 Test patterns available: colocated `*.test.ts` with Vitest (see
44 `packages/slidev/node/syntax/*.test.ts`) using `describe/it/expect` and
45 `toMatchInlineSnapshot`.
46
47 ## Commands you will need
48
49 | Purpose | Command | Expected |
50 |---------|---------|----------|
51 | Install | `pnpm install` | exit 0 |
52 | Build | `pnpm build` | exit 0 |
53 | Test | `pnpm test -- export` | new tests pass |
54 | Typecheck | `pnpm typecheck` | exit 0 |
55
56 ## Scope
57
58 **In scope**:
59 - `packages/slidev/node/commands/export.ts` — export `addToTree`/`makeOutline`
60 (or import the shared builder from 021) so they're testable; no behavior change
61 - `packages/slidev/node/commands/export.test.ts` (create) — unit tests
62
63 **Out of scope**:
64 - Refactoring the `gen*` closures (plan 023).
65 - Browser teardown / filename confinement (plans 007/016 — their helpers may add
66 their own tests; don't duplicate).
67 - Setting up a Playwright CI job (the optional smoke in Step 3 is local-only unless
68 the operator wants it wired into CI).
69
70 ## Git workflow
71
72 - Branch: `test/export-pipeline`.
73 - Conventional commit: `test(export): characterize export helpers`.
74 - Do NOT push/PR unless instructed.
75
76 ## Steps
77
78 ### Step 1: Make the pure helpers importable
79
80 If `addToTree`/`makeOutline` are still local to `export.ts`, add `export` to them
81 (or, if plan 021 landed, import `buildTocTree` from `@slidev/parser`). Do not
82 change their logic.
83
84 ### Step 2: Write characterization tests
85
86 Create `packages/slidev/node/commands/export.test.ts` covering:
87 - **`getExportOptions`**: given representative `args` + a fake `ResolvedSlidevOptions`
88 (minimal `data.config` + `data.slides`), assert the resolved `format`, `output`
89 (default `${basename(entry,'.md')}-export`), `width`/`height` from
90 `canvasWidth`/`aspectRatio`, `withClicks` default for `pptx`, `range`, and
91 `scale` defaults. Snapshot the returned object.
92 - **`makeOutline`** (and `addToTree`/`buildTocTree`): build a small tree from a
93 handful of titled slides at mixed levels and snapshot the outline string
94 (`path|--|title` lines), including a nested case.
95 - **range interplay**: assert `parseRangeString(total, range)` (imported from
96 `@slidev/parser`) selects the expected pages for a couple of inputs the exporter
97 relies on (e.g. `'2-3'`, `undefined`).
98
99 Keep fixtures inline/synthetic — no real rendering, no fs writes.
100
101 **Verify**: `pnpm build && pnpm test -- export` → all new tests pass.
102
103 ### Step 3 (optional, local-only): a Playwright smoke
104
105 Only if the operator wants render coverage and `playwright-chromium` is available:
106 add a slow/opt-in test (or a `cypress`/script harness) that builds the demo,
107 serves it, runs `exportSlides` for a 2-slide deck to each format, and asserts the
108 output file exists with a plausible page count/size. Gate it so it does not run
109 in the default `pnpm test` (e.g. behind an env flag) unless CI is set up for
110 Playwright. **STOP and ask** before adding a browser dependency to the default CI.
111
112 ## Test plan
113
114 - New `export.test.ts` pins `getExportOptions`, outline building, and range
115 selection — the regressions most likely to slip through today.
116 - Optional Playwright smoke (Step 3) is the only true end-to-end; keep it opt-in.
117
118 ## Done criteria
119
120 - [ ] `packages/slidev/node/commands/export.test.ts` exists and passes
121 - [ ] `getExportOptions`, outline building, and range selection are covered
122 - [ ] No behavior change to `export.ts` beyond adding `export` keywords
123 - [ ] Default `pnpm test` does not require Playwright/a browser
124 - [ ] `pnpm build && pnpm typecheck` exit 0
125 - [ ] Only in-scope files modified (`git status`)
126 - [ ] `plans/README.md` status row updated
127
128 ## STOP conditions
129
130 Stop and report if:
131
132 - Making a helper importable would require broad refactoring (it shouldn't — just
133 an `export` keyword) — that means the code has drifted; report.
134 - The operator has not approved adding Playwright to CI (keep Step 3 local/opt-in).
135
136 ## Maintenance notes
137
138 - These are characterization tests: if they fail after an intentional change,
139 update the snapshot deliberately, not reflexively.
140 - This suite is the safety net plan 023 relies on before decomposing `exportSlides`.
141 - Reviewer: confirm the fake `ResolvedSlidevOptions` in tests stays minimal and
142 doesn't couple tests to unrelated config.
143
143 lines MARKDOWN