login and internalUserIdentity used an unscoped "Virtual Keys" text check that now also matches the top-bar breadcrumb, and adminSettings navigated via antd menuitem roles the shadcn nav no longer emits. Scope these to the sidebar's complementary landmark and drive the Settings group by role (expand the button, then click the child link), matching the fixes already applied to the migration and navigation specs
The e2e runs against the real proxy, so a contract drift already fails the test at
runtime; tsc only checks the spec against schema.d.ts, a generated snapshot, so a
backend change with a stale snapshot would pass tsc while the live test still
catches it. The dedicated tsconfig + script + CI step were circular ceremony for
that. Keep the zero-runtime-cost type-only import, which still catches mistakes in
the editor, and make its comment honest about what enforces the contract.
Address an adversarial review of the Loadbalancing e2e:
- The "typed against the backend schema" claim was hollow: nothing type-checked
e2e_tests (the root tsconfig excludes it and no CI step runs tsc), so a
contract drift would compile and run unchanged. Add e2e_tests/tsconfig.json, a
typecheck:e2e script, and a CircleCI step so the schema typing actually gates.
- The two describe blocks both mutate the proxy's shared router_settings, and the
Loadbalancing save echoes the whole settings object, so they could clobber each
other under local fullyParallel. Run the file serially.
- patchRouterSettings swallowed a failed seed, which surfaced later as a
misleading UI timeout. Assert the write succeeded, and rely on the server-side
merge instead of echoing the whole settings object back (drops a cast and a GET).
- Empty routing_groups already reproduces the bug, so drop the non-empty seed and
its model coupling.
Drives the real save flow against a live proxy: seeds a present routing_groups
array (the LIT-4057 trigger) via the typed /config/update contract, changes
num_retries on the Loadbalancing tab, and asserts the POST returns 200 instead
of 422, the success toast appears, and the value still shows after a reload (the
ticket's "refresh shows old values" symptom). The round-trip is typed against the
OpenAPI-generated backend schema (ConfigYAML write, RouterSettingsResponse read)
through a type-only import, so a backend contract drift fails the type check.
* test(e2e): cover add-fallback flow in Router Settings as proxy admin
The Router Settings → Fallbacks → Add Fallbacks flow was an uncovered
manual-QA path. This adds a test that opens the modal, picks a primary
+ fallback from the seeded mock models, saves, and verifies both render
in the fallback table.
* fix(e2e): make router-fallback test idempotent and pick antd options by text
- Match `.ant-select-item-option` by text instead of `getByTitle(...)` —
FallbackGroupConfig uses `options=` (not <Select.Option> children), so
no `title` attribute is emitted and the title-based selector hangs.
- Add before/after hooks that wipe any fallback for fake-openai-gpt-4 via
/config/update so retries and local reruns don't trip on leftover state.
- Tighten the success assertion to a single tbody row containing BOTH the
primary and the fallback names — pre-existing rows can no longer
vacuously satisfy the check.
- Fix the stale "Three tabs" comment to "Four tabs".
Addresses Greptile P2s on PR #29069.
* fix(e2e): keyboard-select fallback models + correct cleanup endpoint
- Replace mouse-based option clicks with click-to-focus + type + Enter.
FallbackGroupConfig's Selects use `options=` and a custom
getPopupContainer, so locating options via `.ant-select-dropdown`
hit several races: DOM-clicks left antd's popup state stale (the
primary popup then intercepted the fallback click), `getByRole`
matched always-mounted hidden options, and pointer stability fought
the open animation. Typing into the showSearch input narrows the
listbox to one option and Enter selects it cleanly.
- Assert on dialog-side state changes (the active tab adopts the
primary model name; the chain helper shows "1/10 used") instead of
popup contents — these reflect the actual selection landing.
- Cleanup helper now hits /get/config/callbacks (the real endpoint;
/get/callbacks returns 404), so the before/after reset actually
clears prior router_settings.fallbacks state.