Skip to content

Commit f34733e

Browse files
committed
Add manual preview tests for single-file root URL accessibility
T17: Verify GET / returns 200 for single-file preview T18: Verify GET /filename.html also works T19: Verify project preview paths still work with isSingleFile guard
1 parent 27218b2 commit f34733e

File tree

1 file changed

+196
-0
lines changed

1 file changed

+196
-0
lines changed
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
# Manual Preview Tests
2+
3+
Tests for `quarto preview` behavior that require an interactive session with file-save events. These cannot run in automated smoke tests.
4+
5+
## Automation
6+
7+
Use the `/quarto-preview-test` command for the general workflow of starting preview, verifying with browser automation, and checking logs/filesystem. It documents the tools and patterns.
8+
9+
For browser interaction, `/agent-browser` is preferred over Chrome DevTools MCP (more token-efficient). See the command for details.
10+
11+
## Test Matrix: quarto_ipynb Accumulation (#14281)
12+
13+
After every test involving Jupyter execution (Python/Julia cells), verify:
14+
1. `ls *.quarto_ipynb*` — at most one `{name}.quarto_ipynb` (no `_1`, `_2` variants)
15+
2. After Ctrl+C exit — no `.quarto_ipynb` files remain (unless `keep-ipynb: true`)
16+
17+
For tests without Jupyter execution (T9, T10, T11), verify no `.quarto_ipynb` files are created at all.
18+
19+
### P1: Critical
20+
21+
#### T1: Single .qmd with Python — re-render accumulation
22+
23+
- **Setup:** `test.qmd` with Python code cell
24+
- **Steps:** `quarto preview test.qmd`, save 5 times, check files, Ctrl+C
25+
- **Expected:** At most one `.quarto_ipynb` at any time. Zero after exit.
26+
- **Catches:** `invalidateForFile()` not deleting transient file before cache eviction
27+
28+
#### T2: Single .qmd with Python — startup duplicate
29+
30+
- **Setup:** Same `test.qmd`
31+
- **Steps:** `quarto preview test.qmd`, check files immediately after first render (before any saves), Ctrl+C
32+
- **Expected:** Exactly one `.quarto_ipynb` during render. Zero after exit.
33+
- **Catches:** `cmd.ts` not passing ProjectContext to `preview()`
34+
35+
#### T3: .qmd in project — project-level preview
36+
37+
- **Setup:** Website project (`_quarto.yml` with `type: website`), `index.qmd` with Python cell
38+
- **Steps:** `quarto preview` (project dir), save `index.qmd` 3 times, check files, Ctrl+C
39+
- **Expected:** At most one `index.quarto_ipynb`. Zero after exit.
40+
- **Catches:** Fix works when `projectContext()` finds a real project
41+
42+
#### T4: .qmd in project — single file preview
43+
44+
- **Setup:** Same project as T3
45+
- **Steps:** `quarto preview index.qmd`, save 3 times, check files, Ctrl+C
46+
- **Expected:** Same as T3. May redirect to project preview (expected behavior).
47+
- **Catches:** Context passing works for files inside serveable projects
48+
49+
### P2: Important
50+
51+
#### T5: .qmd with Julia code cells
52+
53+
- **Setup:** `julia-test.qmd` with Julia cell
54+
- **Steps:** Same as T1
55+
- **Expected:** Same as T1. Julia uses the same Jupyter engine path.
56+
57+
#### T6: Rapid successive saves
58+
59+
- **Setup:** Same `test.qmd` as T1
60+
- **Steps:** Save 5 times within 2-3 seconds (faster than render completes)
61+
- **Expected:** At most one `.quarto_ipynb`. Debounce/queue coalesces saves.
62+
- **Catches:** Race condition in invalidation during in-progress render
63+
64+
#### T7: `keep-ipynb: true`
65+
66+
- **Setup:** `test.qmd` with `keep-ipynb: true` in YAML
67+
- **Steps:** Preview, save 3 times, Ctrl+C, check files
68+
- **Expected:** `test.quarto_ipynb` persists after exit (not cleaned up). No `_1` variants during preview.
69+
- **Catches:** `invalidateForFile()` respects the `transient = false` flag set by `cleanupNotebook()`
70+
71+
#### T8: `--to pdf` format
72+
73+
- **Setup:** Same `test.qmd` (requires TinyTeX)
74+
- **Steps:** `quarto preview test.qmd --to pdf`, save 3 times
75+
- **Expected:** Same as T1. Transient notebook logic is format-independent.
76+
77+
#### T9: Plain .qmd — no code cells (regression)
78+
79+
- **Setup:** `plain.qmd` with only markdown content
80+
- **Steps:** Preview, save 3 times, check for `.quarto_ipynb` files
81+
- **Expected:** No `.quarto_ipynb` files ever created.
82+
- **Catches:** Fix is a no-op when no Jupyter engine is involved
83+
84+
#### T10: .qmd with R/knitr engine (regression)
85+
86+
- **Setup:** `r-test.qmd` with R code cell and `engine: knitr`
87+
- **Steps:** Preview, save 3 times, check for `.quarto_ipynb` files
88+
- **Expected:** No `.quarto_ipynb` files. Knitr doesn't use Jupyter intermediate.
89+
90+
#### T10b: File excluded from project inputs (regression)
91+
92+
- **Setup:** Website project with `_quarto.yml`. Create `_excluded.qmd` with a Python cell (files starting with `_` are excluded from project inputs by default)
93+
- **Steps:** `quarto preview _excluded.qmd`, save 3 times, check files, Ctrl+C
94+
- **Expected:** Falls back to single-file preview (not project preview). At most one `.quarto_ipynb`.
95+
- **Catches:** Context reuse from cmd.ts incorrectly applying project semantics to excluded files
96+
97+
### P3: Nice-to-Have
98+
99+
#### T11: Native .ipynb file
100+
101+
- **Setup:** `notebook.ipynb` (native Jupyter notebook)
102+
- **Steps:** Preview, save 3 times
103+
- **Expected:** No transient `.quarto_ipynb` — the `.ipynb` is the source, not transient.
104+
105+
#### T12: File with spaces in name
106+
107+
- **Setup:** `my document.qmd` with Python cell
108+
- **Steps:** `quarto preview "my document.qmd"`, save 3 times
109+
- **Expected:** At most one `my document.quarto_ipynb`. Path normalization handles spaces.
110+
111+
#### T13: File in subdirectory
112+
113+
- **Setup:** `subdir/deep/test.qmd` with Python cell
114+
- **Steps:** Preview from parent dir, save 3 times
115+
- **Expected:** At most one transient notebook in `subdir/deep/`.
116+
117+
#### T14: Change code cell content
118+
119+
- **Setup:** `test.qmd` with `x = 1; print(x)`
120+
- **Steps:** Change to `x = 2`, save; change to `x = 3`, save
121+
- **Expected:** At most one `.quarto_ipynb`. Code changes trigger re-execution but file is cleaned.
122+
123+
#### T15: Change YAML metadata
124+
125+
- **Setup:** `test.qmd` with `title: "Test"`
126+
- **Steps:** Change title, save; add `theme: cosmo`, save
127+
- **Expected:** Same as T1. Metadata changes go through the same render/invalidation path.
128+
129+
#### T16: Multiple .qmd files in project
130+
131+
- **Setup:** Website with `index.qmd` (Python), `about.qmd` (Python), `plain.qmd` (no code)
132+
- **Steps:** Preview project, edit index, navigate to about, edit about
133+
- **Expected:** At most one `.quarto_ipynb` per Jupyter-using file. No accumulation.
134+
135+
## Test Matrix: Single-file Preview Root URL (#14298)
136+
137+
After every change to preview URL or handler logic, verify that single-file previews serve content at the root URL and print the correct Browse URL.
138+
139+
### P1: Critical
140+
141+
#### T17: Single-file preview — root URL accessible
142+
143+
- **Setup:** `plain.qmd` with only markdown content (no code cells)
144+
- **Steps:** `quarto preview plain.qmd --port XXXX --no-browser`, then `curl -s -o /dev/null -w "%{http_code}" http://localhost:XXXX/`
145+
- **Expected:** HTTP 200. Browse URL prints `http://localhost:XXXX/` (no filename appended).
146+
- **Catches:** `projectHtmlFileRequestHandler` used for single files (defaultFile=`index.html` instead of output filename), or `previewInitialPath` returning filename instead of `""`
147+
148+
#### T18: Single-file preview — named output URL also accessible
149+
150+
- **Setup:** Same `plain.qmd`
151+
- **Steps:** `quarto preview plain.qmd --port XXXX --no-browser`, then `curl -s -o /dev/null -w "%{http_code}" http://localhost:XXXX/plain.html`
152+
- **Expected:** HTTP 200. The output filename path also serves the rendered content.
153+
- **Catches:** Handler regression where only root or only named path works
154+
155+
### P2: Important
156+
157+
#### T19: Project preview — non-index file URL correct
158+
159+
- **Setup:** Website project with `_quarto.yml`, `index.qmd`, and `about.qmd`
160+
- **Steps:** `quarto preview --port XXXX --no-browser`, navigate to `http://localhost:XXXX/about.html`
161+
- **Expected:** HTTP 200. Browse URL may include path for non-index files in project context.
162+
- **Catches:** `isSingleFile` guard accidentally excluding real project files from path computation
163+
164+
## Test File Templates
165+
166+
**Minimal Python .qmd:**
167+
```yaml
168+
---
169+
title: "Preview Test"
170+
---
171+
```
172+
173+
````
174+
```{python}
175+
print("Hello from Python")
176+
```
177+
````
178+
179+
```
180+
Edit this line to trigger re-renders.
181+
```
182+
183+
**Minimal website project (`_quarto.yml`):**
184+
```yaml
185+
project:
186+
type: website
187+
```
188+
189+
**keep-ipynb variant:**
190+
```yaml
191+
---
192+
title: "Keep ipynb Test"
193+
execute:
194+
keep-ipynb: true
195+
---
196+
```

0 commit comments

Comments
 (0)