File size: 5,776 Bytes
bc1d8e8 aff5726 bc1d8e8 aff5726 bc1d8e8 aff5726 bc1d8e8 aff5726 bc1d8e8 aff5726 bc1d8e8 aff5726 bc1d8e8 aff5726 bc1d8e8 aff5726 bc1d8e8 aff5726 bc1d8e8 aff5726 bc1d8e8 aff5726 bc1d8e8 aff5726 bc1d8e8 aff5726 bc1d8e8 aff5726 bc1d8e8 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
#!/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 = '<div id="test1" style="padding:20px;background:#333;color:#fff;margin:10px;border-radius:8px;">Test 1: Waiting...</div>'
TEST1_JS = """
element.innerText = 'Test 1: PASS - js_on_load executed!';
element.style.background = '#228B22';
"""
# Test 2: Async IIFE pattern
TEST2_HTML = '<div id="test2" style="padding:20px;background:#333;color:#fff;margin:10px;border-radius:8px;">Test 2: Waiting...</div>'
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 = '<div id="test3" style="padding:20px;background:#333;color:#fff;margin:10px;border-radius:8px;">Test 3: Waiting...</div>'
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 = """
<div id="test4-container" style="padding:20px;background:#333;color:#fff;margin:10px;border-radius:8px;">
<div id="test4-status">Test 4: Waiting...</div>
<canvas id="test4-canvas" style="width:200px;height:100px;background:#000;margin-top:10px;"></canvas>
</div>
"""
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 = """
<div id="test5-container" style="padding:20px;background:#333;color:#fff;margin:10px;border-radius:8px;">
<div id="test5-status">Test 5: Waiting...</div>
<div id="test5-value" style="font-family:monospace;font-size:12px;margin-top:10px;"></div>
</div>
"""
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)
|