Rows were 57px against the decisions table's 36px, which is the other
scanning surface over hundreds of rows. Two things set that height and
only fixing one would have moved it barely: 24px of td padding, and a
32px override <select>. Both come down; the row is now 31px.
The space that buys is spent on the four facts a routing decision
actually turns on, all already in /admin/api/models -- no API change:
Ctx effective_context_window, the hard filter that 422s
$/1M out the completion price profiles filter on
Prof mean proficiency, with /N and the per-category breakdown
in the title -- a bare mean would imply uniform competence,
which is the one thing the table disproves
Caps T/V/J/R chips, reusing the decisions page's flag language
The Ctx column earned its place immediately: 12 of 30 active OpenRouter
rows read 0 and have never been selected across 23,000+ decisions.
Fixed separately.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VRQXz5SYZYVWscxS1QqF6U
152 lines
6.1 KiB
Python
152 lines
6.1 KiB
Python
"""The models page has to be usable at 446 rows, not just at 45.
|
|
|
|
It shipped as one ungrouped table of every routable model with a single
|
|
"Show deprecated / stale" switch. That is workable while the catalog is
|
|
NeuralWatt-only; with OpenRouter allowlisted the table is 440 rows and the
|
|
switch is an all-or-nothing control over the only axis it offers.
|
|
|
|
Static checks on the source, as with the allowlist filter tests -- this repo
|
|
has no DOM harness. Behaviour was verified in a browser: filters compose
|
|
(45 routable -> 14 neuralwatt -> 7 at tier 3), search types forward with the
|
|
caret intact, paging walks 9 pages of 50, and changing a filter returns to
|
|
page 1.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import re
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
SRC = (Path(__file__).resolve().parent.parent
|
|
/ "admin" / "frontend" / "models.html").read_text(encoding="utf-8")
|
|
|
|
|
|
def _function_body(name: str) -> str:
|
|
match = re.search(rf"^(?:async )?function {re.escape(name)}\(.*?^\}}",
|
|
SRC, re.S | re.M)
|
|
assert match, f"{name}() not found in models.html"
|
|
return match.group(0)
|
|
|
|
|
|
def _strip_comments(text: str) -> str:
|
|
text = re.sub(r"/\*.*?\*/", "", text, flags=re.S)
|
|
return "\n".join(ln for ln in text.split("\n")
|
|
if not ln.strip().startswith("//"))
|
|
|
|
|
|
@pytest.mark.parametrize("control", [
|
|
"mf-search", "mf-provider", "mf-tier", "mf-availability",
|
|
"mf-page-size", "mf-clear", "mf-prev", "mf-next",
|
|
])
|
|
def test_every_filter_control_exists(control):
|
|
assert f'id="{control}"' in SRC
|
|
|
|
|
|
def test_the_old_all_or_nothing_toggle_is_gone():
|
|
"""Availability is a select now -- 'show deprecated' could not express
|
|
'show me only the stale ones', which is what auditing an override needs."""
|
|
assert 'id="show-deprecated-toggle"' not in _strip_comments(SRC)
|
|
|
|
|
|
def test_filters_compose_rather_than_override():
|
|
"""Each axis narrows independently; matchesModelFilters returns false on
|
|
the first miss rather than picking a winner."""
|
|
body = _function_body("matchesModelFilters")
|
|
for axis in ("f.availability", "f.provider", "f.tier", "f.q"):
|
|
assert axis in body, f"{axis} is not consulted"
|
|
|
|
|
|
def test_routable_is_the_default_view():
|
|
"""The page is usually open to answer 'what can the router pick now'."""
|
|
assert '<option value="routable">Routable only</option>' in SRC
|
|
body = _function_body("matchesModelFilters")
|
|
assert "'routable'" in body
|
|
|
|
|
|
def test_the_page_is_paginated():
|
|
render = _function_body("renderModels")
|
|
assert "_modelPageSize" in render
|
|
assert "slice(start, start + _modelPageSize)" in render
|
|
|
|
|
|
def test_changing_a_filter_returns_to_page_one():
|
|
"""Otherwise a narrowed result can land on an empty page."""
|
|
bind = _function_body("bindModelFilters")
|
|
assert "_modelPage = 1" in bind
|
|
|
|
|
|
def test_the_count_names_the_window_and_the_whole():
|
|
"""'31 of 446' is a filter result; '446' alone is a claim about the
|
|
catalog. Same rule as the decisions page."""
|
|
render = _function_body("renderModels")
|
|
assert "of ${eligible.length} models" in render
|
|
|
|
|
|
def test_the_pager_hides_itself_on_a_single_page():
|
|
render = _function_body("renderModels")
|
|
assert "totalPages > 1" in render
|
|
|
|
|
|
def test_filter_controls_are_bound_once_not_re_rendered():
|
|
"""The providers page reversed typed text by rebuilding the input on
|
|
every keystroke and re-focusing it, which reset the caret to 0. These
|
|
controls are static markup, bound once at init."""
|
|
init = _function_body("init")
|
|
assert "bindModelFilters()" in init
|
|
render = _strip_comments(_function_body("renderModels"))
|
|
for control in ("mf-search", "mf-provider", "mf-tier", "mf-availability"):
|
|
assert f'"{control}"' not in render, (
|
|
f"renderModels rebuilds {control}; a keystroke would destroy it"
|
|
)
|
|
|
|
|
|
def test_the_provider_list_is_derived_from_the_catalog():
|
|
"""Hard-coding provider names would go stale the moment one is added."""
|
|
body = _function_body("refreshProviderOptions")
|
|
assert "new Set(models.map" in body
|
|
|
|
|
|
@pytest.mark.parametrize("column", ["Ctx", "$/1M out", "Prof", "Caps"])
|
|
def test_the_decision_relevant_columns_are_present(column):
|
|
"""The four facts a routing decision actually turns on: the context
|
|
ceiling that produces a 422, the completion price profiles filter on,
|
|
the proficiency term that is the only category-dependent part of the
|
|
ranking, and the capability gates that hard-filter a request. All four
|
|
already ship in /admin/api/models -- none needed an API change."""
|
|
assert f">{column}<" in SRC
|
|
|
|
|
|
def test_proficiency_shows_a_mean_and_keeps_the_breakdown_reachable():
|
|
"""A bare mean would imply uniform competence, which is the exact thing
|
|
the proficiency table disproves -- deepseek-v4-flash is 1.00 on coding
|
|
and 0.33 on tool use. The per-category detail stays in the title."""
|
|
body = _function_body("proficiencyCell")
|
|
assert "title=" in body
|
|
assert "entries.length" in body, "the sample count must be visible too"
|
|
|
|
|
|
def test_row_density_matches_the_decisions_table_approach():
|
|
"""Both are scanning surfaces over hundreds of rows, so both trade
|
|
card-table's comfortable spacing for smaller type AND tighter padding.
|
|
Measured: 57px before, 31px after, against decisions' 36px."""
|
|
assert "#model-tbody td, thead th{padding-top:.2rem!important" in SRC
|
|
assert "#model-tbody{font-size:.72rem}" in SRC
|
|
# The override select was 32px and set the floor on row height; shrinking
|
|
# only the padding would have moved the row by almost nothing.
|
|
assert "#model-tbody .model-override{height:24px" in SRC
|
|
|
|
|
|
def test_empty_states_span_every_column():
|
|
"""A stale colspan leaves the empty-state message boxed into part of the
|
|
row, which reads as a broken table rather than an empty one."""
|
|
assert 'colspan="5"' not in SRC
|
|
assert SRC.count('colspan="9"') >= 2
|
|
|
|
|
|
def test_the_page_still_requests_the_unfiltered_catalog():
|
|
"""The availability filter needs the deprecated rows present to show
|
|
them; this is the one caller that passes include_unroutable."""
|
|
assert "include_unroutable=true" in _function_body("loadModels")
|