Skip to content

refactor(emulator): Fold mock terminal into vt package.#962

Merged
gdamore merged 1 commit intomainfrom
mock-to-vt
Jan 1, 2026
Merged

refactor(emulator): Fold mock terminal into vt package.#962
gdamore merged 1 commit intomainfrom
mock-to-vt

Conversation

@gdamore
Copy link
Copy Markdown
Owner

@gdamore gdamore commented Jan 1, 2026

This will allow better testing code as tests can be written to inspect private state.

Summary by CodeRabbit

  • Refactor

    • Consolidated and modernized the mock terminal implementation into a single, unified test backend.
    • Simplified style/color/coordinate model used by the mock backend for clearer testing semantics.
  • Tests

    • Updated the entire test suite to use the reworked mock terminal and new accessors.
    • Adjusted test helpers and assertions to align with the unified testing model; no behavioral changes to product functionality.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 1, 2026

📝 Walkthrough

Walkthrough

Migrates and consolidates the mock terminal API from the removed mock package into vt, replacing mock types/constructors with Coord/Style-based equivalents and updating tests and helpers to use the new vt mock interfaces and accessors.

Changes

Cohort / File(s) Summary
Test files updated to vt mocks
color_test.go, demos/beep/beep_test.go, demos/hello/hello_test.go, demos/styles/styles_test.go, tscreen_test.go
Replaced imports of github.com/gdamore/tcell/v3/mock with .../vt; switched calls from mock.NewMockTerm/mock.MockOpt* to vt.NewMockTerm/vt.MockOpt*/vt.MockTerm; updated test accessors to use .S.Fg()/Bg()/Attr() and vt mock option changes; tscreen_test.go signature updated to use vt.MockOpt/vt.MockTerm.
Removed legacy mock package
mock/term.go
Deleted old mock implementation: removed MockTerm interface, mockTerm type and its methods, and NewMockTerm constructor.
New/expanded vt mock API
vt/mock.go
Introduced comprehensive vt mock backend: public MockTerm, MockBackend, MockCell, MockOpt/MockOptSize/MockOptColors, Coord/Style-based APIs, PutRune/PutGrapheme/Blit, Style fluent accessors, and updated backend method signatures and internals.
Test helpers migrated to local types
vt/mock_test.go
Tests and helpers adapted to local, non-prefixed types: Col/Row/Coord/Attr/KbdEvent, updated helper signatures and assertions to use new Coord/Style accessors and methods.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I hopped from mock into vt skies,
Coord and Style now sparkle in my eyes.
Tests scoped and tidy, new paths to explore,
I nibble bugs and hop to one more chore.
Hooray — the mock’s reborn, I twitch my nose! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 48.28% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: moving the mock terminal implementation from the mock package into the vt package, which is the primary refactoring across all modified files.
✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
demos/styles/styles_test.go (1)

43-49: Fix Attr field access: use Style.Attr() method instead of direct field access.

Line 45 accesses .Attr as a direct field on the MockCell returned by GetCell(). However, the Cell struct (vt/emulate.go:123) does not expose an Attr field. The attributes are accessible via the S field (a Style interface) using the Attr() method.

Change line 45 to:

