test(web): remove template-shape assertions and unused logo

This commit is contained in:
SToneX
2026-09-23 12:24:41 +08:00
parent b9c2ddd5e0
commit ef0550cadf
11 changed files with 13 additions and 1386 deletions
+1 -2
View File
@@ -491,7 +491,6 @@ Regenerate via `scripts/build-map.py`.
| `tests/test_catalog_api.py` | architecture/catalog.md |
| `tests/test_catalog_validate.py` | architecture/catalog.md |
| `tests/test_cli_key_compatibility.py` | interface/cli.md |
| `tests/test_dashboard_markup.py` | architecture/auth-secrets.md |
| `tests/test_dashboard_rollout.py` | interface/dashboard.md |
| `tests/test_dataforseo_constraints.py` | architecture/catalog.md |
| `tests/test_enrich_arena.py` | interface/enrich-arena.md |
@@ -533,7 +532,7 @@ Regenerate via `scripts/build-map.py`.
|---|---|
| `architecture/ads-conversions.md` | `adsconv.py`, `signup.py`, `adtrack.js`, `gtag.js` |
| `architecture/archive.md` | `archive.py`, `hunter.yaml`, `results.py`, `0031_archive_result_admission.py`, `test_cache_result_admission.py`, `archive_bodies.py`, `config.py`, `object_store.py`, `0032_archive_body_storage.py`, `test_archive_r2.py`, `fake_object_store.py`, `smoke_archive_r2.py`, `0002_archive_tables.py`, `0003_callrecord_cached.py`, `0004_archivekey_request_shape.py`, `0011_callrecord_archive_link.py`, `service.py`, `settle.py`, `0039_archive_own_key_and_repeat_pricing.py`, `backfill_call_archive_links.py`, `api.py`, `bootstrap.py`, `admin.py`, `asynctasks.py` |
| `architecture/auth-secrets.md` | `injectors.py`, `ssrf.py`, `crypto.py`, `oauth.py`, `__init__.py`, `authorization.py`, `oauth_flow.py`, `refresh.py`, `oauth_exchange.py`, `oauth_refresh.py`, `oauth_providers.py`, `session.js`, `keys.js`, `TeamPage.vue`, `health.py`, `connect.py`, `connections.py`, `resources.py`, `__init__.py`, `bindings.py`, `bundles.py`, `api_keys.py`, `access.py`, `api_keys.py`, `test_api_keys.py`, `test_oauth_refresh.py`, `test_financialdatasets.py`, `test_key_providers.py`, `test_dashboard_markup.py`, `config.py` |
| `architecture/auth-secrets.md` | `injectors.py`, `ssrf.py`, `crypto.py`, `oauth.py`, `__init__.py`, `authorization.py`, `oauth_flow.py`, `refresh.py`, `oauth_exchange.py`, `oauth_refresh.py`, `oauth_providers.py`, `session.js`, `keys.js`, `TeamPage.vue`, `health.py`, `connect.py`, `connections.py`, `resources.py`, `__init__.py`, `bindings.py`, `bundles.py`, `api_keys.py`, `access.py`, `api_keys.py`, `test_api_keys.py`, `test_oauth_refresh.py`, `test_financialdatasets.py`, `test_key_providers.py`, `config.py` |
| `architecture/catalog.md` | `fishaudio.yaml`, `fishaudio.tts.s2-1-pro.json`, `fishaudio.voices.create.json`, `fishaudio.voices.discover.json`, `provider_resources.py`, `provider_resources.py`, `provider_resources.py`, `tavily.yaml`, `exa.yaml`, `anyapi.extended.yaml`, `trestleiq.yaml`, `financialdatasets.yaml`, `test_financialdatasets.py`, `quickenrich.yaml`, `influencersclub.yaml`, `quickenrich.extended.yaml`, `trykitt.yaml`, `contracts.yaml`, `millionverifier.yaml`, `adapters.yaml`, `prospeo.yaml`, `test_route_cost_ceiling.py`, `tomba.yaml`, `__init__.py`, `contracts.py`, `paths.py`, `plan.py`, `synthetic.py`, `route.py`, `test_routing.py`, `catalog-drift.yml`, `catalog_drift.py`, `catalog_ingest.py`, `catalog_validate.py`, `aliases.yaml`, `fx.yaml`, `cloro.yaml`, `aviato.yaml`, `crustdata.yaml`, `google-search-console.yaml`, `google-search-console.extended.yaml`, `google-tag-manager.yaml`, `google-tag-manager.extended.yaml`, `instagram.yaml`, `instagram.extended.yaml`, `justoneapi.extended.yaml`, `minimax.yaml`, `apify.yaml`, `brightdata.yaml`, `companyenrich.yaml`, `oceanio.yaml`, `akta.extended.yaml`, `dataforseo.yaml`, `dataforseo.extended.yaml`, `test_dataforseo_constraints.py`, `scrapecreators.yaml`, `scrapecreators.extended.yaml`, `serpapi.yaml`, `serpapi.extended.yaml`, `diffbot.yaml`, `diffbot.extended.yaml`, `tikhub.extended.yaml`, `lusha.extended.yaml`, `openrouter.yaml`, `openrouter.extended.yaml`, `replicate.yaml`, `replicate.extended.yaml`, `reapi.yaml`, `piapi.yaml`, `__init__.py`, `store.py`, `hunter.yaml`, `mcp.py`, `settlement.py`, `stats.py`, `catalog_observations.py`, `catalog_stats.py`, `0038_endpoint_day_stats.py`, `catalog.py`, `test_aigc_pr_b.py`, `test_catalog_api.py`, `test_catalog_validate.py` |
| `architecture/composition.md` | `bootstrap.py`, `bootstrap_handlers.py`, `bootstrap_http.py`, `call_surface.py`, `connect.py`, `mcp_oauth.py`, `session.py`, `admin.py`, `auth.py`, `billing.py`, `call.py`, `connections.py`, `onboard.py`, `orgs.py`, `resources.py`, `referrals.py`, `web.py`, `dump_surface.py`, `test_app_roles.py` |
| `architecture/data-model.md` | `0042_pinned_read_scope.py`, `alembic.ini`, `env.py`, `0001_baseline_current_schema.py`, `0002_archive_tables.py`, `0003_callrecord_cached.py`, `0004_archivekey_request_shape.py`, `0005_capacity_policy_snapshot.py`, `0006_overflow_route.py`, `0007_overflow_spend.py`, `0008_org_platform_overflow_disabled.py`, `0009_callrecord_hit.py`, `0017_async_task_record.py`, `0018_async_resource_ownership.py`, `0019_async_poll_failures.py`, `0020_callrecord_created_at_indexes.py`, `0021_ledgerentry_org_created_at_index.py`, `0022_org_spent_today_counter.py`, `0023_callrecord_org_user_created_at_index.py`, `0024_membership_calls_today_counter.py`, `0027_enrich_arena.py`, `0028_arena_insights.py`, `0029_arena_verification_snapshot.py`, `0011_callrecord_archive_link.py`, `0015_idempotentcall_membership_cascade.py`, `0034_managed_api_keys.py`, `0035_default_key_generation.py`, `0036_activity_key_indexes.py`, `0038_endpoint_day_stats.py`, `maintenance.py`, `sitetrack.js`, `models.py`, `0031_archive_result_admission.py`, `0032_archive_body_storage.py`, `0039_archive_own_key_and_repeat_pricing.py`, `0043_provider_resources.py`, `provider_resources.py`, `provider_resources.py`, `0033_signup_promo_eligibility.py`, `0041_searchlog.py`, `timeutil.py`, `db.py`, `referrals.py`, `audit.py`, `analytics.py`, `bootstrap_handlers.py`, `ratestore.py`, `auth.py`, `test_postgres_reset.py`, `test_alembic_expand_safety.py`, `test_api_keys.py` |
@@ -30,7 +30,6 @@ sources:
- tests/test_oauth_refresh.py
- tests/test_financialdatasets.py
- tests/test_key_providers.py
- tests/test_dashboard_markup.py
- src/treg/config.py
related:
- architecture/proxy-model.md
+4 -26
View File
@@ -988,32 +988,10 @@ line rather than an empty table. `.prm-t` explicitly resets the global `table`/`
background, border, radius, filled header bar), which otherwise reads as a stray highlight inside the
`.prm` box and clips the first column against the table's own border. Navigation runs both ways: an integration page carries a
**Covered in the catalog** chip row (`mkPlatforms`) into the platform pages, and each platform page
header links back out to the providers that serve it (`platProviders`). `tests/test_dashboard_markup.py`
pins this provider navigation to the platform response itself; it does not disappear while the
separate OAuth connection registry is still loading. The same test
locks the structure (top-level view, the row/detail `<template>` pair inside the `.ttable`, the
`v-if`'d tab bar and its `platform` fallback, the derived tab list and category order, tiles wearing the
platform's own logo with the generated-initial fallback, the `Platform` tab still carrying the provider
shelves and their connect flow, the category heading being a real heading, the card's four regions
(mark + name + category, the connected-state corner, the count/price footer — and NO summary
paragraph, with the name wrapping instead of ellipsising), the
unified-USD price rule (server `usd`, no local FX constant, native suffix, `{}`-normalisation,
`quota_rows` excluded first) and its unmetered-OAuth-only "free with your account" branch,
the runnable green on all three of its surfaces, the stacked platform header, the always-both
provider/endpoint counts, the credit-priced fallback ranking ahead of "price not published",
the parameters block sitting before the example
toggle with its query/path/body order and its no-params fallback,
the featured-shelf split and its two guards, the ledger being one table
with `other`-last domain sections that need a visible row to exist, the single platform-wide Actions
section holding every management endpoint, and merged-before-single rows, a row title that is a name or a clipped
summary and never a paragraph, the collapsed merged row's non-wrapping three-pills-and-a-count strip, its pills being per-provider,
sorted cheapest-first and priced only when the price is a real number,
the two-level expansion (provider sub-rows, then one detail block shared with the single-row path), the
long metered phrasing never reaching a collapsed line, the filter bar's three controls and their chip
counts, both sticky layers and the overflow rules that let them stick, the two-tab expansion (Request first, no response tab at
all without an example, both panes capped at 320px), the prominent Connect in the tab bar with its
Connected state, the `treg call` line and the provider facts, the cross-currency cheapest rules, the credit-priced "see provider" fallback, the scope
chips, and lazy examples). `tests/test_catalog_api.py` locks the server half: the section order, the
header links back out to the providers that serve it (`platProviders`). Provider navigation derives
from the platform response itself, so it remains available while the separate OAuth connection
registry loads. Browser tests in `frontend/e2e/` cover navigation and interactions; they do not pin
CSS classes or template source spelling. `tests/test_catalog_api.py` locks the server half: the section order, the
merged/single split, the domain resolution ladder, and a delivery-mode path segment never becoming a
subject.
+2 -5
View File
@@ -242,11 +242,8 @@ on a public shelf renders as its bare slug and the whole action chain collapses
`mkOauth` has no public fallback — the open response carries no `auth_kind` — so the public branch
offers BYOK, which is true for every provider, rather than guessing Connect.
**Each action is ONE button whose handler forks on `publicCatalog`**, not a duplicated public
template. `tests/test_dashboard_markup.py` asserts the member chain's exact shape
(`v-else-if="mkOauth(e.provider)" class="btn sm primary"`, `openProvider(e.provider)`, …), and a
fork keeps those substrings intact where a parallel branch drifts. That test reads a fixed-size
window of the markup and has already been outgrown once by these forks.
Each catalog action chooses sign-in or the member flow based on `publicCatalog`. Browser coverage
in `frontend/e2e/dashboard.spec.ts` checks public catalog navigation and reachable sign-in.
### The no-JS fallback
+3
View File
@@ -42,6 +42,9 @@ npm --prefix frontend run test:e2e
uv build
```
Test behavior, not template source strings, CSS class names or component arrangement. Keep transport
unit tests and HTTP rollout/packaging checks; use browser tests for user interactions.
Browser tests start their own server on :18791 with a disposable database and no dotenv file.
They use full Chromium in headless mode so back/forward cache restoration is exercised.
`PLAYWRIGHT_CHANNEL=chrome` can use an installed Chrome for local checks.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 306 KiB

