Daryl Lim Claude Opus 4.8 (1M context) commited on
Commit
c15ff11
·
1 Parent(s): 9fdec8c

test: cover Textbox toolbar buttons and update test counts

Browse files

Add fast tests asserting the input textbox exposes no toolbar buttons
(guards the removed invalid clear button) and the output textbox has a
copy button — the buttons config was previously untested, which let
buttons=["clear"] slip through. Update test counts (48->50, 38->40
fast, test_app.py 28->30) in CLAUDE.md and README.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Files changed (3) hide show
  1. CLAUDE.md +3 -3
  2. README.md +2 -2
  3. tests/test_app.py +14 -0
CLAUDE.md CHANGED
@@ -25,8 +25,8 @@ uv run ruff format .
25
  uv run ty check
26
 
27
  # Test
28
- uv run pytest # all 48 tests (slow require CUDA + model download)
29
- uv run pytest -m "not slow" # 38 fast tests only
30
  uv run pytest -m slow # 10 model tests only (CUDA only)
31
 
32
  # Generate language mapping (dev only)
@@ -41,7 +41,7 @@ uv run scripts/generate_langmap.py <path-to-paper.pdf>
41
 
42
  **`scripts/`** — `generate_langmap.py` parses the MADLAD-400 paper PDF (Table 9, pages 16-22) using pdfplumber and generates the static language mapping with region assignments. Dev-only tool; requires `requirements-dev.txt` dependencies.
43
 
44
- **`tests/`** — 48 tests (38 fast, 10 slow). `test_langmap.py` has 10 fast tests for mapping validation (dict shape, regions, spot-checks). `test_app.py` has 28 fast tests (signatures, device fallback, UI layout with symmetric dropdowns, swap button, textbox config, handler wiring, no HTML elements, locale codes, no title) and 10 slow tests (translation with various parameters, language mapping). Slow tests require CUDA and model download; auto-skipped without CUDA.
45
 
46
  ## Tooling
47
 
 
25
  uv run ty check
26
 
27
  # Test
28
+ uv run pytest # all 50 tests (slow require CUDA + model download)
29
+ uv run pytest -m "not slow" # 40 fast tests only
30
  uv run pytest -m slow # 10 model tests only (CUDA only)
31
 
32
  # Generate language mapping (dev only)
 
41
 
42
  **`scripts/`** — `generate_langmap.py` parses the MADLAD-400 paper PDF (Table 9, pages 16-22) using pdfplumber and generates the static language mapping with region assignments. Dev-only tool; requires `requirements-dev.txt` dependencies.
43
 
44
+ **`tests/`** — 50 tests (40 fast, 10 slow). `test_langmap.py` has 10 fast tests for mapping validation (dict shape, regions, spot-checks). `test_app.py` has 30 fast tests (signatures, device fallback, UI layout with symmetric dropdowns, swap button, textbox config including toolbar buttons, handler wiring, no HTML elements, locale codes, no title) and 10 slow tests (translation with various parameters, language mapping). Slow tests require CUDA and model download; auto-skipped without CUDA.
45
 
46
  ## Tooling
47
 
README.md CHANGED
@@ -38,6 +38,6 @@ The Gradio interface launches at `http://localhost:7860`.
38
  uv run ruff check . # lint
39
  uv run ruff format . # format
40
  uv run ty check # type check
41
- uv run pytest -m "not slow" # 38 fast tests
42
- uv run pytest # all 48 tests (slow require CUDA + model download)
43
  ```
 
38
  uv run ruff check . # lint
39
  uv run ruff format . # format
40
  uv run ty check # type check
41
+ uv run pytest -m "not slow" # 40 fast tests
42
+ uv run pytest # all 50 tests (slow require CUDA + model download)
43
  ```
tests/test_app.py CHANGED
@@ -153,6 +153,13 @@ def test_input_textbox_has_no_placeholder(demo):
153
  assert interactive[0].placeholder is None, f"Expected no placeholder, got {interactive[0].placeholder!r}"
154
 
155
 
 
 
 
 
 
 
 
156
  def test_output_textbox_is_non_interactive(demo):
157
  """Output textbox should be non-interactive."""
158
  textboxes = [b for b in demo.blocks.values() if type(b).__name__ == "Textbox"]
@@ -174,6 +181,13 @@ def test_output_placeholder(demo):
174
  assert output[0].placeholder == "Translation"
175
 
176
 
 
 
 
 
 
 
 
177
  def test_demo_has_translate_button(demo):
178
  """UI should have a Translate button."""
179
  buttons = [b for b in demo.blocks.values() if type(b).__name__ == "Button"]
 
153
  assert interactive[0].placeholder is None, f"Expected no placeholder, got {interactive[0].placeholder!r}"
154
 
155
 
156
+ def test_input_textbox_has_no_buttons(demo):
157
+ """Input textbox should expose no toolbar buttons (invalid 'clear' button removed)."""
158
+ textboxes = [b for b in demo.blocks.values() if type(b).__name__ == "Textbox"]
159
+ interactive = [t for t in textboxes if t.interactive is not False]
160
+ assert interactive[0].buttons == [], f"Expected no buttons, got {interactive[0].buttons!r}"
161
+
162
+
163
  def test_output_textbox_is_non_interactive(demo):
164
  """Output textbox should be non-interactive."""
165
  textboxes = [b for b in demo.blocks.values() if type(b).__name__ == "Textbox"]
 
181
  assert output[0].placeholder == "Translation"
182
 
183
 
184
+ def test_output_textbox_has_copy_button(demo):
185
+ """Output textbox should expose a copy button."""
186
+ textboxes = [b for b in demo.blocks.values() if type(b).__name__ == "Textbox"]
187
+ output = [t for t in textboxes if t.interactive is False]
188
+ assert output[0].buttons == ["copy"], f"Expected ['copy'], got {output[0].buttons!r}"
189
+
190
+
191
  def test_demo_has_translate_button(demo):
192
  """UI should have a Translate button."""
193
  buttons = [b for b in demo.blocks.values() if type(b).__name__ == "Button"]