HongzeFu commited on
Commit
9aca6ab
·
1 Parent(s): 5c590c6

ground truth action button style update,css update

Browse files
gradio-web/main.py CHANGED
@@ -123,7 +123,7 @@ def build_allowed_paths():
123
 
124
  def main():
125
  from state_manager import start_timeout_monitor
126
- from ui_layout import create_ui_blocks
127
 
128
  LOGGER.info("Starting Gradio real environment entrypoint: %s", __file__)
129
  log_runtime_graphics_env()
@@ -150,6 +150,7 @@ def main():
150
  debug=True,
151
  show_error=True,
152
  quiet=False,
 
153
  )
154
 
155
 
 
123
 
124
  def main():
125
  from state_manager import start_timeout_monitor
126
+ from ui_layout import CSS, create_ui_blocks
127
 
128
  LOGGER.info("Starting Gradio real environment entrypoint: %s", __file__)
129
  log_runtime_graphics_env()
 
150
  debug=True,
151
  show_error=True,
152
  quiet=False,
153
+ css=CSS,
154
  )
155
 
156
 
gradio-web/test/test_main_launch_config.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+ import types
5
+
6
+
7
+ class _FakeDemo:
8
+ def __init__(self):
9
+ self.launch_kwargs = None
10
+
11
+ def launch(self, **kwargs):
12
+ self.launch_kwargs = kwargs
13
+ return None
14
+
15
+
16
+ def test_main_launch_passes_ui_css(monkeypatch, reload_module):
17
+ main = reload_module("main")
18
+ fake_demo = _FakeDemo()
19
+ timeout_calls = {"count": 0}
20
+
21
+ fake_state_manager = types.SimpleNamespace(
22
+ start_timeout_monitor=lambda: timeout_calls.__setitem__("count", timeout_calls["count"] + 1)
23
+ )
24
+ fake_ui_layout = types.SimpleNamespace(
25
+ CSS="#reference_action_btn button:not(:disabled){background:#1f8b4c;}",
26
+ create_ui_blocks=lambda: fake_demo,
27
+ )
28
+
29
+ monkeypatch.setitem(sys.modules, "state_manager", fake_state_manager)
30
+ monkeypatch.setitem(sys.modules, "ui_layout", fake_ui_layout)
31
+ monkeypatch.setenv("PORT", "7861")
32
+
33
+ main.main()
34
+
35
+ assert timeout_calls["count"] == 1
36
+ assert fake_demo.launch_kwargs is not None
37
+ assert fake_demo.launch_kwargs["server_name"] == "0.0.0.0"
38
+ assert fake_demo.launch_kwargs["server_port"] == 7861
39
+ assert fake_demo.launch_kwargs["css"] == fake_ui_layout.CSS
gradio-web/test/test_ui_phase_machine_runtime_e2e.py CHANGED
@@ -43,6 +43,32 @@ def _wait_http_ready(url: str, timeout_s: float = 20.0) -> None:
43
  raise RuntimeError(f"Server did not become ready: {url}")
44
 
