mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-09-15 04:32:23 +02:00
116 lines
4.8 KiB
Python
116 lines
4.8 KiB
Python
import json
|
|
import subprocess
|
|
import textwrap
|
|
from pathlib import Path
|
|
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
MODULE = (ROOT / "static/js/editor/render-cancellation.js").as_uri()
|
|
EDITOR_SOURCE = ROOT / "static/js/galleryEditor.js"
|
|
ADJUSTMENT_SOURCE = ROOT / "static/js/editor/adjustment-layer.js"
|
|
EFFECTS_SOURCE = ROOT / "static/js/editor/effects.js"
|
|
|
|
|
|
def run_node(body: str):
|
|
script = textwrap.dedent(
|
|
f"""
|
|
import {{createRenderGeneration}} from {json.dumps(MODULE)};
|
|
{body}
|
|
"""
|
|
)
|
|
result = subprocess.run(
|
|
["node", "--input-type=module", "-e", script], cwd=ROOT,
|
|
text=True, capture_output=True, check=True,
|
|
)
|
|
return json.loads(result.stdout)
|
|
|
|
|
|
def test_new_render_generation_invalidates_previous_work():
|
|
result = run_node(
|
|
"""
|
|
const generations = createRenderGeneration();
|
|
const first = generations.begin();
|
|
const second = generations.begin();
|
|
console.log(JSON.stringify({first:first.isCurrent(), second:second.isCurrent()}));
|
|
"""
|
|
)
|
|
assert result == {"first": False, "second": True}
|
|
|
|
|
|
def test_cancel_only_invalidates_the_cancelled_generation():
|
|
result = run_node(
|
|
"""
|
|
const generations = createRenderGeneration();
|
|
const render = generations.begin();
|
|
render.cancel();
|
|
const next = generations.begin();
|
|
console.log(JSON.stringify({cancelled:render.isCurrent(), next:next.isCurrent()}));
|
|
"""
|
|
)
|
|
assert result == {"cancelled": False, "next": True}
|
|
|
|
|
|
def test_live_composite_coalesces_worker_generations_to_one_latest_rerender():
|
|
editor = EDITOR_SOURCE.read_text()
|
|
assert "let _asyncCompositeInFlight = null;" in editor
|
|
assert "let _asyncCompositeQueued = false;" in editor
|
|
assert "_renderGeneration.invalidate();" in editor
|
|
assert "_asyncCompositeQueued = true;" in editor
|
|
assert "if (_asyncCompositeQueued)" in editor
|
|
|
|
|
|
def test_editor_close_invalidates_async_composite_lifecycle():
|
|
editor = EDITOR_SOURCE.read_text()
|
|
close_start = editor.index("export function closeEditor(")
|
|
close_source = editor[close_start:]
|
|
assert "_renderGeneration.invalidate();" in close_source
|
|
assert "_asyncCompositeQueued = false;" in close_source
|
|
assert "_asyncCompositeInFlight = null;" in close_source
|
|
|
|
|
|
def test_stale_adjustment_worker_errors_do_not_run_full_resolution_fallback():
|
|
adjustment = ADJUSTMENT_SOURCE.read_text()
|
|
assert "worker.onerror = () => finish(shouldContinue() ? applyAdjustment(source, adjustment) : null);" in adjustment
|
|
assert "return shouldContinue() ? applyAdjustment(source, adjustment) : null;" in adjustment
|
|
assert "if (!shouldContinue()) return false;\n adjusted = renderWithLayerMasks" in adjustment
|
|
|
|
|
|
def test_stale_effect_worker_errors_do_not_run_full_resolution_fallback():
|
|
effects = EFFECTS_SOURCE.read_text()
|
|
assert "return shouldContinue() ? renderEffects(source, effects, shouldContinue) : null;" in effects
|
|
assert "worker.onerror = () => finish(shouldContinue() ? renderEffects(source, effects, shouldContinue) : null);" in effects
|
|
assert "if (!shouldContinue()) {\n sourceBitmap.close?.();" in effects
|
|
|
|
|
|
def test_autosave_thumbnail_uses_only_a_completed_composite_surface():
|
|
editor = EDITOR_SOURCE.read_text()
|
|
assert "state.documentRenderReady = false;" in editor
|
|
assert "state.documentRenderReady = true;" in editor
|
|
assert "state.documentRenderReady && state.documentCompositeCanvas" in editor
|
|
assert ": flatten();" in editor
|
|
|
|
|
|
def test_autosave_thumbnail_encoding_can_leave_the_main_thread():
|
|
editor = EDITOR_SOURCE.read_text()
|
|
assert "async function _buildThumbnailAsync()" in editor
|
|
assert "new URL('./editor/thumbnail-worker.js', import.meta.url)" in editor
|
|
assert "const thumbnailPromise = _buildThumbnailAsync();" in editor
|
|
assert "const savePromise = doSave();" in editor
|
|
assert "state.persistInFlight = savePromise" in editor
|
|
|
|
|
|
def test_autosave_serializes_canvas_payloads_from_an_immutable_metadata_snapshot():
|
|
editor = EDITOR_SOURCE.read_text()
|
|
assert "function _serializationSnapshot(source, canvasProxy)" in editor
|
|
assert "new URL('./editor/serialization-worker.js', import.meta.url)" in editor
|
|
assert "const payload = _serializeEditorDocument(snapshot);" in editor
|
|
assert "const encoded = await _encodeSerializedCanvases(canvases);" in editor
|
|
assert "const payloadPromise = _buildDraftPayloadAsync();" in editor
|
|
|
|
|
|
def test_autosave_captures_payload_and_thumbnail_before_close_can_clear_state():
|
|
editor = EDITOR_SOURCE.read_text()
|
|
assert "const payloadPromise = _buildDraftPayloadAsync();" in editor
|
|
assert "const thumbnailPromise = _buildThumbnailAsync();" in editor
|
|
assert "const [payload, thumbnail] = await Promise.all([payloadPromise, thumbnailPromise]);" in editor
|