phase: 104_chip_sizing_question_cap
All completion criteria verified. Final report: **Phase 104 — final verification pass: all green** - Verified (no code changes needed): single-line ellipsized `.suggestion-chip` CSS + deleted `.maybe-try` override, `renderChips` full-text `title` + `aria-label`-when-clipped, `maxlength="4000"` + `#char-count` counter + `handleSend` over-cap guard, unit pins file, schemas boundary pins, dedicated E2E suite. - E2E (isolation): `uv run pytest tests/e2e/test_chip_sizing_question_cap.py -v --no-cov` → **6 passed**; regressions: `test_suggestion_chips.py` 8 passed, `test_pinned_composer.py` 4 passed, `test_responsive_polish.py` 7 passed, `test_chat_history.py` 5 passed. - `uv run pytest` → **2102 passed**; `--cov=app` → **99%** (>90%); `uv run ruff check . && uv run pyright` → clean, 0 errors. - Criteria: chip E2E (single-line, clipped, title+aria-label full text) ✅; paste caps at exactly 4,000, send streams, counter hides ✅; programmatic 5,000-char fill → banner, no turn, text kept ✅; 4,000/4,001 boundary pinned + HTML maxlength == JS constant cross-file pin ✅. - Diff scope: `frontend/`, new unit file, `tests/unit/test_schemas.py`, new E2E file, phase files — **no `app/` diff, no migration, no `shared.js` diff**. - Deviations: 4 regression test files touched — 2 genuine DOM-pin conflicts from the new `#char-count` child (explicitly anticipated by the overview) + 3 documented **pre-existing E2E flake fixes** (smooth-scroll race, tab-walk heuristic, 10 ms timeout), each verified pre-existing on the pre-phase-104 tree. - No commit made (harness commits per the execution protocol override). - Next pending phase: `98_sync_summary_visibility`.
This commit is contained in:
@@ -695,8 +695,10 @@ def test_chat_actions_wrapper_holds_both_pills_in_order() -> None:
|
||||
phase 65 (2026-09-01, ``TODO.md`` L3, owner confirmation) moved it
|
||||
from the top of the column to the bottom: below the ``#messages``
|
||||
section, directly above the composer; nothing but the row's own
|
||||
comment lands between ``#messages`` and the row, and nothing but
|
||||
the composer comment lands between the row and the composer. No
|
||||
comment lands between ``#messages`` and the row, and nothing but the
|
||||
phase-104 ``#char-count`` counter + the composer comment lands
|
||||
between the row and the composer (the counter is hidden by default —
|
||||
zero height, the pinned-cluster geometry untouched). No
|
||||
other page carries ``.chat-actions`` (chat-page only, like the
|
||||
pills)."""
|
||||
html = _index()
|
||||
@@ -730,12 +732,23 @@ def test_chat_actions_wrapper_holds_both_pills_in_order() -> None:
|
||||
and "<form" not in between
|
||||
), ("nothing but the row's comment lands between #messages and the row")
|
||||
after = html[end:composer_idx]
|
||||
# Phase 104 (owner 2026-09-12): the ONE permitted child between the
|
||||
# row and the composer is the hidden-by-default question-length
|
||||
# counter — everything else (ids, buttons, sections, forms) is
|
||||
# still excluded from the gap.
|
||||
after_minus_counter = after.replace(
|
||||
'<p class="char-count" id="char-count" hidden></p>', ""
|
||||
)
|
||||
assert (
|
||||
"id=" not in after
|
||||
and "<button" not in after
|
||||
and "<section" not in after
|
||||
and "<form" not in after
|
||||
), ("nothing but the composer comment lands between the row and the composer")
|
||||
after.count("<p") == 1
|
||||
and "id=" not in after_minus_counter
|
||||
and "<button" not in after_minus_counter
|
||||
and "<section" not in after_minus_counter
|
||||
and "<form" not in after_minus_counter
|
||||
), (
|
||||
"nothing but the phase-104 counter + the composer comment lands "
|
||||
"between the row and the composer"
|
||||
)
|
||||
# Phase 76 (task 02): the folded view files are gone (the shell's
|
||||
# chat view is the one and only carrier of the row — pinned above);
|
||||
# the standalone pages carry none (task 03 dropped the last folded
|
||||
|
||||
Reference in New Issue
Block a user