45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  def _read_header_task_value(page) -> str | None:
47
  return page.evaluate(
48
  """() => {
@@ -102,8 +128,10 @@ def _read_live_obs_geometry(page) -> dict[str, dict[str, float] | None]:
102
  def phase_machine_ui_url():
103
  state = {"precheck_calls": 0}
104
  demo_video_url = "https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4"
 
105
 
106
  with gr.Blocks(title="Native phase machine test") as demo:
 
107
  phase_state = gr.State("init")
108
 
109
  with gr.Column(visible=True, elem_id="login_group") as login_group:
@@ -121,6 +149,11 @@ def phase_machine_ui_url():
121
  coords_box = gr.Textbox(value="please click the keypoint selection image", elem_id="coords_box")
122
  with gr.Column(visible=False, elem_id="action_buttons_row") as action_buttons_row:
123
  exec_btn = gr.Button("EXECUTE", elem_id="exec_btn")
 
 
 
 
 
124
  next_task_btn = gr.Button("Next Task", elem_id="next_task_btn")
125
 
126
  log_output = gr.Markdown("", elem_id="log_output")
@@ -134,6 +167,7 @@ def phase_machine_ui_url():
134
  gr.update(visible=False),
135
  gr.update(visible=False),
136
  gr.update(visible=False),
 
137
  gr.update(value="please click the keypoint selection image"),
138
  "demo_video",
139
  )
@@ -144,6 +178,7 @@ def phase_machine_ui_url():
144
  gr.update(visible=True),
145
  gr.update(visible=True),
146
  gr.update(visible=True),
 
147
  "action_keypoint",
148
  )
149
 
@@ -158,6 +193,7 @@ def phase_machine_ui_url():
158
  gr.update(interactive=False),
159
  gr.update(interactive=False),
160
  gr.update(interactive=False),
 
161
  "execution_playback",
162
  )
163
 
@@ -175,6 +211,7 @@ def phase_machine_ui_url():
175
  gr.update(interactive=True),
176
  gr.update(interactive=True),
177
  gr.update(interactive=True),
 
178
  "action_keypoint",
179
  )
180
 
@@ -188,6 +225,7 @@ def phase_machine_ui_url():
188
  action_phase_group,
189
  control_panel_group,
190
  action_buttons_row,
 
191
  coords_box,
192
  phase_state,
193
  ],
@@ -196,7 +234,14 @@ def phase_machine_ui_url():
196
 
197
  video_display.end(
198
  fn=on_video_end_fn,
199
- outputs=[video_phase_group, action_phase_group, control_panel_group, action_buttons_row, phase_state],
 
 
 
 
 
 
 
200
  queue=False,
201
  )
202
 
@@ -212,6 +257,7 @@ def phase_machine_ui_url():
212
  exec_btn,
213
  next_task_btn,
214
  img_display,
 
215
  phase_state,
216
  ],
217
  queue=False,
@@ -221,7 +267,7 @@ def phase_machine_ui_url():
221
  queue=False,
222
  ).then(
223
  fn=to_action_fn,
224
- outputs=[options_radio, exec_btn, next_task_btn, img_display, phase_state],
225
  queue=False,
226
  )
227
 
@@ -399,6 +445,52 @@ def test_phase_machine_runtime_flow_and_execute_precheck(phase_machine_ui_url):
399
  assert state["precheck_calls"] >= 2
400
 
401
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
402
  def test_unified_loading_overlay_init_flow(monkeypatch):
403
  ui_layout = importlib.reload(importlib.import_module("ui_layout"))
404
 
 
43
  raise RuntimeError(f"Server did not become ready: {url}")
44
 
45
 
46
+ def _resolve_button_snapshot(page, elem_id: str) -> dict[str, str | bool | None]:
47
+ return page.evaluate(
48
+ """(elemId) => {
49
+ const button = document.querySelector(`#${elemId} button`) || document.querySelector(`button#${elemId}`);
50
+ if (!button) {
51
+ return {
52
+ found: false,
53
+ disabled: null,
54
+ backgroundColor: null,
55
+ borderColor: null,
56
+ color: null,
57
+ };
58
+ }
59
+ const style = getComputedStyle(button);
60
+ return {
61
+ found: true,
62
+ disabled: button.disabled,
63
+ backgroundColor: style.backgroundColor,
64
+ borderColor: style.borderColor,
65
+ color: style.color,
66
+ };
67
+ }""",
68
+ elem_id,
69
+ )
70
+
71
+
72
  def _read_header_task_value(page) -> str | None:
73
  return page.evaluate(
74
  """() => {
 
128
  def phase_machine_ui_url():
129
  state = {"precheck_calls": 0}
130
  demo_video_url = "https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4"
131
+ ui_layout = importlib.reload(importlib.import_module("ui_layout"))
132
 
133
  with gr.Blocks(title="Native phase machine test") as demo:
134
+ gr.HTML(f"<style>{ui_layout.CSS}</style>")
135
  phase_state = gr.State("init")
136
 
137
  with gr.Column(visible=True, elem_id="login_group") as login_group:
 
149
  coords_box = gr.Textbox(value="please click the keypoint selection image", elem_id="coords_box")
150
  with gr.Column(visible=False, elem_id="action_buttons_row") as action_buttons_row:
151
  exec_btn = gr.Button("EXECUTE", elem_id="exec_btn")
152
+ reference_action_btn = gr.Button(
153
+ "Ground Truth Action",
154
+ elem_id="reference_action_btn",
155
+ interactive=False,
156
+ )
157
  next_task_btn = gr.Button("Next Task", elem_id="next_task_btn")
158
 
159
  log_output = gr.Markdown("", elem_id="log_output")
 
167
  gr.update(visible=False),
168
  gr.update(visible=False),
169
  gr.update(visible=False),
170
+ gr.update(interactive=False),
171
  gr.update(value="please click the keypoint selection image"),
172
  "demo_video",
173
  )
 
178
  gr.update(visible=True),
179
  gr.update(visible=True),
180
  gr.update(visible=True),
181
+ gr.update(interactive=True),
182
  "action_keypoint",
183
  )
184
 
 
193
  gr.update(interactive=False),
194
  gr.update(interactive=False),
195
  gr.update(interactive=False),
196
+ gr.update(interactive=False),
197
  "execution_playback",
198
  )
199
 
 
211
  gr.update(interactive=True),
212
  gr.update(interactive=True),
213
  gr.update(interactive=True),
214
+ gr.update(interactive=True),
215
  "action_keypoint",
216
  )
217
 
 
225
  action_phase_group,
226
  control_panel_group,
227
  action_buttons_row,
228
+ reference_action_btn,
229
  coords_box,
230
  phase_state,
231
  ],
 
234
 
235
  video_display.end(
236
  fn=on_video_end_fn,
237
+ outputs=[
238
+ video_phase_group,
239
+ action_phase_group,
240
+ control_panel_group,
241
+ action_buttons_row,
242
+ reference_action_btn,
243
+ phase_state,
244
+ ],
245
  queue=False,
246
  )
247
 
 
257
  exec_btn,
258
  next_task_btn,
259
  img_display,
260
+ reference_action_btn,
261
  phase_state,
262
  ],
263
  queue=False,
 
267
  queue=False,
268
  ).then(
269
  fn=to_action_fn,
270
+ outputs=[options_radio, exec_btn, next_task_btn, img_display, reference_action_btn, phase_state],
271
  queue=False,
272
  )
273
 
 
445
  assert state["precheck_calls"] >= 2
446
 
447
 
448
+ def test_reference_action_button_is_green_only_when_interactive(phase_machine_ui_url):
449
+ root_url, _state = phase_machine_ui_url
450
+
451
+ with sync_playwright() as p:
452
+ browser = p.chromium.launch(headless=True)
453
+ page = browser.new_page(viewport={"width": 1280, "height": 900})
454
+ page.goto(root_url, wait_until="domcontentloaded")
455
+
456
+ page.wait_for_timeout(2500)
457
+ page.wait_for_selector("#login_btn", timeout=20000)
458
+ page.click("#login_btn")
459
+
460
+ disabled_snapshot = _resolve_button_snapshot(page, "reference_action_btn")
461
+ if disabled_snapshot["found"]:
462
+ assert disabled_snapshot["disabled"] is True
463
+ assert disabled_snapshot["backgroundColor"] != "rgb(31, 139, 76)"
464
+
465
+ page.wait_for_selector("#demo_video video", timeout=5000)
466
+ did_dispatch_end = page.evaluate(
467
+ """() => {
468
+ const videoEl = document.querySelector('#demo_video video');
469
+ if (!videoEl) return false;
470
+ videoEl.dispatchEvent(new Event('ended', { bubbles: true }));
471
+ return true;
472
+ }"""
473
+ )
474
+ assert did_dispatch_end
475
+
476
+ page.wait_for_function(
477
+ """() => {
478
+ const button = document.querySelector('#reference_action_btn button') || document.querySelector('button#reference_action_btn');
479
+ return !!button && button.disabled === false;
480
+ }""",
481
+ timeout=6000,
482
+ )
483
+
484
+ enabled_snapshot = _resolve_button_snapshot(page, "reference_action_btn")
485
+ assert enabled_snapshot["found"] is True
486
+ assert enabled_snapshot["disabled"] is False
487
+ assert enabled_snapshot["backgroundColor"] == "rgb(31, 139, 76)"
488
+ assert enabled_snapshot["borderColor"] == "rgb(31, 139, 76)"
489
+ assert enabled_snapshot["color"] == "rgb(255, 255, 255)"
490
+
491
+ browser.close()
492
+
493
+
494
  def test_unified_loading_overlay_init_flow(monkeypatch):
495
  ui_layout = importlib.reload(importlib.import_module("ui_layout"))
496
 
gradio-web/ui_layout.py CHANGED
@@ -216,17 +216,15 @@ CSS = f"""
216
  margin: 0 !important;
217
  }}
218
 
219
- button#reference_action_btn:not(:disabled),
220
- #reference_action_btn:not(:disabled),
221
- #reference_action_btn button:not(:disabled) {{
222
  background: #1f8b4c !important;
223
  border-color: #1f8b4c !important;
224
  color: #ffffff !important;
225
  }}
226
 
227
- button#reference_action_btn:not(:disabled):hover,
228
- #reference_action_btn:not(:disabled):hover,
229
- #reference_action_btn button:not(:disabled):hover {{
230
  background: #19713d !important;
231
  border-color: #19713d !important;
232
  }}
 
216
  margin: 0 !important;
217
  }}
218
 
219
+ #reference_action_btn button:not(:disabled),
220
+ button#reference_action_btn:not(:disabled) {{
 
221
  background: #1f8b4c !important;
222
  border-color: #1f8b4c !important;
223
  color: #ffffff !important;
224
  }}
225
 
226
+ #reference_action_btn button:not(:disabled):hover,
227
+ button#reference_action_btn:not(:disabled):hover {{
 
228
  background: #19713d !important;
229
  border-color: #19713d !important;
230
  }}