2222
2323HAS_XELATEX = check_installed (["xelatex" , "--version" ])
2424HAS_ASY = check_installed (["asy" , "--version" ])
25+ HAS_SAGE = check_installed (["sage" , "--version" ])
2526
2627
2728@contextmanager
@@ -88,6 +89,10 @@ def test_devscript(script_runner: ScriptRunner) -> None:
8889 not HAS_XELATEX ,
8990 reason = "Skipped since xelatex isn't found." ,
9091)
92+ @pytest .mark .skipif (
93+ not HAS_SAGE ,
94+ reason = "Skipped since sage isn't found." ,
95+ )
9196@pytest .mark .skipif (
9297 not HAS_ASY ,
9398 reason = "Skipped since asy isn't found." ,
@@ -131,7 +136,6 @@ def test_build(tmp_path: Path, script_runner: ScriptRunner) -> None:
131136 / "fig_tikz-example-diagram.svg"
132137 ).exists ()
133138
134- # Do a full build.
135139 assert script_runner .run (
136140 [PTX_CMD , "-v" , "debug" , "build" , "web" ], cwd = project_path
137141 ).success
@@ -242,98 +246,137 @@ def test_init_and_update_with_git(tmp_path: Path, script_runner: ScriptRunner) -
242246 assert f"pretext == { pretext .VERSION } \n " in lines [1 ]
243247
244248
245- @pytest .mark .skipif (
246- not HAS_ASY ,
247- reason = "Skipped since asy isn't found." ,
248- )
249- def test_build_generate (tmp_path : Path , script_runner : ScriptRunner ) -> None :
249+ def test_build_no_generate (tmp_path : Path , script_runner : ScriptRunner ) -> None :
250250 """
251- Test the behavior of `pretext build -g ` (force generate) and `pretext build -q` (no generate) .
251+ Test the behavior of `pretext build -q ` (no generate) and -g -q together .
252252
253253 Expected behaviors (per docs/asset-generation.md):
254254 - `pretext build -q`: no assets are generated, even if source has changed.
255- - `pretext build -g`: all assets generated regardless of whether source has changed.
256255 - `pretext build -g -q`: warning issued; proceeds as if neither flag was set.
257- - Regular `pretext build` after a successful build: assets NOT regenerated when source is unchanged.
258256 """
259- graphics_path = tmp_path / "graphics "
260- shutil .copytree (EXAMPLES_DIR / "projects" / "graphics " , graphics_path )
257+ prefigure_path = tmp_path / "prefigure "
258+ shutil .copytree (EXAMPLES_DIR / "projects" / "prefigure " , prefigure_path )
261259
262- asymptote_asset = graphics_path / "generated-assets" / "asymptote" / "test.html"
263- prefigure_asset = graphics_path / "generated-assets" / "prefigure" / "pftest.svg"
260+ prefigure_asset = prefigure_path / "generated-assets" / "prefigure" / "pftest.svg"
264261
265262 # --- Test -q: build without generating any assets ---
266263 result = script_runner .run (
267- [PTX_CMD , "-v" , "debug" , "build" , "-q" ], cwd = graphics_path
264+ [PTX_CMD , "-v" , "debug" , "build" , "-q" ], cwd = prefigure_path
268265 )
269266 assert result .success
270- assert not asymptote_asset .exists (), (
271- "Assets should NOT be generated when using -q (no-generate)"
272- )
273- assert not prefigure_asset .exists (), (
274- "Assets should NOT be generated when using -q (no-generate)"
267+ assert (
268+ not prefigure_asset .exists ()
269+ ), "Prefigure assets should NOT be generated when using -q (no-generate)"
270+
271+ # --- Test -g -q together: warning issued, behaves like normal build ---
272+ result = script_runner .run (
273+ [PTX_CMD , "-v" , "debug" , "build" , "-g" , "-q" ], cwd = prefigure_path
275274 )
275+ assert result .success
276+ # The warning message about conflicting flags should appear in the output.
277+ combined_output = result .stdout + result .stderr
278+ assert (
279+ "doesn't make sense" in combined_output
280+ ), "A warning about using -g and -q together should be emitted"
281+ # Since the flags cancel each other, behavior is like a normal build.
282+ # On a clean project, that means the missing prefigure asset should be generated.
283+ assert (
284+ prefigure_asset .exists ()
285+ ), "With -g and -q together, prefigure assets should be generated on a clean project (flags cancel each other)"
286+
287+
288+ def test_build_force_generate_prefigure (
289+ tmp_path : Path , script_runner : ScriptRunner
290+ ) -> None :
291+ """
292+ Test the behavior of `pretext build -g` (force generate) and regular builds.
293+
294+ Expected behaviors (per docs/asset-generation.md):
295+ - `pretext build -g`: all assets generated regardless of whether source has changed.
296+ - Regular `pretext build` after a successful build: assets NOT regenerated when source is unchanged.
297+ """
298+ prefigure_path = tmp_path / "prefigure"
299+ shutil .copytree (EXAMPLES_DIR / "projects" / "prefigure" , prefigure_path )
300+
301+ prefigure_asset = prefigure_path / "generated-assets" / "prefigure" / "pftest.svg"
276302
277303 # --- Test -g: build with force-generate ---
278304 result = script_runner .run (
279- [PTX_CMD , "-v" , "debug" , "build" , "-g" ], cwd = graphics_path
305+ [PTX_CMD , "-v" , "debug" , "build" , "-g" ], cwd = prefigure_path
280306 )
281307 assert result .success
282- assert asymptote_asset .exists (), (
283- "Asymptote asset should be generated when using -g (force generate)"
284- )
285- assert prefigure_asset .exists (), (
286- "Prefigure asset should be generated when using -g (force generate)"
287- )
288- assert (graphics_path / "output" / "web" ).exists (), (
289- "Build output should exist after `pretext build -g`"
290- )
308+ assert (
309+ prefigure_asset .exists ()
310+ ), "Prefigure asset should be generated when using -g (force generate)"
311+ assert (
312+ prefigure_path / "output" / "web"
313+ ).exists (), "Build output should exist after `pretext build -g`"
291314
292315 # --- Test regular build does NOT regenerate when source is unchanged ---
293316 # Delete the generated asset to simulate a missing file after a previous build.
294- asymptote_asset .unlink ()
295- assert not asymptote_asset .exists ()
317+ prefigure_asset .unlink ()
318+ assert not prefigure_asset .exists ()
296319
297320 # A regular build (no -g flag) should NOT regenerate since source hash has not changed.
298- result = script_runner .run (
299- [PTX_CMD , "-v" , "debug" , "build" ], cwd = graphics_path
300- )
321+ result = script_runner .run ([PTX_CMD , "-v" , "debug" , "build" ], cwd = prefigure_path )
301322 assert result .success
302- assert not asymptote_asset . exists (), (
303- "Regular `pretext build` should NOT regenerate assets when source is unchanged"
304- )
323+ assert (
324+ not prefigure_asset . exists ()
325+ ), "Regular `pretext build` should NOT regenerate prefigure assets when source is unchanged"
305326
306327 # --- Test -g regenerates even though source is unchanged ---
307328 result = script_runner .run (
308- [PTX_CMD , "-v" , "debug" , "build" , "-g" ], cwd = graphics_path
329+ [PTX_CMD , "-v" , "debug" , "build" , "-g" ], cwd = prefigure_path
309330 )
310331 assert result .success
311- assert asymptote_asset .exists (), (
312- "`pretext build -g` should regenerate assets even when source is unchanged"
313- )
332+ assert (
333+ prefigure_asset .exists ()
334+ ), "`pretext build -g` should regenerate prefigure assets even when source is unchanged"
335+
336+
337+ @pytest .mark .skipif (
338+ not HAS_ASY ,
339+ reason = "Skipped since asy isn't found." ,
340+ )
341+ def test_build_force_generate_asymptote (
342+ tmp_path : Path , script_runner : ScriptRunner
343+ ) -> None :
344+ graphics_path = tmp_path / "graphics"
345+ shutil .copytree (EXAMPLES_DIR / "projects" / "graphics" , graphics_path )
346+
347+ asymptote_asset = graphics_path / "generated-assets" / "asymptote" / "test.html"
314348
315- # --- Test -g -q together: warning issued, behaves like normal build ---
316- # Remove an asset to confirm it is NOT regenerated (warning clears both flags, behaves like normal build).
317- asymptote_asset .unlink ()
318349 result = script_runner .run (
319- [PTX_CMD , "-v" , "debug" , "build" , "-g" , "-q" ], cwd = graphics_path
350+ [PTX_CMD , "-v" , "debug" , "build" , "-g" ], cwd = graphics_path
320351 )
321352 assert result .success
322- # The warning message about conflicting flags should appear in the output.
323- combined_output = result .stdout + result .stderr
324- assert "doesn't make sense" in combined_output , (
325- "A warning about using -g and -q together should be emitted"
326- )
327- # Since the flags cancel each other, behavior is like a normal build with no source changes,
328- # so assets should NOT be regenerated.
329- assert not asymptote_asset .exists (), (
330- "With -g and -q together, assets should not be regenerated (flags cancel each other)"
331- )
353+ assert (
354+ asymptote_asset .exists ()
355+ ), "Asymptote asset should be generated when using -g (force generate)"
332356
333357
334- def test_generate_graphics (tmp_path : Path , script_runner : ScriptRunner ) -> None :
358+ def test_generate_graphics_prefigure (
359+ tmp_path : Path , script_runner : ScriptRunner
360+ ) -> None :
361+ prefigure_path = tmp_path / "prefigure"
362+ shutil .copytree (EXAMPLES_DIR / "projects" / "prefigure" , prefigure_path )
363+
364+ assert script_runner .run (
365+ [PTX_CMD , "-v" , "debug" , "generate" , "prefigure" ], cwd = prefigure_path
366+ ).success
367+ assert (prefigure_path / "generated-assets" / "prefigure" / "pftest.svg" ).exists ()
368+
369+
370+ @pytest .mark .skipif (
371+ not HAS_ASY ,
372+ reason = "Skipped since asy isn't found." ,
373+ )
374+ def test_generate_graphics_asymptote_local (
375+ tmp_path : Path , script_runner : ScriptRunner
376+ ) -> None :
335377 graphics_path = tmp_path / "graphics"
336378 shutil .copytree (EXAMPLES_DIR / "projects" / "graphics" , graphics_path )
379+
337380 assert script_runner .run (
338381 [PTX_CMD , "-v" , "debug" , "generate" , "asymptote" ], cwd = graphics_path
339382 ).success
@@ -348,11 +391,27 @@ def test_generate_graphics(tmp_path: Path, script_runner: ScriptRunner) -> None:
348391 [PTX_CMD , "-v" , "debug" , "generate" , "asymptote" , "-t" , "web" ],
349392 cwd = graphics_path ,
350393 ).success
351- os .remove (graphics_path / "generated-assets" / "asymptote" / "test.html" )
394+
395+
396+ def test_generate_graphics_asymptote_server (
397+ tmp_path : Path , script_runner : ScriptRunner
398+ ) -> None :
399+ graphics_path = tmp_path / "graphics"
400+ shutil .copytree (EXAMPLES_DIR / "projects" / "graphics" , graphics_path )
401+
402+ # Force server-backed asymptote generation so this test is independent of local asy.
403+ project_manifest = graphics_path / "project.ptx"
404+ project_manifest .write_text (
405+ project_manifest .read_text ().replace (
406+ '<project ptx-version="2">' ,
407+ '<project ptx-version="2" asy-method="server">' ,
408+ )
409+ )
410+
352411 assert script_runner .run (
353- [PTX_CMD , "-v" , "debug" , "generate" , "prefigure " ], cwd = graphics_path
412+ [PTX_CMD , "-v" , "debug" , "generate" , "asymptote " ], cwd = graphics_path
354413 ).success
355- assert (graphics_path / "generated-assets" / "prefigure " / "pftest.svg " ).exists ()
414+ assert (graphics_path / "generated-assets" / "asymptote " / "test.html " ).exists ()
356415
357416
358417# @pytest.mark.skip(
0 commit comments