if attr := mt.GetCell(vt.Coord{X: vt.Col(x), Y: vt.Row(y)}).S.Attr(); attr != lastAttr {

The same issue affects demos/hello/hello_test.go line 88, which also needs to call .S.Attr() instead of accessing a nonexistent .Attr field.

demos/hello/hello_test.go (1)

78-91: Update test to access style information through the S field.

The test accesses cell.Fg, cell.Bg, and cell.Attr fields that do not exist on vt.MockCell. The MockCell struct embeds Cell (defined in vt/emulate.go:123-126), which has only C (content) and S (style) fields. The S field is of type Style interface, which provides accessor methods Fg(), Bg(), and Attr().

Update the comparisons to use:

  • cell.S.Fg() instead of cell.Fg
  • cell.S.Bg() instead of cell.Bg
  • cell.S.Attr() instead of cell.Attr

This pattern is already used correctly in vt/mock_test.go (lines 86, 93, 96).

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b752f2f and b8ac521.

📒 Files selected for processing (8)
  • color_test.go
  • demos/beep/beep_test.go
  • demos/hello/hello_test.go
  • demos/styles/styles_test.go
  • mock/term.go
  • tscreen_test.go
  • vt/mock.go
  • vt/mock_test.go
💤 Files with no reviewable changes (1)
  • mock/term.go
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-12-18T02:50:48.847Z
Learnt from: gdamore
Repo: gdamore/tcell PR: 908
File: stdin_unix.go:128-155
Timestamp: 2025-12-18T02:50:48.847Z
Learning: In the tcell Tty interface implementations (stdin_unix.go, tty_unix.go, tty_win.go, tty_plan9.go), the caller is responsible for providing synchronization/mutual exclusion guarantees for method calls like NotifyResize. The Tty implementations themselves do not need internal locking for these methods, as documented in tty.go. The tscreen.go layer handles the synchronization.

Applied to files:

  • tscreen_test.go
  • vt/mock_test.go
  • demos/styles/styles_test.go
  • vt/mock.go
📚 Learning: 2025-12-31T22:01:49.486Z
Learnt from: gdamore
Repo: gdamore/tcell PR: 959
File: vt/emulate.go:0-0
Timestamp: 2025-12-31T22:01:49.486Z
Learning: In vt/emulate.go, the autoWrap (pending wrap) flag behavior is directional: backward/leftward cursor movements always clear autoWrap because they move away from the right column, while forward movements may or may not clear it depending on the specific action. CHT (cursor forward tab) intentionally does not clear autoWrap, aligning with HT (horizontal tab) behavior.

Applied to files:

  • vt/mock_test.go
🧬 Code graph analysis (7)
tscreen_test.go (2)
vt/mock.go (3)
  • MockOpt (464-464)
  • MockTerm (124-147)
  • NewMockTerm (150-156)
mock/term.go (4)
  • mt (110-113)
  • NewMockTerm (150-156)
  • mt (105-107)
  • Tty (124-147)
demos/beep/beep_test.go (2)
vt/mock.go (1)
  • NewMockTerm (150-156)
mock/term.go (7)
  • mt (110-113)
  • mt (105-107)
  • mt (86-88)
  • mt (75-77)
  • mt (36-38)
  • mt (42-44)
  • mt (68-72)
vt/mock_test.go (4)
vt/mock.go (2)
  • MockTerm (124-147)
  • MockBackend (167-184)
vt/coord.go (3)
  • Col (25-25)
  • Row (22-22)
  • Coord (28-31)
vt/attr.go (13)
  • Attr (18-18)
  • Plain (21-21)
  • Bold (22-22)
  • Dim (25-25)
  • Underline (28-28)
  • DoubleUnderline (33-33)
  • CurlyUnderline (34-34)
  • DottedUnderline (35-35)
  • DashedUnderline (36-36)
  • StrikeThrough (27-27)
  • Reverse (24-24)
  • Overline (29-29)
  • Blink (23-23)
vt/kbd.go (1)
  • KbdEvent (17-24)
demos/styles/styles_test.go (2)
vt/mock.go (1)
  • NewMockTerm (150-156)
mock/term.go (2)
  • Tty (124-147)
  • mt (110-113)
demos/hello/hello_test.go (2)
vt/mock.go (2)
  • NewMockTerm (150-156)
  • MockOptColors (472-472)
mock/term.go (3)
  • Tty (124-147)
  • NewMockTerm (150-156)
  • mt (110-113)
color_test.go (4)
tscreen_test.go (1)
  • NewMockScreen (72-89)
vt/mock.go (1)
  • MockOptSize (467-467)
mock/term.go (2)
  • mt (110-113)
  • Tty (124-147)
mock/term_test.go (1)
  • TestTitler (767-787)
vt/mock.go (6)
vt/emulate.go (1)
  • Emulator (36-68)
vt/backend.go (1)
  • Backend (24-60)
vt/coord.go (1)
  • Coord (28-31)
vt/kbd.go (1)
  • KbdEvent (17-24)
vt/mode.go (5)
  • PrivateMode (23-23)
  • ModeStatus (64-64)
  • ModeOn (68-68)
  • ModeOff (69-69)
  • PmShowCursor (30-30)
vt/attr.go (1)
  • Attr (18-18)
🪛 GitHub Actions: linux
demos/hello/hello_test.go

[error] 82-82: Command failed: go test -coverpkg=github.com/gdamore/tcell/v3/... -covermode=count -coverprofile=coverage.txt ./...; demos/hello/hello_test.go:82:19: cell.Fg undefined (type vt.MockCell has no field or method Fg)

🪛 GitHub Actions: macos
demos/hello/hello_test.go

[error] 82-82: go test failed: demos/hello/hello_test.go:82:19: cell.Fg undefined (type vt.MockCell has no field or method Fg). Command: 'go test -coverpkg="github.com/gdamore/tcell/v3/..." -covermode=count -coverprofile="coverage.txt" ./...'

🪛 GitHub Actions: windows
demos/hello/hello_test.go

[error] 82-82: demos/hello/hello_test.go:82:19: cell.Fg undefined (type vt.MockCell has no field or method Fg)

🔇 Additional comments (17)
demos/hello/hello_test.go (1)

16-16: Migration to vt-based mock looks correct.

The change from mock.NewMockTerm to vt.NewMockTerm(vt.MockOptColors(8)) properly aligns with the new vt-based mock API.

vt/mock.go (8)

15-22: Package migration completed correctly.

The package declaration and imports are appropriate for the vt-based mock implementation.


24-156: Mock terminal implementation looks sound.

The mockTerm implementation correctly delegates to the backend and emulator. The Escape key delay (lines 98-101) is appropriately documented for sequence disambiguation.

Based on learnings, the absence of internal locking in methods like NotifyResize is correct, as the caller (tscreen layer) provides synchronization guarantees.


158-184: MockCell and MockBackend interfaces are well-structured.

The interface composition and Coord-based API provide good type safety. However, note that MockCell embeds Cell, and the Cell type must expose fields or methods for accessing foreground color, background color, and attributes to support existing test patterns (see critical issue in demos/hello/hello_test.go).


225-267: Cell update logic correctly handles content and styles.

The PutRune and PutGrapheme methods properly:

  • Handle erasure when content is zero/empty
  • Update both content (C) and style (S) fields
  • Clear adjacent cells for wide characters
  • Perform bounds checking via the index helper

303-321: Color capability handling looks correct.

The pickColor method appropriately validates colors against terminal capabilities and handles the color.Reset case by returning the default color.


363-403: Resize and reset logic is correctly implemented.

The SetSize method properly:

  • Initializes new cells with BaseStyle
  • Preserves existing cell content within the new bounds
  • Clips the cursor position
  • Uses non-blocking notification for resize events

The Reset method correctly restores default state including style, modes, and cursor position.


405-460: Blit implementation correctly handles overlapping regions.

The blit logic properly:

  • Clips source and destination to valid bounds
  • Chooses forward or reverse copy direction based on overlap to prevent corruption
  • Uses efficient index arithmetic in the inner loops

476-504: Mock backend initialization is correct.

The NewMockBackend constructor properly:

  • Sets reasonable defaults (80×24, 256 colors)
  • Applies options before dependent initialization
  • Initializes the style with default colors when color support is enabled
  • Creates and initializes all cells with BaseStyle
  • Sets up the mode map with appropriate defaults
demos/beep/beep_test.go (1)

14-14: Migration to vt-based mock is correct.

The change from mock.NewMockTerm() to vt.NewMockTerm() properly uses the new vt-based mock API.

demos/styles/styles_test.go (1)

17-17: Migration to vt-based mock is correct.

The change from mock.NewMockTerm() to vt.NewMockTerm() properly uses the new vt-based mock API.

color_test.go (2)

22-22: Import migration is correct.

The change from importing mock to vt aligns with the package refactoring.


55-55: MockOptSize usage updated correctly.

The change from mock.MockOptSize to vt.MockOptSize properly uses the type from the new location.

tscreen_test.go (1)

22-22: LGTM! Clean refactoring to use vt package.

The migration from mock to vt package is correctly applied. The function signature, import, and constructor call are all consistently updated.

Also applies to: 72-72, 78-78

vt/mock_test.go (3)

15-15: LGTM! Package change enables private state inspection.

The change from external test (package vt_test) to internal test (package vt) correctly aligns with the PR objective to allow tests to inspect private state of the vt package.


71-99: LGTM! Type references correctly updated.

All type references are consistently updated to use local package types (removing vt. prefix for KbdEvent, Coord, Col, Row, Attr, modifier constants, and key codes). The helper functions are correctly refactored to work with the local types.

Also applies to: 489-596, 619-689


163-167: The project's go.mod specifies Go 1.24.0, which fully supports range-over-integer syntax (available since Go 1.23). No action required.

This will allow better testing code as tests can be written to inspect private state.
@codecov
Copy link
Copy Markdown

codecov Bot commented Jan 1, 2026

Codecov Report

❌ Patch coverage is 96.00000% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.48%. Comparing base (b752f2f) to head (0b808ee).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
vt/mock.go 96.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #962      +/-   ##
==========================================
+ Coverage   70.47%   70.48%   +0.01%     
==========================================
  Files          37       36       -1     
  Lines        3441     3439       -2     
==========================================
- Hits         2425     2424       -1     
+ Misses        871      870       -1     
  Partials      145      145              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
vt/mock.go (1)

95-102: Consider the test performance impact of the Escape delay.

The 150ms sleep after each Escape key event could significantly slow down tests that simulate multiple Escape key presses. While the delay is necessary to disambiguate Escape from other sequences, consider whether this duration could be:

  • Made configurable via a MockOpt
  • Reduced if testing in a controlled environment where disambiguation timing is less critical
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b8ac521 and 0b808ee.

📒 Files selected for processing (8)
  • color_test.go
  • demos/beep/beep_test.go
  • demos/hello/hello_test.go
  • demos/styles/styles_test.go
  • mock/term.go
  • tscreen_test.go
  • vt/mock.go
  • vt/mock_test.go
💤 Files with no reviewable changes (1)
  • mock/term.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • color_test.go
  • demos/styles/styles_test.go
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-12-31T22:01:49.486Z
Learnt from: gdamore
Repo: gdamore/tcell PR: 959
File: vt/emulate.go:0-0
Timestamp: 2025-12-31T22:01:49.486Z
Learning: In vt/emulate.go, the autoWrap (pending wrap) flag behavior is directional: backward/leftward cursor movements always clear autoWrap because they move away from the right column, while forward movements may or may not clear it depending on the specific action. CHT (cursor forward tab) intentionally does not clear autoWrap, aligning with HT (horizontal tab) behavior.

Applied to files:

  • vt/mock_test.go
📚 Learning: 2025-12-18T02:50:48.847Z
Learnt from: gdamore
Repo: gdamore/tcell PR: 908
File: stdin_unix.go:128-155
Timestamp: 2025-12-18T02:50:48.847Z
Learning: In the tcell Tty interface implementations (stdin_unix.go, tty_unix.go, tty_win.go, tty_plan9.go), the caller is responsible for providing synchronization/mutual exclusion guarantees for method calls like NotifyResize. The Tty implementations themselves do not need internal locking for these methods, as documented in tty.go. The tscreen.go layer handles the synchronization.

Applied to files:

  • vt/mock_test.go
  • vt/mock.go
  • tscreen_test.go
🧬 Code graph analysis (5)
demos/beep/beep_test.go (3)
vt/mock.go (1)
  • NewMockTerm (150-156)
mock/term.go (7)
  • mt (110-113)
  • mt (105-107)
  • mt (86-88)
  • mt (75-77)
  • mt (36-38)
  • mt (42-44)
  • mt (68-72)
mock/term_test.go (3)
  • TestTitler (767-787)
  • TestBell (206-222)
  • TestAutoMargin (367-443)
demos/hello/hello_test.go (4)
vt/mock.go (2)
  • NewMockTerm (150-156)
  • MockOptColors (472-472)
vt/attr.go (1)
  • Attr (18-18)
mock/term.go (2)
  • Tty (124-147)
  • mt (86-88)
mock/backend.go (1)
  • cells (55-70)
vt/mock_test.go (4)
vt/mock.go (2)
  • MockTerm (124-147)
  • MockBackend (167-184)
vt/coord.go (3)
  • Col (25-25)
  • Row (22-22)
  • Coord (28-31)
vt/attr.go (14)
  • Attr (18-18)
  • Plain (21-21)
  • Bold (22-22)
  • Dim (25-25)
  • Italic (26-26)
  • Underline (28-28)
  • DoubleUnderline (33-33)
  • CurlyUnderline (34-34)
  • DottedUnderline (35-35)
  • DashedUnderline (36-36)
  • StrikeThrough (27-27)
  • Reverse (24-24)
  • Overline (29-29)
  • Blink (23-23)
vt/kbd.go (16)
  • KbdEvent (17-24)
  • KcReturn (62-62)
  • KcEsc (63-63)
  • KcF1 (193-193)
  • KcF2 (194-194)
  • KcF3 (195-195)
  • KcF4 (196-196)
  • KcF5 (197-197)
  • KcF6 (198-198)
  • KcF7 (199-199)
  • KcF8 (200-200)
  • KcF9 (201-201)
  • KcF20 (212-212)
  • KcHelp (75-75)
  • KcF15 (207-207)
  • KcMenu (70-70)
vt/mock.go (7)
vt/emulate.go (3)
  • Emulator (36-68)
  • NewEmulator (131-152)
  • Cell (123-126)
vt/backend.go (3)
  • Resizer (92-95)
  • Backend (24-60)
  • Blitter (110-112)
vt/coord.go (1)
  • Coord (28-31)
vt/kbd.go (2)
  • KbdEvent (17-24)
  • KcEsc (63-63)
vt/mode.go (6)
  • PrivateMode (23-23)
  • ModeStatus (64-64)
  • ModeOn (68-68)
  • ModeOff (69-69)
  • PmShowCursor (30-30)
  • PmGraphemeClusters (39-39)
vt/attr.go (1)
  • Attr (18-18)
mock/backend.go (2)
  • Backend (33-50)
  • cells (55-70)
tscreen_test.go (1)
vt/mock.go (3)
  • MockOpt (464-464)
  • MockTerm (124-147)
  • NewMockTerm (150-156)
🔇 Additional comments (17)
demos/beep/beep_test.go (1)

14-14: LGTM!

The migration from mock.NewMockTerm() to vt.NewMockTerm() correctly reflects the consolidation of the mock terminal implementation into the vt package.

demos/hello/hello_test.go (2)

16-16: LGTM!

The migration to vt.NewMockTerm(vt.MockOptColors(8)) correctly uses the new vt-based mock API with the color option.


82-89: LGTM!

The change from direct field access to accessor methods (cell.S.Fg(), cell.S.Bg(), cell.S.Attr()) correctly adapts to the new MockCell structure where style information is accessed through the S field's methods.

tscreen_test.go (1)

72-72: LGTM!

The function signature and implementation correctly migrated to use vt.MockOpt and vt.NewMockTerm, aligning with the consolidation of mock functionality into the vt package.

Also applies to: 78-78

vt/mock.go (8)

149-156: LGTM!

The NewMockTerm constructor correctly initializes the mock terminal with a backend and emulator, and sets the terminal identification.


158-184: LGTM!

The MockCell structure and MockBackend interface are well-designed. The MockCell appropriately extends Cell with width information, and MockBackend cleanly combines Backend, Blitter, and mock-specific capabilities.


225-267: LGTM!

The PutRune and PutGrapheme methods correctly handle wide characters by clearing the adjacent cell when width is 2, preventing display corruption.


303-341: LGTM!

The pickColor method properly validates colors against the terminal's color capability and handles the color.Reset special case to restore defaults. The color setter methods correctly use the WithFg/WithBg/WithAttr style builder pattern.


363-388: LGTM!

The SetSize method correctly handles terminal resizing:

  • New cells are properly initialized with BaseStyle
  • Content is copied from the old grid up to the minimum dimensions
  • Cursor position is clamped to the new size
  • Resize notification is non-blocking via select/default pattern

390-403: LGTM!

The Reset method comprehensively restores the terminal to its initial state, correctly handling style, colors, cursor position, and private modes.


405-460: LGTM!

The Blit method correctly handles cell region copying with:

  • Proper clipping to visible source and destination boundaries
  • Forward copy for non-overlapping regions
  • Reverse copy for overlapping regions to prevent corruption
  • Efficient indexing with gap calculation for row advancement

476-503: LGTM!

The NewMockBackend constructor properly initializes all backend state:

  • Sensible defaults (80x24, 256 colors, silver/black)
  • Applies configuration options
  • Initializes all cells with BaseStyle
  • Sets default private modes (cursor shown, grapheme clusters off)
vt/mock_test.go (5)

71-99: LGTM!

The test helper functions are correctly updated to use local types (Col, Row, Coord, Attr) and style accessor methods (S.Attr(), S.Fg(), S.Bg()). The changes are consistent with the new mock API structure.


163-187: LGTM!

The test correctly uses local types throughout, with the range Row(3) and range Col(5) iteration pattern and consistent use of checkAttrs and checkContent helpers.


360-427: LGTM!

The TestAutoMargin function is properly updated to use Coord{X: x, Y: y} for cell access and local types throughout. The automargin behavior tests remain comprehensive and correct.


489-609: LGTM!

The keyboard event tests are comprehensively updated to use local KbdEvent type and key code constants. The test coverage for legacy key protocol remains thorough, including function keys, modifiers, and special key combinations.


1020-1104: LGTM!

The backend blit tests are properly updated to use local Coord and Attr types. The tests maintain comprehensive coverage of both forward and reverse copy scenarios, ensuring overlapping region handling works correctly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant