Terminal.Gui 2.0→2.4.5 migration + in-process TUI component tests (layer 1)#165
Conversation
Code Review: Terminal.Gui 2.0 → 2.4.5 migration + TUI component testsOverall this is a well-scoped, necessary upgrade. The mapping table in the PR description is a genuinely useful artifact. A few specific issues worth addressing before merge, plus a formatting nit that runs through the whole diff. Bugs / correctness
}.WithScheme(GetScheme()!);
}.WithScheme(GetScheme() ?? ThemeManager.Current.MainColorScheme);
SelectedFilePath = _files[_fileListView.SelectedItem!.Value].FullName;
var selected = _fileListItems[_fileListView.SelectedItem!.Value];In TG 2.4 var selectedRow = _tableView.Value?.SelectedCell.Y ?? -1;
- _listView.TopItem = Math.Max(0, _displayedEntries.Count - _listView.Frame.Height);
var activated = _treeView.SelectedObject; // reads state after the event firesThe selection could have changed between when Known regression worth flagging explicitlyThe PR description mentions border-colour loss as a "Known regression to confirm". The theme system had distinct frameView.SetScheme(isFocused ? theme.FocusedBorderColorScheme : theme.BorderColorScheme);This applies the accent scheme to the entire frame when focused, not just the border line. That means the frame's text content also picks up the accent colours, which is likely more visible than intended. Worth an eyeball against both themes. Style / formattingThe // OpenConfigDialog.cs, QuickHelpDialog.cs, WriteValueDialog.cs, MonitoredVariablesView.cs:
}.WithScheme(new Scheme { Normal = new Attribute(theme.Accent, theme.Background), Focus = new Attribute(theme.AccentBright, theme.Background), HotNormal = new Attribute(theme.Accent, theme.Background), HotFocus = new Attribute(theme.AccentBright, theme.Background), Disabled = new Attribute(theme.MutedText, theme.Background) });The same PR also introduces nicely formatted multi-line equivalents elsewhere (e.g. TestsThe new layer-1 tests are well-structured:
A couple of small additions would strengthen coverage:
Minor nits
|
Regression review done (multi-agent, adversarially verified)Ran a regression review over the migration diff (7 subsystem reviewers → independent per-finding verification against decompiled Terminal.Gui 2.0 and 2.4 sources → synthesis). It confirmed 4 behavioral regressions, now fixed in
Root pattern: TG 2.4 moved selection/activation out of overridden Still-open known item (by design, not fixed): per-adornment border colouring is lost in TG 2.4 (adornments have no own 627/627 tests pass. |
Code Review — Terminal.Gui 2.0→2.4.5 Migration + TUI Component Tests (Layer 1)This is a large, well-executed migration. The PR description is clear about the scope and the known regressions. The in-line comments explaining why each migration was made are genuinely helpful for future maintainers. A few issues worth addressing before merge. Issues1. Potential null-dereference in }.WithScheme(GetScheme()!);
}.WithScheme(GetScheme() ?? Theme.MainColorScheme);2. Dead code: The per-border colouring was correctly removed because Terminal.Gui 2.4 no longer supports per-adornment schemes. However, the 3. // Before
Application.SizeChanging += (s, e) => UiThread.Run(UpdateConnectionStatusLabelPosition);
// After
SubViewLayout += (s, e) => UiThread.Run(UpdateConnectionStatusLabelPosition);
4. Readability: long single-line Several var accentScheme = new Scheme
{
Normal = new Attribute(theme.Accent, theme.Background),
Focus = new Attribute(theme.AccentBright, theme.Background),
HotNormal = new Attribute(theme.Accent, theme.Background),
HotFocus = new Attribute(theme.AccentBright, theme.Background),
Disabled = new Attribute(theme.MutedText, theme.Background)
};
var openButton = new Button { ... }.WithScheme(accentScheme);The identical accent-button scheme also appears across six dialogs — it would be worth extracting it into a helper on 5. Missing teardown in TUI tests
6. The doc refers to Positive Observations
SummaryThe migration is solid and the reasoning throughout is well-documented. The blocking issues are (1) the |
The component-test APIs (Application.Create, InjectKey/InjectSequence,
VirtualTimeProvider) first appear in Terminal.Gui 2.1.0, which also landed a
breaking API redesign. This ports the whole UI layer to 2.4.5:
- Namespace reorg: add GlobalUsings for Terminal.Gui.{App,ViewBase,Views,
Drawing,Input,Drivers,Text,Configuration}; alias Attribute -> Drawing.Attribute.
- ColorScheme -> Scheme; view.ColorScheme = x -> view.SetScheme(x); add a
WithScheme() fluent helper for initializer-style scheme assignment.
- Toplevel -> Window; RadioGroup -> OptionSelector (Labels/Value/ValueChanged).
- TableView: SelectedRow -> Value?.SelectedCell.Y; SelectedCellChanged ->
ValueChanged<TableSelection>; MouseClick -> MouseEvent(Mouse).
- TreeView ObjectActivated -> Activated (read SelectedObject).
- ListView OpenSelectedItem -> Accepting; drop TopItem (SelectedItem autoscrolls).
- MenuItem shortcutKey: named arg -> positional Key.
- Custom drawing: Driver!.X(...) -> view-level SetAttribute/AddRune/AddStr/Move
in OnDrawingContent(DrawContext).
- Application.Top -> TopRunnable/TopRunnableView; SizeChanging -> SubViewLayout;
Colors.ColorSchemes["Menu"] -> SchemeManager.AddScheme; MessageBox.* now take
Application.Instance; ShadowStyle.None -> ShadowStyles.None; Subviews -> SubViews;
TextField.CursorPosition -> MoveEnd().
Known regression (flagged for review): Terminal.Gui 2.4 adornments have no
independent Scheme, so per-border colouring (grey borders, focus-highlight title)
now inherits the view scheme; focus highlight reapplied via FrameView scheme.
Builds clean; all 613 existing tests pass; published --help smoke exits 0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Constructs the real Terminal.Gui views/dialogs and asserts on observable component behaviour: - MonitoredVariablesView: AddVariable/RemoveVariable, scope-selection bookkeeping, per-client-handle idempotency. - ConnectDialog: endpoint protocol-prefix handling, publishing interval, and the authentication selector (migrated RadioGroup -> OptionSelector). - Theme/Scheme: DarkTheme/LightTheme schemes and ThemeStyler.ApplyTo guard the ColorScheme -> Scheme migration. Tests run in a non-parallel xUnit collection because Terminal.Gui's Application is global state. Picked up automatically by `dotnet test` / CI. Rendered cell-buffer assertions are intentionally deferred to the black-box PTY suite: Terminal.Gui 2.4.5 stable exposes no public headless driver (Application.Create leaves Driver null; DriverAssert is develop-only). Documented in docs/TESTING.md. 627/627 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adversarial review of the Terminal.Gui 2.0->2.4 migration confirmed three event-routing / API-semantics regressions (TG 2.4 moved selection/activation from overridden handlers into the command pipeline, which now runs AFTER the raw MouseEvent/Accepting events): - MonitoredVariablesView.HandleMouseClick: dropped `e.Handled = true` on Sel-column clicks. Marking it handled now pre-empts TableView's LeftButtonClicked -> Command.Activate -> SetSelection, so a Sel click toggled scope but no longer highlighted the row or raised SelectedVariableChanged. Unhandled restores both. - SaveRecordingDialog.OnFileListOpenSelected: set `e.Handled = true`. An unhandled Accepting bubbles Accept to the default Save button, so navigating a folder or picking a file would save+close the dialog mid-browse. - SaveRecordingDialog.NavigateToSelected: null-safe guard. ListView.SelectedItem is now int? (null = none); the OR-form guard didn't catch null and dereferenced null.Value (InvalidOperationException at a CSV-less filesystem root). - LogView: restore log auto-scroll via EnsureSelectedItemVisible() (TG 2.4 removed ListView.TopItem); without it the log stopped following new entries. 627/627 tests pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rebasing onto main brought in the Terminal theme (#176) and its tests, which were written against Terminal.Gui 2.0: - TerminalTheme: ColorScheme -> Scheme; drop the local Attribute alias now provided by GlobalUsings. - ThemeManager: Application.Force16Colors no longer exists as a static; set the flag on Application.Driver only. - ThemeManagerTests: assert UseTerminalColors on the theme since the driver (which now owns Force16Colors) is null in headless tests. - ThemeSchemeTests: ThemeStyler.ApplyTo was dropped in favour of main's leaner surface (#177); test ApplyToFrame instead.
7d2799b to
8535266
Compare
Code Review — Terminal.Gui 2.0→2.4.5 migration + TUI component testsOverall this is a well-executed, large-scale framework migration. The mapping document in the PR description, the inline comments at each changed site, and the 627/627 passing tests all indicate solid execution. Below are specific observations grouped by severity. Medium — Readability regressions in inline
|
- ScopeDialog: replace GetScheme()! with an explicit fallback to the theme's main scheme, removing the NRE risk reviewers flagged. - ConnectDialog: normalize an empty password box to null so Password honours its nullable contract; downstream sends the same bytes. - Expand the collapsed single-line Scheme initializers in HelpDialog, WriteValueDialog and MonitoredVariablesView to the multi-line style used elsewhere. - AppTheme: mark the now-unapplied HighlightTitleBorderColorScheme with a TODO tied to the planned VisualRoles work. - AddressSpaceView: document why reading SelectedObject in Activated is race-free. - Tests: cover TerminalTheme in ThemeSchemeTests, add a WithScheme unit test, assert Password stays null without input, and dispose views in TUI tests to stop ThemeChanged handler leaks across the collection. - docs/TESTING.md: note the E2E project ships in the follow-up PR.
Code Review — PR #165: Terminal.Gui 2.0 → 2.4.5 migration + TUI component testsThis is a thorough, well-executed migration. The PR description maps every breaking change to its fix, the 14 new tests guard the migration, and 692/692 tests pass. Overall I'd call this ready to merge with a few minor items worth addressing. What the PR does
Positives
IssuesBug risk —
|
…polish - AppTheme: mark HighlightTitleBorderColorScheme [Obsolete] so future callers can't silently rely on a scheme that is never applied. - ConnectDialogTests: cover the non-null path of the Password getter by typing into the dialog's Secret TextField. - MonitoredVariablesView: note that Mouse.Position is Point? in Terminal.Gui 2.4 so the null pattern isn't stripped as redundant. - NodeDetailsView: use WithScheme for the copy button like every other initializer in the migration. - ScopeView: drop a stray blank line left by the Driver-null-check removal.
Code Review — PR #165: Terminal.Gui 2.0→2.4.5 Migration + TUI Component Tests (Layer 1)This is a well-executed, large-scope framework upgrade. The migration mapping is thorough and the inline documentation of why each change was made is excellent. Notes below are roughly priority-ordered. Potential Bugs / Issues1. In SubViewLayout += (s, e) => UiThread.Run(UpdateConnectionStatusLabelPosition);The original 2.
These seem intentionally distinct (one returns the 3. }.WithScheme(GetScheme() ?? Theme.MainColorScheme);
Code Quality
The new helper in
The property is marked obsolete and no call site in this PR uses it, but the lazy-init backing field still computes and caches a
// Safe from activate/select races: Activated is raised synchronously on the UI
// thread by the command that acted on the selection, so it still matches.
var activated = _treeView.SelectedObject;The reasoning is sound. Small suggestion: move this comment to the method rather than inside the body so it's visible when reading the event subscription.
The explanation for why the event must not be marked handled (to preserve row-selection after Sel-column toggle) is exactly the kind of non-obvious invariant that belongs in the code. No changes needed; calling it out as a model for the rest of the migration comments. Test CoverageNew
Missing:
Minor / Nits
SummaryThis is a solid, well-documented breaking-framework migration. The three main things I'd ask about before merging:
The new test layer is a good foundation. The architecture decision (state assertions now, rendered-cell assertions in the PTY PR) is clearly reasoned and documented. 🤖 Generated with Claude Code |
Captured against the in-repo OPC UA test server (tmux + ANSI render): main window in all three themes, the migrated Connect dialog (OptionSelector), and the braille scope with four live signals.
Code Review — Terminal.Gui 2.0→2.4.5 Migration + TUI Component Tests (Layer 1)This is a well-executed, large-scale framework migration. The PR is systematic, well-documented, and lands cleanly. Notes below are ordered by significance. OverviewA breaking Terminal.Gui upgrade (~400 compile errors across 23 files) bundled with the first layer of in-process TUI component tests. The PR body is unusually thorough about what changed and why — the mapping table is genuinely useful for reviewing. Screenshots confirm visual parity across all three themes. What's done well
Issues and suggestions1.
|
| Test class | What it guards |
|---|---|
ConnectDialogTests |
Endpoint prefixing, interval, OptionSelector auth, password null-contract |
MonitoredVariablesViewTests |
Add/remove, scope bookkeeping, idempotency by client handle |
ThemeSchemeTests |
ColorScheme→Scheme migration (all 3 themes), WithScheme chaining |
The scope is appropriate for the "state, not rendered cells" limitation imposed by the stable 2.4.5 release. docs/TESTING.md honestly describes the gap and where layer 2 will close it.
One gap: there are no tests for the SaveRecordingDialog Accepting → e.Handled = true fix (item 2 in the bullet list above). That's a subtle behaviour change; a regression would be silent. Even a unit test that calls NavigateToSelected via a subview find and verifies the dialog isn't closed would add meaningful coverage.
Security / performance
No concerns. This is pure UI and test infrastructure. The Driver! null-forgiving accesses have all been replaced with view-level methods — that's a correctness improvement.
Summary
The migration is thorough and the new tests are well-targeted. The items above are all low-to-medium severity; none are blockers. Approachable as-is with the SubViewLayout frequency and the HandleObjectActivated invariant called out as follow-up tracking items.
🤖 Generated with Claude Code
First of two PRs adding programmatic TUI testing.
What this is
Layer 1 of two-layer TUI testing: in-process component tests that drive the real
Terminal.Gui views/dialogs. Because the component-testing APIs only exist from Terminal.Gui
2.1.0+, this PR also carries the (large) Terminal.Gui 2.0.0 → 2.4.5 upgrade that they
require.
Terminal.Gui 2.0.0 → 2.1.0 was a breaking API redesign (not a minor bump); there is no version
with the test APIs that avoids it. Upgrading surfaced ~400 compile errors across 23 files.
Mapped and applied:
Terminal.Gui.{App,ViewBase,Views,Drawing,Input,Drivers,…}→added
GlobalUsings.cs; aliasedAttribute→Drawing.Attribute.ColorScheme→Scheme;view.ColorScheme = x→view.SetScheme(x); added aWithScheme()fluent helper for initializer-style assignment.Toplevel→Window,RadioGroup→OptionSelector(Labels/Value/ValueChanged).SelectedRow→Value?.SelectedCell.Y;SelectedCellChanged→ValueChanged;MouseClick→MouseEvent(Mouse).ObjectActivated→Activated; ListViewOpenSelectedItem→Accepting.shortcutKey:→ positionalKey; custom drawingDriver!.X→ view-levelSetAttribute/AddRune/AddStr/MoveinOnDrawingContent.Application.Top→TopRunnable/TopRunnableView;SizeChanging→SubViewLayout;Colors.ColorSchemes[..]→SchemeManager.AddScheme;MessageBox.*now takeApplication.Instance;ShadowStyle.None→ShadowStyles.None; misc.Rebased onto current main
The branch was rebased onto main (post #171/#173/#174/#175/#176/#177). Code added on main
after the branch point was migrated to 2.4.5 in a follow-up commit:
TerminalTheme(Add Terminal theme that inherits the terminal's ANSI colour scheme #176):ColorScheme→Scheme; dropped its localAttributealias(now in
GlobalUsings.cs).ThemeManager: the staticApplication.Force16Colorsno longer exists — the flag nowlives on
Application.Driveronly.ThemeStylerkeeps main's consolidated surface from Streamline codebase: remove dead code and consolidate duplicated logic #177 (CreateAccentButtonScheme/CreateFlatBarScheme), migrated to returnScheme.Known regression — now verified visually (screenshots below)
Terminal.Gui 2.4 made adornments (Border/Margin/Padding) non-
Viewobjects without their ownScheme. The former per-border colouring (distinct grey borders; bright-accent title on themain window) now inherits the owning view's scheme. Focus-highlight is reapplied via the
FrameView's own scheme (UpdatePanelBorder) — visible in the screenshots as the accentdouble-border on the focused pane. Border rendering is intact in all three themes.
Screenshots (live against the in-repo OPC UA test server)
OptionSelector)Scope with four live signals (braille canvas, custom
OnDrawingContentmigration):Layer 1 tests
Tests/Opcilloscope.Tests/Tui/— real views, asserting component behaviour:MonitoredVariablesView: add/remove, scope-selection bookkeeping, idempotency.ConnectDialog: endpoint prefixing, interval, auth selector (the migrated OptionSelector),credential null-contract.
Scheme: guards theColorScheme → Schememigration (all three themes) and theWithSchemehelper.Non-parallel xUnit collection (
Applicationis global state). Auto-run bydotnet test/CI.Why state, not rendered cells: Terminal.Gui 2.4.5 stable ships no public headless driver
(
Application.Create()leavesDrivernull;DriverAssertis develop-only). Rendered-screenassertions are delivered by layer 2 (separate PR) — a black-box PTY harness against the
published binary. See
docs/TESTING.md.Verification
--helpexits 0; full TUI launched against the in-repo test server: connect dialog,address-space browsing, subscriptions, live value updates, scope rendering, and all three
themes exercised end-to-end (see screenshots).
🤖 Generated with Claude Code