Commit graph

1 commit

Author SHA1 Message Date
84861dafa5 test: integration — App+MainWindow STA smoke, control-surface live VM, theme XAML load
Some checks failed
CI / build-and-test (push) Failing after 30s
Punch-list items 26 + 27 — three integration tests that need a live
WPF Application + STA dispatcher, sharing one WpfHostFixture so
Application is created exactly once for the suite (it's
one-per-AppDomain and any second `new Application()` throws).

* src/tests/TeamsISO.App.Tests/Integration/WpfHostFixture.cs (new)
  — long-lived STA thread that hosts a single Application instance
  and a Dispatcher; tests marshal work onto it via Run<T>() /
  Run(Action). WpfHostCollection wraps it as an
  ICollectionFixture so xUnit injects the shared fixture into
  any test class that opts in.
* src/tests/TeamsISO.App.Tests/Integration/IntegrationTests.cs
  (new) — single test class carrying all three cases:
  - AppStartup_FullChain_Constructs_WithoutThrowing — pre-loads
    Theme.Dark.xaml + WildDragonTheme.xaml via pack URIs, calls
    ThemeManager.Apply(), constructs MainViewModel with the stub
    controller, constructs MainWindow with the VM as DataContext,
    and asserts the Wd.Canvas brush key resolves on the live
    window. All DependencyObject access happens inside a single
    Dispatcher.Invoke so we never marshal a DO reference across
    threads (WPF's VerifyAccess would throw).
  - ControlSurface_GetParticipants_ReturnsLiveViewModelState —
    boots a ControlSurfaceServer on an ephemeral port against
    a real MainViewModel; publishes a synthetic participant
    through the stub controller's observable; drains the
    dispatcher to ApplicationIdle so the Background-priority
    add lands before the REST call; asserts the JSON includes
    Alice. Complements branch-9 route-smoke tests (which used a
    null view-model) by exercising the dispatcher-marshalling
    path.
  - ThemeXaml_DarkAndLight_BothLoadWithDistinctWdCanvas — loads
    both theme files directly via pack URIs and asserts the two
    canvas brushes are the documented #0A0A0A and #FAFAFB. Doesn't
    test ThemeManager.SwapColorDictionary against Application.
    Resources (the swap STATE test was flaky under xUnit's
    parallel-collection model — Application.Resources is
    process-wide and sibling tests' mutations made the read
    non-deterministic). The unit-layer ThemeManagerTests already
    cover the swap state machine against stubbed seams; this
    integration test guards that the real XAML files load and
    produce the documented colours.

Production code change to support both tests AND a longstanding
correctness issue:
* ThemeManager.SwapColorDictionary now constructs its replacement
  ResourceDictionary with a `pack://application:,,,/TeamsISO;component/Themes/…`
  absolute URI instead of the relative `/Themes/…` form. The
  relative form resolves against Application.Current's base URI —
  which is the entry assembly in production (TeamsISO) but the
  test assembly in xUnit. The pack URI is unambiguous in both
  contexts. Production behaviour is identical (still resolves to
  the same XAML files in the App assembly).

Notes-state collection: NotesServiceTests + OscBridgeDispatchTests
now share a NotesStateCollection xUnit collection because both
mutate the static NotesService.DirectoryOverride; without the
collection xUnit's parallel-collection scheduling let one class's
ctor clobber the override mid-test.

Xunit.StaFact 1.1.11 package added to the test csproj — primary
use was the early WpfFact-based iteration of these tests, kept
because Xunit.StaFact provides the [WpfFact] alternative if a
future test wants per-test STA without sharing the fixture.

Final test totals: 56 → 131 in App.Tests; 103 → 106 in
Engine.Tests. 237 tests pass. Build clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 21:34:09 -04:00