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.