File size: 7,775 Bytes
06c11b0 a7b9f8e 6d95d0c a7b9f8e 8a7aab0 6d95d0c 8a7aab0 5de6fb7 601060f 6a155d5 601060f 6a155d5 5de6fb7 79a56bd 02e3d3d d10d370 a365309 d10d370 06c11b0 8a7aab0 06c11b0 a74e633 06c11b0 a74e633 347ca04 06c11b0 d1f67eb 06c11b0 6d95d0c e51a493 06c11b0 347ca04 a74e633 4ccc0e4 347ca04 06c11b0 347ca04 a74e633 06c11b0 4ccc0e4 06c11b0 | 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 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | from __future__ import annotations
def test_native_ui_has_no_legacy_runtime_js_or_card_shell_tokens(reload_module):
ui_layout = reload_module("ui_layout")
assert ui_layout.SYNC_JS.strip() == ""
css = ui_layout.CSS
assert ".native-card" in css
forbidden_tokens = [
"card-shell-hit",
"card-shell-button",
"floating-card",
"applyCardShellOnce",
"media_card_anchor",
"action_selection_card_anchor",
"next_task_btn_card_anchor",
"MutationObserver",
]
for token in forbidden_tokens:
assert token not in css
def test_native_ui_css_uses_configured_global_font_size_variables(reload_module):
config = reload_module("config")
ui_layout = reload_module("ui_layout")
css = ui_layout.CSS
assert f"--body-text-size: {config.UI_GLOBAL_FONT_SIZE} !important;" in css
assert f"--prose-text-size: {config.UI_GLOBAL_FONT_SIZE} !important;" in css
assert f"--input-text-size: {config.UI_GLOBAL_FONT_SIZE} !important;" in css
assert f"--block-label-text-size: {config.UI_GLOBAL_FONT_SIZE} !important;" in css
assert f"--button-large-text-size: {config.UI_GLOBAL_FONT_SIZE} !important;" in css
assert f"--section-header-text-size: {config.UI_GLOBAL_FONT_SIZE} !important;" in css
assert f"--text-md: {config.UI_GLOBAL_FONT_SIZE} !important;" in css
assert "#load_status_mode" not in css
def test_native_ui_css_excludes_header_title_from_global_font_size(reload_module):
ui_layout = reload_module("ui_layout")
assert "#header_title h2" in ui_layout.CSS
assert "font-size: var(--text-xxl) !important;" in ui_layout.CSS
def test_native_ui_forces_light_theme_and_uses_light_overlay_baseline(reload_module):
ui_layout = reload_module("ui_layout")
css = ui_layout.CSS
assert "color-scheme: light !important;" in css
assert "#loading_overlay_group" not in css
assert "body.dark," not in css
assert ".dark," not in css
assert ":root.dark" not in css
assert "rgba(15, 23, 42, 0.92)" not in css
assert "window.__robommeForceLightTheme = applyLightTheme;" in ui_layout.THEME_LOCK_HEAD
assert 'store.setItem("gradio-theme", "light");' in ui_layout.THEME_LOCK_HEAD
assert 'node.classList.remove("dark");' in ui_layout.THEME_LOCK_HEAD
assert "window.__robommeForceLightTheme();" in ui_layout.THEME_LOCK_JS
def test_native_ui_css_highlights_media_card_not_live_obs_transform(reload_module):
ui_layout = reload_module("ui_layout")
css = ui_layout.CSS
assert "#media_card::after" in css
assert "--media-card-radius: 8px;" in css
assert "#media_card #live_obs button" in css
assert "#media_card #live_obs img" in css
assert "#media_card:has(#live_obs.live-obs-point-waiting)::after" in css
assert "inset: 0;" in css
assert "border-radius: inherit;" in css
assert "animation: media-card-point-ring 1.2s ease-in-out infinite;" in css
assert "@keyframes media-card-point-ring" in css
assert "#live_obs.live-obs-point-waiting .image-frame" not in css
assert "#live_obs.live-obs-point-waiting .upload-container" not in css
assert "transform: scale(" not in css
def test_extract_last_goal_prefers_last_list_item(reload_module):
ui_layout = reload_module("ui_layout")
assert ui_layout.extract_last_goal("['goal a', 'goal b']") == "goal b"
def test_render_header_goal_capitalizes_display_value(reload_module):
ui_layout = reload_module("ui_layout")
assert ui_layout.render_header_goal("place cube on target") == "Place cube on target"
assert ui_layout.render_header_goal("['goal a', 'goal b']") == "Goal b"
assert ui_layout.render_header_goal("") == "—"
def test_header_task_dropdown_uses_task_name_list_order(reload_module):
config = reload_module("config")
ui_layout = reload_module("ui_layout")
ui_layout.user_manager.env_choices = list(config.TASK_NAME_LIST)
demo = ui_layout.create_ui_blocks()
try:
cfg = demo.get_config_file()
header_task_comp = next(
comp
for comp in cfg.get("components", [])
if comp.get("props", {}).get("elem_id") == "header_task"
)
choices = header_task_comp.get("props", {}).get("choices") or []
normalized_choices = [choice[0] if isinstance(choice, (list, tuple)) else choice for choice in choices]
assert normalized_choices == config.TASK_NAME_LIST
finally:
demo.close()
def test_native_ui_config_contains_phase_machine_and_precheck_chain(reload_module):
ui_layout = reload_module("ui_layout")
demo = ui_layout.create_ui_blocks()
try:
cfg = demo.get_config_file()
assert cfg.get("theme") == "default"
assert cfg.get("head") == ui_layout.THEME_LOCK_HEAD
elem_ids = {
comp.get("props", {}).get("elem_id")
for comp in cfg.get("components", [])
if comp.get("props", {}).get("elem_id")
}
required_ids = {
"header_task",
"main_layout_row",
"media_card",
"log_card",
"right_top_row",
"right_action_col",
"right_log_col",
"control_panel_group",
"video_phase_group",
"execution_video_group",
"action_phase_group",
"demo_video",
"execute_video",
"watch_demo_video_btn",
"live_obs",
"action_radio",
"coords_box",
"exec_btn",
"reference_action_btn",
"restart_episode_btn",
"next_task_btn",
}
missing = required_ids - elem_ids
assert not missing, f"missing required elem_ids: {sorted(missing)}"
values = [
comp.get("props", {}).get("value")
for comp in cfg.get("components", [])
if "value" in comp.get("props", {})
]
assert all("_anchor" not in str(v) for v in values)
assert all(
"Logging in and setting up environment... Please wait." not in str(v)
for v in values
)
assert all("Loading environment, please wait..." not in str(v) for v in values)
assert "The episode is loading..." in ui_layout.PROGRESS_TEXT_REWRITE_JS
assert ui_layout.UI_TEXT["progress"]["entry_rejected"] == "Too many users are trying the demo right now. Please try again later."
log_output_comp = next(
comp
for comp in cfg.get("components", [])
if comp.get("props", {}).get("elem_id") == "log_output"
)
assert log_output_comp.get("props", {}).get("max_lines") is None
demo_video_comp = next(
comp
for comp in cfg.get("components", [])
if comp.get("props", {}).get("elem_id") == "demo_video"
)
assert demo_video_comp.get("props", {}).get("autoplay") is False
execute_video_comp = next(
comp
for comp in cfg.get("components", [])
if comp.get("props", {}).get("elem_id") == "execute_video"
)
assert execute_video_comp.get("props", {}).get("autoplay") is True
component_types = [comp.get("type") for comp in cfg.get("components", [])]
assert "timer" not in component_types
api_names = [dep.get("api_name") for dep in cfg.get("dependencies", [])]
assert "on_demo_video_play" in api_names
assert "on_execute_video_end_transition" in api_names
assert "precheck_execute_inputs" in api_names
assert "switch_to_execute_phase" in api_names
assert "execute_step" in api_names
assert "refresh_live_obs" not in api_names
finally:
demo.close()
|