Path: blob/main/tests/docs/manual/preview/README.md
12922 views
Manual Preview Tests
Tests for quarto preview behavior that require an interactive session with file-save events. These cannot run in automated smoke tests.
Automation
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.
For browser interaction, /agent-browser is preferred over Chrome DevTools MCP (more token-efficient). See the command for details.
Test Matrix: quarto_ipynb Accumulation (#14281)
After every test involving Jupyter execution (Python/Julia cells), verify:
ls *.quarto_ipynb*— at most one{name}.quarto_ipynb(no_1,_2variants)After Ctrl+C exit — no
.quarto_ipynbfiles remain (unlesskeep-ipynb: true)
For tests without Jupyter execution (T9, T10, T11), verify no .quarto_ipynb files are created at all.
P1: Critical
T1: Single .qmd with Python — re-render accumulation
Setup:
test.qmdwith Python code cellSteps:
quarto preview test.qmd, save 5 times, check files, Ctrl+CExpected: At most one
.quarto_ipynbat any time. Zero after exit.Catches:
invalidateForFile()not deleting transient file before cache eviction
T2: Single .qmd with Python — startup duplicate
Setup: Same
test.qmdSteps:
quarto preview test.qmd, check files immediately after first render (before any saves), Ctrl+CExpected: Exactly one
.quarto_ipynbduring render. Zero after exit.Catches:
cmd.tsnot passing ProjectContext topreview()
T3: .qmd in project — project-level preview
Setup: Website project (
_quarto.ymlwithtype: website),index.qmdwith Python cellSteps:
quarto preview(project dir), saveindex.qmd3 times, check files, Ctrl+CExpected: At most one
index.quarto_ipynb. Zero after exit.Catches: Fix works when
projectContext()finds a real project
T4: .qmd in project — single file preview
Setup: Same project as T3
Steps:
quarto preview index.qmd, save 3 times, check files, Ctrl+CExpected: Same as T3. May redirect to project preview (expected behavior).
Catches: Context passing works for files inside serveable projects
P2: Important
T5: .qmd with Julia code cells
Setup:
julia-test.qmdwith Julia cellSteps: Same as T1
Expected: Same as T1. Julia uses the same Jupyter engine path.
T6: Rapid successive saves
Setup: Same
test.qmdas T1Steps: Save 5 times within 2-3 seconds (faster than render completes)
Expected: At most one
.quarto_ipynb. Debounce/queue coalesces saves.Catches: Race condition in invalidation during in-progress render
T7: keep-ipynb: true
Setup:
test.qmdwithkeep-ipynb: truein YAMLSteps: Preview, save 3 times, Ctrl+C, check files
Expected:
test.quarto_ipynbpersists after exit (not cleaned up). No_1variants during preview.Catches:
invalidateForFile()respects thetransient = falseflag set bycleanupNotebook()
T8: --to pdf format
Setup: Same
test.qmd(requires TinyTeX)Steps:
quarto preview test.qmd --to pdf, save 3 timesExpected: Same as T1. Transient notebook logic is format-independent.
T9: Plain .qmd — no code cells (regression)
Setup:
plain.qmdwith only markdown contentSteps: Preview, save 3 times, check for
.quarto_ipynbfilesExpected: No
.quarto_ipynbfiles ever created.Catches: Fix is a no-op when no Jupyter engine is involved
T10: .qmd with R/knitr engine (regression)
Setup:
r-test.qmdwith R code cell andengine: knitrSteps: Preview, save 3 times, check for
.quarto_ipynbfilesExpected: No
.quarto_ipynbfiles. Knitr doesn't use Jupyter intermediate.
T10b: File excluded from project inputs (regression)
Setup: Website project with
_quarto.yml. Create_excluded.qmdwith a Python cell (files starting with_are excluded from project inputs by default)Steps:
quarto preview _excluded.qmd, save 3 times, check files, Ctrl+CExpected: Falls back to single-file preview (not project preview). At most one
.quarto_ipynb.Catches: Context reuse from cmd.ts incorrectly applying project semantics to excluded files
P3: Nice-to-Have
T11: Native .ipynb file
Setup:
notebook.ipynb(native Jupyter notebook)Steps: Preview, save 3 times
Expected: No transient
.quarto_ipynb— the.ipynbis the source, not transient.
T12: File with spaces in name
Setup:
my document.qmdwith Python cellSteps:
quarto preview "my document.qmd", save 3 timesExpected: At most one
my document.quarto_ipynb. Path normalization handles spaces.
T13: File in subdirectory
Setup:
subdir/deep/test.qmdwith Python cellSteps: Preview from parent dir, save 3 times
Expected: At most one transient notebook in
subdir/deep/.
T14: Change code cell content
Setup:
test.qmdwithx = 1; print(x)Steps: Change to
x = 2, save; change tox = 3, saveExpected: At most one
.quarto_ipynb. Code changes trigger re-execution but file is cleaned.
T15: Change YAML metadata
Setup:
test.qmdwithtitle: "Test"Steps: Change title, save; add
theme: cosmo, saveExpected: Same as T1. Metadata changes go through the same render/invalidation path.
T16: Multiple .qmd files in project
Setup: Website with
index.qmd(Python),about.qmd(Python),plain.qmd(no code)Steps: Preview project, edit index, navigate to about, edit about
Expected: At most one
.quarto_ipynbper Jupyter-using file. No accumulation.
Test Matrix: Single-file Preview Root URL (#14298)
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.
P1: Critical
T17: Single-file preview — root URL accessible
Setup:
plain.qmdwith only markdown content (no code cells)Steps:
quarto preview plain.qmd --port XXXX --no-browser, thencurl -s -o /dev/null -w "%{http_code}" http://localhost:XXXX/Expected: HTTP 200. Browse URL prints
http://localhost:XXXX/(no filename appended).Catches:
projectHtmlFileRequestHandlerused for single files (defaultFile=index.htmlinstead of output filename), orpreviewInitialPathreturning filename instead of""
T18: Single-file preview — named output URL also accessible
Setup: Same
plain.qmdSteps:
quarto preview plain.qmd --port XXXX --no-browser, thencurl -s -o /dev/null -w "%{http_code}" http://localhost:XXXX/plain.htmlExpected: HTTP 200. The output filename path also serves the rendered content.
Catches: Handler regression where only root or only named path works
P2: Important
T19: Project preview — non-index file URL correct
Setup: Website project with
_quarto.yml,index.qmd, andabout.qmdSteps:
quarto preview --port XXXX --no-browser, navigate tohttp://localhost:XXXX/about.htmlExpected: HTTP 200. Browse URL may include path for non-index files in project context.
Catches:
isSingleFileguard accidentally excluding real project files from path computation
Test File Templates
Minimal Python .qmd:
Minimal website project (_quarto.yml):
keep-ipynb variant: