#!/usr/bin/env python
"""Test script to verify js_on_load + async + dynamic import works in Gradio.
This tests the core mechanism needed to fix the NiiVue black screen bug.
Run:
uv run python scripts/test_js_on_load.py
Then open http://localhost:7860 and check if the tests pass.
"""
from pathlib import Path
import gradio as gr
# Setup local assets for testing
# This mirrors the fix in the main app
ASSETS_DIR = Path(__file__).parent.parent / "src" / "stroke_deepisles_demo" / "ui" / "assets"
gr.set_static_paths(paths=[str(ASSETS_DIR)])
NIIVUE_JS_URL = f"/gradio_api/file={ASSETS_DIR / 'niivue.js'}"
# Test 1: Basic js_on_load execution
TEST1_HTML = '
Test 1: Waiting...
'
TEST1_JS = """
element.innerText = 'Test 1: PASS - js_on_load executed!';
element.style.background = '#228B22';
"""
# Test 2: Async IIFE pattern
TEST2_HTML = 'Test 2: Waiting...
'
TEST2_JS = """
(async () => {
element.innerText = 'Test 2: Async started...';
await new Promise(r => setTimeout(r, 500));
element.innerText = 'Test 2: PASS - Async/await works!';
element.style.background = '#228B22';
})();
"""
# Test 3: Dynamic import from Local (was CDN)
TEST3_HTML = 'Test 3: Waiting...
'
TEST3_JS = f"""
(async () => {{
element.innerText = 'Test 3: Loading NiiVue from Local...';
try {{
const mod = await import('{NIIVUE_JS_URL}');
if (mod.Niivue) {{
element.innerText = 'Test 3: PASS - NiiVue loaded! Niivue class available.';
element.style.background = '#228B22';
}} else {{
element.innerText = 'Test 3: PARTIAL - Module loaded but no Niivue class';
element.style.background = '#FFA500';
}}
}} catch(e) {{
element.innerText = 'Test 3: FAIL - ' + e.message;
element.style.background = '#DC143C';
}}
}})();
"""
# Test 4: Canvas + WebGL2 check
TEST4_HTML = """
"""
TEST4_JS = f"""
(async () => {{
const status = element.querySelector('#test4-status');
const canvas = element.querySelector('#test4-canvas');
status.innerText = 'Test 4: Checking WebGL2...';
const gl = canvas.getContext('webgl2');
if (!gl) {{
status.innerText = 'Test 4: FAIL - WebGL2 not supported';
element.style.background = '#DC143C';
return;
}}
status.innerText = 'Test 4: Loading NiiVue...';
try {{
const {{ Niivue }} = await import('{NIIVUE_JS_URL}');
const nv = new Niivue({{ logging: false, backColor: [0.2, 0.2, 0.3, 1] }});
await nv.attachToCanvas(canvas);
nv.drawScene();
status.innerText = 'Test 4: PASS - NiiVue attached to canvas!';
status.style.color = '#90EE90';
}} catch(e) {{
status.innerText = 'Test 4: FAIL - ' + e.message;
element.style.background = '#DC143C';
}}
}})();
"""
# Test 5: Full integration with props.value
TEST5_HTML = """
"""
TEST5_JS = """
const status = element.querySelector('#test5-status');
const valueDiv = element.querySelector('#test5-value');
// Check if we can access props
if (typeof props !== 'undefined') {
status.innerText = 'Test 5: PASS - props object accessible!';
status.style.color = '#90EE90';
valueDiv.innerText = 'props.value = ' + JSON.stringify(props.value ?? null).substring(0, 100) + '...';
} else {
status.innerText = 'Test 5: FAIL - props not defined';
element.style.background = '#DC143C';
}
"""
with gr.Blocks(title="js_on_load Test Suite") as demo:
gr.Markdown("""
# NiiVue js_on_load Test Suite
Testing if `js_on_load` supports the patterns we need for NiiVue:
1. **Basic execution** - Does js_on_load run at all?
2. **Async IIFE** - Does `(async () => { await ... })()` work?
3. **Dynamic import** - Can we `await import()` from local assets?
4. **Canvas + NiiVue** - Can we attach NiiVue to a canvas?
5. **Props access** - Can we read `props.value`?
All tests should show green "PASS" if our fix will work.
""")
with gr.Row():
with gr.Column():
gr.HTML(value=TEST1_HTML, js_on_load=TEST1_JS)
gr.HTML(value=TEST2_HTML, js_on_load=TEST2_JS)
gr.HTML(value=TEST3_HTML, js_on_load=TEST3_JS)
with gr.Column():
gr.HTML(value=TEST4_HTML, js_on_load=TEST4_JS)
gr.HTML(value=TEST5_HTML, js_on_load=TEST5_JS)
gr.Markdown("""
---
**If all tests pass:** We can implement the `js_on_load` fix for NiiVue viewer.
**If tests fail:** We'll need alternative approaches (gradio-iframe or enhanced 2D).
""")
if __name__ == "__main__":
print("Starting js_on_load test server...")
print("Open http://localhost:7860 to see test results")
demo.launch(server_port=7860)