"""UI tests: design fidelity, escaping, and the action bridge. The fidelity tests here are the cheap half of the check -- they assert the stylesheets reach the page and the design's own values are used. The other half (measuring the rendered page in a browser) cannot run in CI and is done by hand against the deployed Space. """ from __future__ import annotations from pathlib import Path import pytest from src import atlas from bit_ui import bridge, icons, theme from src.ui import chrome, shell from tests.conftest import make_row # -------------------------------------------------------------------------- # The design system's stylesheets must actually reach the page # -------------------------------------------------------------------------- # # This is the guard the design-port notes ask for: it is easy to vendor the # CSS files and then wire up only some of them, which leaves the app looking # *approximately* right in a way that is hard to name. Each assertion is keyed # on a rule only that file contains. @pytest.mark.parametrize("marker,source", [ ("--bg-canvas", "colors.css"), ("--text-2xs", "typography.css"), ("--space-", "spacing.css"), ("border-radius", "base.css"), ]) def test_every_design_stylesheet_reaches_the_page(marker, source): css = theme.full_css() assert marker in css, f"{source} did not reach the page (missing {marker})" def test_fonts_are_declared(): css = theme.full_css() assert "@font-face" in css assert "Styrene A" in css assert "Mac Minecraft" in css def test_theme_uses_the_designs_dense_type_scale(): """Gradio's 16px default would be a full step too large everywhere.""" built = theme.bit_theme() assert built.body_text_size == "10px" assert built.block_radius == "0px" def test_bridge_transport_elements_are_hidden_not_removed(): """`visible=False` would delete them from the DOM and break the bridge.""" css = theme.full_css() assert "#bit-action" in css and "#bit-trigger" in css assert "clip:rect(0,0,0,0)" in css.replace(" ", "") # -------------------------------------------------------------------------- # Escaping -- model cards are written by strangers # -------------------------------------------------------------------------- XSS = '' def test_red_flags_are_escaped_in_badges(): row = make_row("evil/model", red_flags=[XSS]) html = shell._badges(row) assert "', red_flags=[XSS], training_data_summary=XSS) built = atlas.Index(pd.DataFrame([nasty])) built.dataset_repo = "x/y" state = atlas.default_state() view = {"rows": built.rows, "hidden": 0, "tape": [], "trending": [], "links": {}} html = shell.page(built, state, view) assert "" not in html assert ", an element that forces height from vh feeds back into the height the parent sets, and ratchets. This is the check that keeps it fixed. """ from bit_ui import nav as bit_nav state = dict(atlas.default_state(), sel="ProsusAI/finbert") view = {"rows": index.rows, "matched": len(index.rows), "truncated": 0, "hidden": 1, "tape": [], "trending": [], "links": {}, "nav": bit_nav.default_document(), "palette_groups": []} assert theme.find_forced_vh(shell.page(index, state, view)) == [] def test_gradio_own_main_padding_is_reset(): """Gradio ships a second
with padding:16px 32px around ours.""" css = chrome.full_css() assert "main.fillable" in css def test_sidebar_toggle_costs_no_round_trip(index): """Collapsing is a client-side attribute flip, not a server action. Every action re-renders the whole page: 1.16 MB here, 95% of it the model table. Putting that behind a purely visual toggle measured at 1.5-2.2s. """ from bit_ui import nav as bit_nav view = {"rows": [], "matched": 0, "truncated": 0, "hidden": 0, "tape": [], "trending": [], "links": {}, "nav": bit_nav.default_document(), "palette_groups": []} html = shell.page(index, atlas.default_state(), view) assert "data-bit-sidebar-toggle" in html assert "sidebar:toggle" not in html assert "sidebar" not in chrome.ALLOWED_KEYS, ( "the sidebar action is back on the allow-list") def test_header_and_sidebar_are_sticky(index): from bit_ui import nav as bit_nav css = chrome.full_css() assert ".bit-header" in css and "position: sticky" in css view = {"rows": [], "matched": 0, "truncated": 0, "hidden": 0, "tape": [], "trending": [], "links": {}, "nav": bit_nav.default_document(), "palette_groups": []} assert 'class="bit-header"' in shell.page(index, atlas.default_state(), view) def test_search_bar_is_live_not_enter_only(index): """The bug: fields sent `key=value`, which parse_action drops on the floor, so the search box did nothing at all from the browser.""" html = shell.title_row(index, atlas.default_state(), shown=5) assert 'data-bit-live="q"' in html assert "⌘K" in html def test_every_chrome_action_is_on_the_allow_list(index): """The sidebar and dialogs emit through this Space's emitter.""" import re from bit_ui import dialogs as bit_dialogs from bit_ui import nav as bit_nav doc = bit_nav.default_document() html = "".join([ shell.page(index, atlas.default_state(), {"rows": [], "matched": 0, "truncated": 0, "hidden": 0, "tape": [], "trending": [], "links": {}, "nav": doc, "palette_groups": []}), bit_dialogs.contact(doc, {"contact_form_open": True}, chrome.emit), bit_dialogs.coming_soon(bit_nav.find(doc, "Dispatch"), doc, chrome.emit), ]) emitted = set(re.findall(r'data-bit="([^:"]+):', html)) emitted |= set(re.findall(r'data-bit-(?:input|live)="([^="]+)"', html)) unknown = emitted - chrome.ALLOWED_KEYS assert not unknown, f"chrome emits actions the bridge rejects: {unknown}" def test_the_app_serves_this_spaces_own_css_not_just_the_shared_css(): """`theme.full_css()` is bit-ui's CSS only and silently drops the Atlas's. This shipped once: the table had just been converted to CSS classes whose rules live in ATLAS_CSS, and none of them reached the page. Everything still rendered, just unstyled -- exactly the kind of break that looks like a design regression rather than a wiring mistake. """ import app as module css = module.chrome.full_css() for marker in (".bit-row", ".bit-header", ".bit-cell", ".bit-tag"): assert marker in css, f"{marker} is missing from the app's CSS" source = (Path(module.__file__).read_text()) assert "css=chrome.full_css()" in source, ( "app.py is not serving this Space's CSS") assert "css=theme.full_css()" not in source def test_every_class_the_table_renders_has_a_rule(): """A class with no rule is invisible styling debt.""" import re import app as module from bit_ui import nav as bit_nav index = module.INDEX css = module.chrome.full_css() state = atlas.default_state() view = {"rows": index.rows[:3], "matched": 3, "truncated": 0, "hidden": 0, "tape": [], "trending": [], "links": {}, "nav": bit_nav.default_document(), "palette_groups": []} html = shell.page(index, state, view) rendered = set() for attr in re.findall(r'class="([^"]+)"', html): rendered.update(c for c in attr.split() if c.startswith("bit-")) missing = sorted(c for c in rendered if f".{c}" not in css) assert not missing, f"classes rendered with no CSS rule: {missing}"