-34
View File
@@ -1,34 +0,0 @@
"""Read the authored dashboard for existing source-level regression checks.
Component templates are expanded at their actual mount sites, preserving conditional ancestry.
Runtime navigation and event bindings are covered separately by the browser suite.
"""
from pathlib import Path
import re
FRONTEND = Path(__file__).resolve().parents[1] / "frontend" / "src"
def template_source(path: Path) -> str:
source = path.read_text()
template = source.split("<template>", 1)[1].rsplit("</template>", 1)[0]
imports = re.findall(r"import (\w+) from ['\"](.+?\.vue)['\"]", source)
for name, relative in imports:
child = template_source((path.parent / relative).resolve())
template = re.sub(
rf"<{name}\b([^>]*?)/>",
lambda match: "<template" + (" " + match[1].strip() if match[1].strip() else "") + ">" + child + "</template>",
template,
)
return template
def dashboard_source() -> str:
state = FRONTEND / "state"
computed = "\n".join(p.read_text() for p in sorted(state.glob("*Computed.js")))
methods = "\n".join(p.read_text() for p in sorted(state.glob("*.js")) if not p.stem.endswith("Computed"))
return (
(FRONTEND / "styles/base.css").read_text()
+ template_source(FRONTEND / "App.vue")
+ "\ncomputed:{\n" + computed + "\nmethods:{\n" + methods
)
File diff suppressed because it is too large Load Diff
-5
View File
@@ -1009,11 +1009,6 @@ async def test_arena_and_dashboard_share_setup_components(clients):
page = (await clients.get('/enrich-arena')).text
dashboard = (await clients.get('/app')).text
assert '/agent-setup.js' in page and '/agent-setup.js' in dashboard
from dashboard_source import FRONTEND
assert 'treg-setup-instructions' in page
assert 'treg-setup-instructions' in (FRONTEND / 'dialogs/WelcomeDialog.vue').read_text()
assert "app.component('TregSetupInstructions', setup.SetupInstructions!)" in (FRONTEND / 'main.ts').read_text()
assert 'Setup treg in' in page and 'ref="setupDialog"' in page
def test_discovery_public_cohorts_keep_all_requested_constraints():
+3 -10
View File
@@ -47,17 +47,10 @@ async def test_auth_me_user_hash_is_hmac_of_the_email(clients, monkeypatch):
assert "s3cret" not in r.text # the secret itself never leaves the server
def test_pages_gate_on_meta_app_id():
from dashboard_source import FRONTEND
assert "intercom_app_id" in (FRONTEND / "state/analytics.js").read_text()
# each Intercom-bearing page keys its loader off /meta's intercom_app_id (empty = inert)
for page in ("landing.html", "support.html"):
assert "intercom_app_id" in (WEB / page).read_text(), page
def test_no_hardcoded_workspace_id_anywhere():
# the only allowed form of the widget URL is the config-driven concatenation
pat = re.compile(r"widget\.intercom\.io/widget/(?!'\+app)")
for f in WEB.rglob("*"):
if "dashboard" not in f.relative_to(WEB).parts and f.is_file() and f.suffix in {".html", ".js", ".md", ".txt"}:
sources = [*WEB.rglob("*"), *(WEB.parents[2] / "frontend" / "src").rglob("*")]
for f in sources:
if "dashboard" not in f.parts and f.is_file() and f.suffix in {".html", ".js", ".md", ".txt"}:
assert not pat.search(f.read_text()), f"hardcoded Intercom workspace id in {f.name}"
-49
View File
@@ -347,55 +347,6 @@ def test_no_shelf_is_published_that_the_app_grid_hides():
"publish /catalog/<slug> for each while the app's tile grid hides them")
# -------------------------------------------------------------------- public-mode chrome & CTAs
# Markup assertions rather than behaviour: these live in index.html's Vue template, which the test
# suite reads as text (see tests/test_dashboard_markup.py). Both were reported from the browser.
def _spa() -> str:
from dashboard_source import dashboard_source
return dashboard_source()
def test_public_catalog_drops_the_workspace_chrome():
"""A catalog visitor is reading a website, not operating an app. The org switcher, the global
tool search and the member nav are furniture for a job they have not started."""
spa = _spa()
assert '<template v-if="publicCatalog">' in spa # marketing nav instead
member_header = '<header class="rd-top" >'
assert member_header in spa # app bar only for members
header = spa.split(member_header, 1)[1].split('</header>', 1)[0]
assert 'class="orgblock"' in header and 'class="rd-navs"' in header
assert 'v-if="!publicCatalog && (view===\'tools\'||view===\'resources\'||view===\'connections\')"' in spa
assert 'v-if="authed && !publicCatalog" class="rd-referral"' in spa
assert '.layout.solo{grid-template-columns:minmax(0,1fr)}' in spa # main spans the full width
def test_no_public_cta_navigates_to_a_page_that_bounces():
"""/app sends a logged-out visitor straight back to the landing (`location.replace('/')`), so a
CTA pointing there is a dead end that loses the page they were reading. Every one of them opens
the sign-in modal in place instead."""
spa = _spa()
assert "location.href='/app'" not in spa
assert spa.count("publicCatalog ? openSignin()") >= 5 # try-it, connect, byok ×3, chips
def test_the_signin_modal_is_reachable_from_public_mode():
"""It used to live inside the logged-out landing branch, which public mode does not render —
so there was nothing for a CTA to open."""
spa = _spa()
lp = spa.index('class="lp"')
modal = spa.index('<div class="lc-scrim"')
shell = spa.index("<template v-else>")
assert not (lp < modal < shell), "the modal is trapped inside the logged-out landing branch"
def test_the_modal_does_not_talk_about_a_sandbox_on_the_catalog():
"""Default copy is the sandbox's ('bring it into a real account') — nonsense to someone who
arrived from a search result."""
spa = _spa()
assert 'v-else-if="publicCatalog" class="sub">Verify your new account' in spa
async def test_no_page_ships_an_unsubstituted_base(clients: AsyncClient):
"""`{BASE}` reaching a browser means a canonical or og:url is pointing at nothing."""
for path in ("/", "/support", "/terms", "/privacy", "/tutorial", "/catalog"):