postIt: wire DarkMode, drop dead themeVariant, add UI tests for the banner
Three related changes that close the loop on the DarkMode
field and lay the first stone of a UI test scaffold for
PostIt.
1. Settings.DarkMode was previously a dead field. It round-
tripped through postit-settings.json and the SettingsPage
CheckBox, OnDarkModeChanged flipped IsDirty, and that was
it — no consumer ever read the value, so toggling the
CheckBox had no visible effect. The fix is in
App.OnFrameworkInitializationCompleted: read the value
Load() just populated and set
Application.Current.RequestedThemeVariant accordingly
(so a dark-mode user lands on a dark window on first
launch, not on a default-light window that flips after
the user touches the toggle), then subscribe to
settings.PropertyChanged and update the theme on every
DarkMode change. The consumer lives in App.axaml.cs, not
in Settings, so the Settings model stays free of any
Avalonia.Application dependency and the SettingsLoadTests
(which construct Settings outside an Avalonia host)
still pass unchanged.
2. MainPageViewModel had a vestigial [ObservableProperty]
ThemeVariant themeVariant = ThemeVariant.Default that no
XAML, no code, and no test ever read. It was the start of
a half-finished attempt to expose the theme variant on
the page VM. The dark-mode wiring above makes it
irrelevant: the theme is now driven by Application, not
by a VM property. The field is removed, along with the
using Avalonia.Styling; it pulled in (now unused).
3. SessionStatusBannerTests adds the first set of UI tests
for PostIt. They mount a real MainWindow via the headless
Avalonia host declared in TestApp.cs, attach a
SessionStatusViewModel as the banner's DataContext, and
assert the actual visual tree contents: three buttons
render (Se déconnecter, Se connecter, Paramètres), the
Login button is visible when logged out, the Logout
button is hidden when logged out, the Paramètres button
is visible regardless of session, and the session label
text reflects the VM. The pattern follows what
UnitTest1.MainPage_Should_Load already established:
[AvaloniaFact] (from Avalonia.Headless.XUnit) plus
new MainWindow() / window.Show(). A plain [Fact] cannot
drive Window..ctor() because the headless platform's
PlatformManager.CreateWindow() has no service registered
outside a dispatcher-aware test context; the
AvaloniaFact attribute provides that context. The
DataContext is set on the banner directly because
App.OnFrameworkInitializationCompleted is not called in
a unit test (production wiring is exercised by the
manual launch, not here).
Build: 0 errors. Tests: 5/5 SessionStatusBannerTests,
3/3 SettingsLoadTests, 1/1 MainPageTests (the existing
scaffold test, unchanged). The other PostIt.Tests suites
depend on the OIDC stub WebApplicationFactory and time out
on this network-restricted host.
2026-07-09 22:17:56 +01:00
|
|
|
using Avalonia.Controls;
|
|
|
|
|
using Avalonia.Headless.XUnit;
|
|
|
|
|
using Avalonia.VisualTree;
|
|
|
|
|
using PostIt.ViewModels;
|
|
|
|
|
using PostIt.Views;
|
|
|
|
|
|
|
|
|
|
namespace PostIt.Tests;
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// UI tests for <see cref="SessionStatusBanner"/>. Mounted inside
|
2026-08-25 14:16:49 +01:00
|
|
|
/// a real <see cref="MainView"/> via the headless Avalonia
|
postIt: wire DarkMode, drop dead themeVariant, add UI tests for the banner
Three related changes that close the loop on the DarkMode
field and lay the first stone of a UI test scaffold for
PostIt.
1. Settings.DarkMode was previously a dead field. It round-
tripped through postit-settings.json and the SettingsPage
CheckBox, OnDarkModeChanged flipped IsDirty, and that was
it — no consumer ever read the value, so toggling the
CheckBox had no visible effect. The fix is in
App.OnFrameworkInitializationCompleted: read the value
Load() just populated and set
Application.Current.RequestedThemeVariant accordingly
(so a dark-mode user lands on a dark window on first
launch, not on a default-light window that flips after
the user touches the toggle), then subscribe to
settings.PropertyChanged and update the theme on every
DarkMode change. The consumer lives in App.axaml.cs, not
in Settings, so the Settings model stays free of any
Avalonia.Application dependency and the SettingsLoadTests
(which construct Settings outside an Avalonia host)
still pass unchanged.
2. MainPageViewModel had a vestigial [ObservableProperty]
ThemeVariant themeVariant = ThemeVariant.Default that no
XAML, no code, and no test ever read. It was the start of
a half-finished attempt to expose the theme variant on
the page VM. The dark-mode wiring above makes it
irrelevant: the theme is now driven by Application, not
by a VM property. The field is removed, along with the
using Avalonia.Styling; it pulled in (now unused).
3. SessionStatusBannerTests adds the first set of UI tests
for PostIt. They mount a real MainWindow via the headless
Avalonia host declared in TestApp.cs, attach a
SessionStatusViewModel as the banner's DataContext, and
assert the actual visual tree contents: three buttons
render (Se déconnecter, Se connecter, Paramètres), the
Login button is visible when logged out, the Logout
button is hidden when logged out, the Paramètres button
is visible regardless of session, and the session label
text reflects the VM. The pattern follows what
UnitTest1.MainPage_Should_Load already established:
[AvaloniaFact] (from Avalonia.Headless.XUnit) plus
new MainWindow() / window.Show(). A plain [Fact] cannot
drive Window..ctor() because the headless platform's
PlatformManager.CreateWindow() has no service registered
outside a dispatcher-aware test context; the
AvaloniaFact attribute provides that context. The
DataContext is set on the banner directly because
App.OnFrameworkInitializationCompleted is not called in
a unit test (production wiring is exercised by the
manual launch, not here).
Build: 0 errors. Tests: 5/5 SessionStatusBannerTests,
3/3 SettingsLoadTests, 1/1 MainPageTests (the existing
scaffold test, unchanged). The other PostIt.Tests suites
depend on the OIDC stub WebApplicationFactory and time out
on this network-restricted host.
2026-07-09 22:17:56 +01:00
|
|
|
/// platform declared in <c>TestApp.cs</c>.
|
|
|
|
|
///
|
|
|
|
|
/// <para>The pattern is the one that <c>UnitTest1.MainPage_Should_Load</c>
|
|
|
|
|
/// established: a test attribute <c>[AvaloniaFact]</c> (from
|
|
|
|
|
/// <c>Avalonia.Headless.XUnit</c>) instead of plain <c>[Fact]</c>,
|
|
|
|
|
/// <c>new MainWindow()</c>, <c>window.Show()</c>. The AvaloniaFact
|
|
|
|
|
/// attribute schedules the test body inside a dispatcher, which
|
|
|
|
|
/// is the precondition for the headless Window's
|
|
|
|
|
/// <c>PlatformManager.CreateWindow()</c> to find a registered
|
|
|
|
|
/// service. A plain <c>[Fact]</c> test that calls
|
|
|
|
|
/// <c>new Window().Show()</c> throws because the harness has not
|
|
|
|
|
/// been initialised for that thread.</para>
|
|
|
|
|
///
|
2026-10-11 07:28:17 +01:00
|
|
|
/// <para>These tests set the DataContext directly on the banner
|
|
|
|
|
/// mounted in the window. The production code path is exercised
|
postIt: wire DarkMode, drop dead themeVariant, add UI tests for the banner
Three related changes that close the loop on the DarkMode
field and lay the first stone of a UI test scaffold for
PostIt.
1. Settings.DarkMode was previously a dead field. It round-
tripped through postit-settings.json and the SettingsPage
CheckBox, OnDarkModeChanged flipped IsDirty, and that was
it — no consumer ever read the value, so toggling the
CheckBox had no visible effect. The fix is in
App.OnFrameworkInitializationCompleted: read the value
Load() just populated and set
Application.Current.RequestedThemeVariant accordingly
(so a dark-mode user lands on a dark window on first
launch, not on a default-light window that flips after
the user touches the toggle), then subscribe to
settings.PropertyChanged and update the theme on every
DarkMode change. The consumer lives in App.axaml.cs, not
in Settings, so the Settings model stays free of any
Avalonia.Application dependency and the SettingsLoadTests
(which construct Settings outside an Avalonia host)
still pass unchanged.
2. MainPageViewModel had a vestigial [ObservableProperty]
ThemeVariant themeVariant = ThemeVariant.Default that no
XAML, no code, and no test ever read. It was the start of
a half-finished attempt to expose the theme variant on
the page VM. The dark-mode wiring above makes it
irrelevant: the theme is now driven by Application, not
by a VM property. The field is removed, along with the
using Avalonia.Styling; it pulled in (now unused).
3. SessionStatusBannerTests adds the first set of UI tests
for PostIt. They mount a real MainWindow via the headless
Avalonia host declared in TestApp.cs, attach a
SessionStatusViewModel as the banner's DataContext, and
assert the actual visual tree contents: three buttons
render (Se déconnecter, Se connecter, Paramètres), the
Login button is visible when logged out, the Logout
button is hidden when logged out, the Paramètres button
is visible regardless of session, and the session label
text reflects the VM. The pattern follows what
UnitTest1.MainPage_Should_Load already established:
[AvaloniaFact] (from Avalonia.Headless.XUnit) plus
new MainWindow() / window.Show(). A plain [Fact] cannot
drive Window..ctor() because the headless platform's
PlatformManager.CreateWindow() has no service registered
outside a dispatcher-aware test context; the
AvaloniaFact attribute provides that context. The
DataContext is set on the banner directly because
App.OnFrameworkInitializationCompleted is not called in
a unit test (production wiring is exercised by the
manual launch, not here).
Build: 0 errors. Tests: 5/5 SessionStatusBannerTests,
3/3 SettingsLoadTests, 1/1 MainPageTests (the existing
scaffold test, unchanged). The other PostIt.Tests suites
depend on the OIDC stub WebApplicationFactory and time out
on this network-restricted host.
2026-07-09 22:17:56 +01:00
|
|
|
/// end-to-end by the manual launch, not here.</para>
|
|
|
|
|
/// </summary>
|
2026-10-11 07:28:17 +01:00
|
|
|
public class SessionStatusBannerTests : IDisposable
|
postIt: wire DarkMode, drop dead themeVariant, add UI tests for the banner
Three related changes that close the loop on the DarkMode
field and lay the first stone of a UI test scaffold for
PostIt.
1. Settings.DarkMode was previously a dead field. It round-
tripped through postit-settings.json and the SettingsPage
CheckBox, OnDarkModeChanged flipped IsDirty, and that was
it — no consumer ever read the value, so toggling the
CheckBox had no visible effect. The fix is in
App.OnFrameworkInitializationCompleted: read the value
Load() just populated and set
Application.Current.RequestedThemeVariant accordingly
(so a dark-mode user lands on a dark window on first
launch, not on a default-light window that flips after
the user touches the toggle), then subscribe to
settings.PropertyChanged and update the theme on every
DarkMode change. The consumer lives in App.axaml.cs, not
in Settings, so the Settings model stays free of any
Avalonia.Application dependency and the SettingsLoadTests
(which construct Settings outside an Avalonia host)
still pass unchanged.
2. MainPageViewModel had a vestigial [ObservableProperty]
ThemeVariant themeVariant = ThemeVariant.Default that no
XAML, no code, and no test ever read. It was the start of
a half-finished attempt to expose the theme variant on
the page VM. The dark-mode wiring above makes it
irrelevant: the theme is now driven by Application, not
by a VM property. The field is removed, along with the
using Avalonia.Styling; it pulled in (now unused).
3. SessionStatusBannerTests adds the first set of UI tests
for PostIt. They mount a real MainWindow via the headless
Avalonia host declared in TestApp.cs, attach a
SessionStatusViewModel as the banner's DataContext, and
assert the actual visual tree contents: three buttons
render (Se déconnecter, Se connecter, Paramètres), the
Login button is visible when logged out, the Logout
button is hidden when logged out, the Paramètres button
is visible regardless of session, and the session label
text reflects the VM. The pattern follows what
UnitTest1.MainPage_Should_Load already established:
[AvaloniaFact] (from Avalonia.Headless.XUnit) plus
new MainWindow() / window.Show(). A plain [Fact] cannot
drive Window..ctor() because the headless platform's
PlatformManager.CreateWindow() has no service registered
outside a dispatcher-aware test context; the
AvaloniaFact attribute provides that context. The
DataContext is set on the banner directly because
App.OnFrameworkInitializationCompleted is not called in
a unit test (production wiring is exercised by the
manual launch, not here).
Build: 0 errors. Tests: 5/5 SessionStatusBannerTests,
3/3 SettingsLoadTests, 1/1 MainPageTests (the existing
scaffold test, unchanged). The other PostIt.Tests suites
depend on the OIDC stub WebApplicationFactory and time out
on this network-restricted host.
2026-07-09 22:17:56 +01:00
|
|
|
{
|
2026-10-11 07:28:17 +01:00
|
|
|
private MainWindow? _window;
|
|
|
|
|
|
postIt: wire DarkMode, drop dead themeVariant, add UI tests for the banner
Three related changes that close the loop on the DarkMode
field and lay the first stone of a UI test scaffold for
PostIt.
1. Settings.DarkMode was previously a dead field. It round-
tripped through postit-settings.json and the SettingsPage
CheckBox, OnDarkModeChanged flipped IsDirty, and that was
it — no consumer ever read the value, so toggling the
CheckBox had no visible effect. The fix is in
App.OnFrameworkInitializationCompleted: read the value
Load() just populated and set
Application.Current.RequestedThemeVariant accordingly
(so a dark-mode user lands on a dark window on first
launch, not on a default-light window that flips after
the user touches the toggle), then subscribe to
settings.PropertyChanged and update the theme on every
DarkMode change. The consumer lives in App.axaml.cs, not
in Settings, so the Settings model stays free of any
Avalonia.Application dependency and the SettingsLoadTests
(which construct Settings outside an Avalonia host)
still pass unchanged.
2. MainPageViewModel had a vestigial [ObservableProperty]
ThemeVariant themeVariant = ThemeVariant.Default that no
XAML, no code, and no test ever read. It was the start of
a half-finished attempt to expose the theme variant on
the page VM. The dark-mode wiring above makes it
irrelevant: the theme is now driven by Application, not
by a VM property. The field is removed, along with the
using Avalonia.Styling; it pulled in (now unused).
3. SessionStatusBannerTests adds the first set of UI tests
for PostIt. They mount a real MainWindow via the headless
Avalonia host declared in TestApp.cs, attach a
SessionStatusViewModel as the banner's DataContext, and
assert the actual visual tree contents: three buttons
render (Se déconnecter, Se connecter, Paramètres), the
Login button is visible when logged out, the Logout
button is hidden when logged out, the Paramètres button
is visible regardless of session, and the session label
text reflects the VM. The pattern follows what
UnitTest1.MainPage_Should_Load already established:
[AvaloniaFact] (from Avalonia.Headless.XUnit) plus
new MainWindow() / window.Show(). A plain [Fact] cannot
drive Window..ctor() because the headless platform's
PlatformManager.CreateWindow() has no service registered
outside a dispatcher-aware test context; the
AvaloniaFact attribute provides that context. The
DataContext is set on the banner directly because
App.OnFrameworkInitializationCompleted is not called in
a unit test (production wiring is exercised by the
manual launch, not here).
Build: 0 errors. Tests: 5/5 SessionStatusBannerTests,
3/3 SettingsLoadTests, 1/1 MainPageTests (the existing
scaffold test, unchanged). The other PostIt.Tests suites
depend on the OIDC stub WebApplicationFactory and time out
on this network-restricted host.
2026-07-09 22:17:56 +01:00
|
|
|
[AvaloniaFact]
|
2026-10-11 07:28:17 +01:00
|
|
|
public void Banner_renders_four_buttons_in_the_visual_tree()
|
postIt: wire DarkMode, drop dead themeVariant, add UI tests for the banner
Three related changes that close the loop on the DarkMode
field and lay the first stone of a UI test scaffold for
PostIt.
1. Settings.DarkMode was previously a dead field. It round-
tripped through postit-settings.json and the SettingsPage
CheckBox, OnDarkModeChanged flipped IsDirty, and that was
it — no consumer ever read the value, so toggling the
CheckBox had no visible effect. The fix is in
App.OnFrameworkInitializationCompleted: read the value
Load() just populated and set
Application.Current.RequestedThemeVariant accordingly
(so a dark-mode user lands on a dark window on first
launch, not on a default-light window that flips after
the user touches the toggle), then subscribe to
settings.PropertyChanged and update the theme on every
DarkMode change. The consumer lives in App.axaml.cs, not
in Settings, so the Settings model stays free of any
Avalonia.Application dependency and the SettingsLoadTests
(which construct Settings outside an Avalonia host)
still pass unchanged.
2. MainPageViewModel had a vestigial [ObservableProperty]
ThemeVariant themeVariant = ThemeVariant.Default that no
XAML, no code, and no test ever read. It was the start of
a half-finished attempt to expose the theme variant on
the page VM. The dark-mode wiring above makes it
irrelevant: the theme is now driven by Application, not
by a VM property. The field is removed, along with the
using Avalonia.Styling; it pulled in (now unused).
3. SessionStatusBannerTests adds the first set of UI tests
for PostIt. They mount a real MainWindow via the headless
Avalonia host declared in TestApp.cs, attach a
SessionStatusViewModel as the banner's DataContext, and
assert the actual visual tree contents: three buttons
render (Se déconnecter, Se connecter, Paramètres), the
Login button is visible when logged out, the Logout
button is hidden when logged out, the Paramètres button
is visible regardless of session, and the session label
text reflects the VM. The pattern follows what
UnitTest1.MainPage_Should_Load already established:
[AvaloniaFact] (from Avalonia.Headless.XUnit) plus
new MainWindow() / window.Show(). A plain [Fact] cannot
drive Window..ctor() because the headless platform's
PlatformManager.CreateWindow() has no service registered
outside a dispatcher-aware test context; the
AvaloniaFact attribute provides that context. The
DataContext is set on the banner directly because
App.OnFrameworkInitializationCompleted is not called in
a unit test (production wiring is exercised by the
manual launch, not here).
Build: 0 errors. Tests: 5/5 SessionStatusBannerTests,
3/3 SettingsLoadTests, 1/1 MainPageTests (the existing
scaffold test, unchanged). The other PostIt.Tests suites
depend on the OIDC stub WebApplicationFactory and time out
on this network-restricted host.
2026-07-09 22:17:56 +01:00
|
|
|
{
|
2026-10-11 07:28:17 +01:00
|
|
|
SessionStatusBanner banner = CreateBanner();
|
postIt: wire DarkMode, drop dead themeVariant, add UI tests for the banner
Three related changes that close the loop on the DarkMode
field and lay the first stone of a UI test scaffold for
PostIt.
1. Settings.DarkMode was previously a dead field. It round-
tripped through postit-settings.json and the SettingsPage
CheckBox, OnDarkModeChanged flipped IsDirty, and that was
it — no consumer ever read the value, so toggling the
CheckBox had no visible effect. The fix is in
App.OnFrameworkInitializationCompleted: read the value
Load() just populated and set
Application.Current.RequestedThemeVariant accordingly
(so a dark-mode user lands on a dark window on first
launch, not on a default-light window that flips after
the user touches the toggle), then subscribe to
settings.PropertyChanged and update the theme on every
DarkMode change. The consumer lives in App.axaml.cs, not
in Settings, so the Settings model stays free of any
Avalonia.Application dependency and the SettingsLoadTests
(which construct Settings outside an Avalonia host)
still pass unchanged.
2. MainPageViewModel had a vestigial [ObservableProperty]
ThemeVariant themeVariant = ThemeVariant.Default that no
XAML, no code, and no test ever read. It was the start of
a half-finished attempt to expose the theme variant on
the page VM. The dark-mode wiring above makes it
irrelevant: the theme is now driven by Application, not
by a VM property. The field is removed, along with the
using Avalonia.Styling; it pulled in (now unused).
3. SessionStatusBannerTests adds the first set of UI tests
for PostIt. They mount a real MainWindow via the headless
Avalonia host declared in TestApp.cs, attach a
SessionStatusViewModel as the banner's DataContext, and
assert the actual visual tree contents: three buttons
render (Se déconnecter, Se connecter, Paramètres), the
Login button is visible when logged out, the Logout
button is hidden when logged out, the Paramètres button
is visible regardless of session, and the session label
text reflects the VM. The pattern follows what
UnitTest1.MainPage_Should_Load already established:
[AvaloniaFact] (from Avalonia.Headless.XUnit) plus
new MainWindow() / window.Show(). A plain [Fact] cannot
drive Window..ctor() because the headless platform's
PlatformManager.CreateWindow() has no service registered
outside a dispatcher-aware test context; the
AvaloniaFact attribute provides that context. The
DataContext is set on the banner directly because
App.OnFrameworkInitializationCompleted is not called in
a unit test (production wiring is exercised by the
manual launch, not here).
Build: 0 errors. Tests: 5/5 SessionStatusBannerTests,
3/3 SettingsLoadTests, 1/1 MainPageTests (the existing
scaffold test, unchanged). The other PostIt.Tests suites
depend on the OIDC stub WebApplicationFactory and time out
on this network-restricted host.
2026-07-09 22:17:56 +01:00
|
|
|
|
2026-10-11 07:28:17 +01:00
|
|
|
var buttons = banner.GetVisualDescendants()
|
postIt: wire DarkMode, drop dead themeVariant, add UI tests for the banner
Three related changes that close the loop on the DarkMode
field and lay the first stone of a UI test scaffold for
PostIt.
1. Settings.DarkMode was previously a dead field. It round-
tripped through postit-settings.json and the SettingsPage
CheckBox, OnDarkModeChanged flipped IsDirty, and that was
it — no consumer ever read the value, so toggling the
CheckBox had no visible effect. The fix is in
App.OnFrameworkInitializationCompleted: read the value
Load() just populated and set
Application.Current.RequestedThemeVariant accordingly
(so a dark-mode user lands on a dark window on first
launch, not on a default-light window that flips after
the user touches the toggle), then subscribe to
settings.PropertyChanged and update the theme on every
DarkMode change. The consumer lives in App.axaml.cs, not
in Settings, so the Settings model stays free of any
Avalonia.Application dependency and the SettingsLoadTests
(which construct Settings outside an Avalonia host)
still pass unchanged.
2. MainPageViewModel had a vestigial [ObservableProperty]
ThemeVariant themeVariant = ThemeVariant.Default that no
XAML, no code, and no test ever read. It was the start of
a half-finished attempt to expose the theme variant on
the page VM. The dark-mode wiring above makes it
irrelevant: the theme is now driven by Application, not
by a VM property. The field is removed, along with the
using Avalonia.Styling; it pulled in (now unused).
3. SessionStatusBannerTests adds the first set of UI tests
for PostIt. They mount a real MainWindow via the headless
Avalonia host declared in TestApp.cs, attach a
SessionStatusViewModel as the banner's DataContext, and
assert the actual visual tree contents: three buttons
render (Se déconnecter, Se connecter, Paramètres), the
Login button is visible when logged out, the Logout
button is hidden when logged out, the Paramètres button
is visible regardless of session, and the session label
text reflects the VM. The pattern follows what
UnitTest1.MainPage_Should_Load already established:
[AvaloniaFact] (from Avalonia.Headless.XUnit) plus
new MainWindow() / window.Show(). A plain [Fact] cannot
drive Window..ctor() because the headless platform's
PlatformManager.CreateWindow() has no service registered
outside a dispatcher-aware test context; the
AvaloniaFact attribute provides that context. The
DataContext is set on the banner directly because
App.OnFrameworkInitializationCompleted is not called in
a unit test (production wiring is exercised by the
manual launch, not here).
Build: 0 errors. Tests: 5/5 SessionStatusBannerTests,
3/3 SettingsLoadTests, 1/1 MainPageTests (the existing
scaffold test, unchanged). The other PostIt.Tests suites
depend on the OIDC stub WebApplicationFactory and time out
on this network-restricted host.
2026-07-09 22:17:56 +01:00
|
|
|
.OfType<Button>()
|
|
|
|
|
.ToList();
|
|
|
|
|
|
2026-10-11 07:28:17 +01:00
|
|
|
Assert.Equal(4, buttons.Count);
|
postIt: wire DarkMode, drop dead themeVariant, add UI tests for the banner
Three related changes that close the loop on the DarkMode
field and lay the first stone of a UI test scaffold for
PostIt.
1. Settings.DarkMode was previously a dead field. It round-
tripped through postit-settings.json and the SettingsPage
CheckBox, OnDarkModeChanged flipped IsDirty, and that was
it — no consumer ever read the value, so toggling the
CheckBox had no visible effect. The fix is in
App.OnFrameworkInitializationCompleted: read the value
Load() just populated and set
Application.Current.RequestedThemeVariant accordingly
(so a dark-mode user lands on a dark window on first
launch, not on a default-light window that flips after
the user touches the toggle), then subscribe to
settings.PropertyChanged and update the theme on every
DarkMode change. The consumer lives in App.axaml.cs, not
in Settings, so the Settings model stays free of any
Avalonia.Application dependency and the SettingsLoadTests
(which construct Settings outside an Avalonia host)
still pass unchanged.
2. MainPageViewModel had a vestigial [ObservableProperty]
ThemeVariant themeVariant = ThemeVariant.Default that no
XAML, no code, and no test ever read. It was the start of
a half-finished attempt to expose the theme variant on
the page VM. The dark-mode wiring above makes it
irrelevant: the theme is now driven by Application, not
by a VM property. The field is removed, along with the
using Avalonia.Styling; it pulled in (now unused).
3. SessionStatusBannerTests adds the first set of UI tests
for PostIt. They mount a real MainWindow via the headless
Avalonia host declared in TestApp.cs, attach a
SessionStatusViewModel as the banner's DataContext, and
assert the actual visual tree contents: three buttons
render (Se déconnecter, Se connecter, Paramètres), the
Login button is visible when logged out, the Logout
button is hidden when logged out, the Paramètres button
is visible regardless of session, and the session label
text reflects the VM. The pattern follows what
UnitTest1.MainPage_Should_Load already established:
[AvaloniaFact] (from Avalonia.Headless.XUnit) plus
new MainWindow() / window.Show(). A plain [Fact] cannot
drive Window..ctor() because the headless platform's
PlatformManager.CreateWindow() has no service registered
outside a dispatcher-aware test context; the
AvaloniaFact attribute provides that context. The
DataContext is set on the banner directly because
App.OnFrameworkInitializationCompleted is not called in
a unit test (production wiring is exercised by the
manual launch, not here).
Build: 0 errors. Tests: 5/5 SessionStatusBannerTests,
3/3 SettingsLoadTests, 1/1 MainPageTests (the existing
scaffold test, unchanged). The other PostIt.Tests suites
depend on the OIDC stub WebApplicationFactory and time out
on this network-restricted host.
2026-07-09 22:17:56 +01:00
|
|
|
Assert.Contains(buttons, b => b.Content as string == "Se déconnecter");
|
|
|
|
|
Assert.Contains(buttons, b => b.Content as string == "Se connecter");
|
|
|
|
|
Assert.Contains(buttons, b => b.Content as string == "Paramètres");
|
2026-10-11 07:28:17 +01:00
|
|
|
Assert.Contains(buttons, b => b.Content as string == "À propos");
|
postIt: wire DarkMode, drop dead themeVariant, add UI tests for the banner
Three related changes that close the loop on the DarkMode
field and lay the first stone of a UI test scaffold for
PostIt.
1. Settings.DarkMode was previously a dead field. It round-
tripped through postit-settings.json and the SettingsPage
CheckBox, OnDarkModeChanged flipped IsDirty, and that was
it — no consumer ever read the value, so toggling the
CheckBox had no visible effect. The fix is in
App.OnFrameworkInitializationCompleted: read the value
Load() just populated and set
Application.Current.RequestedThemeVariant accordingly
(so a dark-mode user lands on a dark window on first
launch, not on a default-light window that flips after
the user touches the toggle), then subscribe to
settings.PropertyChanged and update the theme on every
DarkMode change. The consumer lives in App.axaml.cs, not
in Settings, so the Settings model stays free of any
Avalonia.Application dependency and the SettingsLoadTests
(which construct Settings outside an Avalonia host)
still pass unchanged.
2. MainPageViewModel had a vestigial [ObservableProperty]
ThemeVariant themeVariant = ThemeVariant.Default that no
XAML, no code, and no test ever read. It was the start of
a half-finished attempt to expose the theme variant on
the page VM. The dark-mode wiring above makes it
irrelevant: the theme is now driven by Application, not
by a VM property. The field is removed, along with the
using Avalonia.Styling; it pulled in (now unused).
3. SessionStatusBannerTests adds the first set of UI tests
for PostIt. They mount a real MainWindow via the headless
Avalonia host declared in TestApp.cs, attach a
SessionStatusViewModel as the banner's DataContext, and
assert the actual visual tree contents: three buttons
render (Se déconnecter, Se connecter, Paramètres), the
Login button is visible when logged out, the Logout
button is hidden when logged out, the Paramètres button
is visible regardless of session, and the session label
text reflects the VM. The pattern follows what
UnitTest1.MainPage_Should_Load already established:
[AvaloniaFact] (from Avalonia.Headless.XUnit) plus
new MainWindow() / window.Show(). A plain [Fact] cannot
drive Window..ctor() because the headless platform's
PlatformManager.CreateWindow() has no service registered
outside a dispatcher-aware test context; the
AvaloniaFact attribute provides that context. The
DataContext is set on the banner directly because
App.OnFrameworkInitializationCompleted is not called in
a unit test (production wiring is exercised by the
manual launch, not here).
Build: 0 errors. Tests: 5/5 SessionStatusBannerTests,
3/3 SettingsLoadTests, 1/1 MainPageTests (the existing
scaffold test, unchanged). The other PostIt.Tests suites
depend on the OIDC stub WebApplicationFactory and time out
on this network-restricted host.
2026-07-09 22:17:56 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[AvaloniaFact]
|
|
|
|
|
public void Banner_login_button_is_visible_when_logged_out()
|
|
|
|
|
{
|
2026-10-11 07:28:17 +01:00
|
|
|
SessionStatusBanner banner = CreateBanner();
|
postIt: wire DarkMode, drop dead themeVariant, add UI tests for the banner
Three related changes that close the loop on the DarkMode
field and lay the first stone of a UI test scaffold for
PostIt.
1. Settings.DarkMode was previously a dead field. It round-
tripped through postit-settings.json and the SettingsPage
CheckBox, OnDarkModeChanged flipped IsDirty, and that was
it — no consumer ever read the value, so toggling the
CheckBox had no visible effect. The fix is in
App.OnFrameworkInitializationCompleted: read the value
Load() just populated and set
Application.Current.RequestedThemeVariant accordingly
(so a dark-mode user lands on a dark window on first
launch, not on a default-light window that flips after
the user touches the toggle), then subscribe to
settings.PropertyChanged and update the theme on every
DarkMode change. The consumer lives in App.axaml.cs, not
in Settings, so the Settings model stays free of any
Avalonia.Application dependency and the SettingsLoadTests
(which construct Settings outside an Avalonia host)
still pass unchanged.
2. MainPageViewModel had a vestigial [ObservableProperty]
ThemeVariant themeVariant = ThemeVariant.Default that no
XAML, no code, and no test ever read. It was the start of
a half-finished attempt to expose the theme variant on
the page VM. The dark-mode wiring above makes it
irrelevant: the theme is now driven by Application, not
by a VM property. The field is removed, along with the
using Avalonia.Styling; it pulled in (now unused).
3. SessionStatusBannerTests adds the first set of UI tests
for PostIt. They mount a real MainWindow via the headless
Avalonia host declared in TestApp.cs, attach a
SessionStatusViewModel as the banner's DataContext, and
assert the actual visual tree contents: three buttons
render (Se déconnecter, Se connecter, Paramètres), the
Login button is visible when logged out, the Logout
button is hidden when logged out, the Paramètres button
is visible regardless of session, and the session label
text reflects the VM. The pattern follows what
UnitTest1.MainPage_Should_Load already established:
[AvaloniaFact] (from Avalonia.Headless.XUnit) plus
new MainWindow() / window.Show(). A plain [Fact] cannot
drive Window..ctor() because the headless platform's
PlatformManager.CreateWindow() has no service registered
outside a dispatcher-aware test context; the
AvaloniaFact attribute provides that context. The
DataContext is set on the banner directly because
App.OnFrameworkInitializationCompleted is not called in
a unit test (production wiring is exercised by the
manual launch, not here).
Build: 0 errors. Tests: 5/5 SessionStatusBannerTests,
3/3 SettingsLoadTests, 1/1 MainPageTests (the existing
scaffold test, unchanged). The other PostIt.Tests suites
depend on the OIDC stub WebApplicationFactory and time out
on this network-restricted host.
2026-07-09 22:17:56 +01:00
|
|
|
|
2026-10-11 07:28:17 +01:00
|
|
|
var login = banner.GetVisualDescendants()
|
postIt: wire DarkMode, drop dead themeVariant, add UI tests for the banner
Three related changes that close the loop on the DarkMode
field and lay the first stone of a UI test scaffold for
PostIt.
1. Settings.DarkMode was previously a dead field. It round-
tripped through postit-settings.json and the SettingsPage
CheckBox, OnDarkModeChanged flipped IsDirty, and that was
it — no consumer ever read the value, so toggling the
CheckBox had no visible effect. The fix is in
App.OnFrameworkInitializationCompleted: read the value
Load() just populated and set
Application.Current.RequestedThemeVariant accordingly
(so a dark-mode user lands on a dark window on first
launch, not on a default-light window that flips after
the user touches the toggle), then subscribe to
settings.PropertyChanged and update the theme on every
DarkMode change. The consumer lives in App.axaml.cs, not
in Settings, so the Settings model stays free of any
Avalonia.Application dependency and the SettingsLoadTests
(which construct Settings outside an Avalonia host)
still pass unchanged.
2. MainPageViewModel had a vestigial [ObservableProperty]
ThemeVariant themeVariant = ThemeVariant.Default that no
XAML, no code, and no test ever read. It was the start of
a half-finished attempt to expose the theme variant on
the page VM. The dark-mode wiring above makes it
irrelevant: the theme is now driven by Application, not
by a VM property. The field is removed, along with the
using Avalonia.Styling; it pulled in (now unused).
3. SessionStatusBannerTests adds the first set of UI tests
for PostIt. They mount a real MainWindow via the headless
Avalonia host declared in TestApp.cs, attach a
SessionStatusViewModel as the banner's DataContext, and
assert the actual visual tree contents: three buttons
render (Se déconnecter, Se connecter, Paramètres), the
Login button is visible when logged out, the Logout
button is hidden when logged out, the Paramètres button
is visible regardless of session, and the session label
text reflects the VM. The pattern follows what
UnitTest1.MainPage_Should_Load already established:
[AvaloniaFact] (from Avalonia.Headless.XUnit) plus
new MainWindow() / window.Show(). A plain [Fact] cannot
drive Window..ctor() because the headless platform's
PlatformManager.CreateWindow() has no service registered
outside a dispatcher-aware test context; the
AvaloniaFact attribute provides that context. The
DataContext is set on the banner directly because
App.OnFrameworkInitializationCompleted is not called in
a unit test (production wiring is exercised by the
manual launch, not here).
Build: 0 errors. Tests: 5/5 SessionStatusBannerTests,
3/3 SettingsLoadTests, 1/1 MainPageTests (the existing
scaffold test, unchanged). The other PostIt.Tests suites
depend on the OIDC stub WebApplicationFactory and time out
on this network-restricted host.
2026-07-09 22:17:56 +01:00
|
|
|
.OfType<Button>()
|
|
|
|
|
.Single(b => b.Content as string == "Se connecter");
|
|
|
|
|
|
|
|
|
|
// The XAML binds IsVisible to IsLoggedOut. After Show,
|
|
|
|
|
// the binding has been evaluated.
|
|
|
|
|
Assert.True(login.IsVisible);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[AvaloniaFact]
|
|
|
|
|
public void Banner_logout_button_is_hidden_when_logged_out()
|
|
|
|
|
{
|
2026-10-11 07:28:17 +01:00
|
|
|
SessionStatusBanner banner = CreateBanner();
|
2026-08-25 23:01:00 +01:00
|
|
|
|
2026-10-11 07:28:17 +01:00
|
|
|
Assert.False(Assert.IsType<SessionStatusViewModel>(banner.DataContext).IsLoggedIn);
|
2026-08-25 23:01:00 +01:00
|
|
|
var logout = banner.GetVisualDescendants()
|
postIt: wire DarkMode, drop dead themeVariant, add UI tests for the banner
Three related changes that close the loop on the DarkMode
field and lay the first stone of a UI test scaffold for
PostIt.
1. Settings.DarkMode was previously a dead field. It round-
tripped through postit-settings.json and the SettingsPage
CheckBox, OnDarkModeChanged flipped IsDirty, and that was
it — no consumer ever read the value, so toggling the
CheckBox had no visible effect. The fix is in
App.OnFrameworkInitializationCompleted: read the value
Load() just populated and set
Application.Current.RequestedThemeVariant accordingly
(so a dark-mode user lands on a dark window on first
launch, not on a default-light window that flips after
the user touches the toggle), then subscribe to
settings.PropertyChanged and update the theme on every
DarkMode change. The consumer lives in App.axaml.cs, not
in Settings, so the Settings model stays free of any
Avalonia.Application dependency and the SettingsLoadTests
(which construct Settings outside an Avalonia host)
still pass unchanged.
2. MainPageViewModel had a vestigial [ObservableProperty]
ThemeVariant themeVariant = ThemeVariant.Default that no
XAML, no code, and no test ever read. It was the start of
a half-finished attempt to expose the theme variant on
the page VM. The dark-mode wiring above makes it
irrelevant: the theme is now driven by Application, not
by a VM property. The field is removed, along with the
using Avalonia.Styling; it pulled in (now unused).
3. SessionStatusBannerTests adds the first set of UI tests
for PostIt. They mount a real MainWindow via the headless
Avalonia host declared in TestApp.cs, attach a
SessionStatusViewModel as the banner's DataContext, and
assert the actual visual tree contents: three buttons
render (Se déconnecter, Se connecter, Paramètres), the
Login button is visible when logged out, the Logout
button is hidden when logged out, the Paramètres button
is visible regardless of session, and the session label
text reflects the VM. The pattern follows what
UnitTest1.MainPage_Should_Load already established:
[AvaloniaFact] (from Avalonia.Headless.XUnit) plus
new MainWindow() / window.Show(). A plain [Fact] cannot
drive Window..ctor() because the headless platform's
PlatformManager.CreateWindow() has no service registered
outside a dispatcher-aware test context; the
AvaloniaFact attribute provides that context. The
DataContext is set on the banner directly because
App.OnFrameworkInitializationCompleted is not called in
a unit test (production wiring is exercised by the
manual launch, not here).
Build: 0 errors. Tests: 5/5 SessionStatusBannerTests,
3/3 SettingsLoadTests, 1/1 MainPageTests (the existing
scaffold test, unchanged). The other PostIt.Tests suites
depend on the OIDC stub WebApplicationFactory and time out
on this network-restricted host.
2026-07-09 22:17:56 +01:00
|
|
|
.OfType<Button>()
|
|
|
|
|
.Single(b => b.Content as string == "Se déconnecter");
|
|
|
|
|
|
|
|
|
|
Assert.False(logout.IsVisible);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[AvaloniaFact]
|
|
|
|
|
public void Banner_settings_button_is_visible_regardless_of_session()
|
|
|
|
|
{
|
2026-08-25 23:01:00 +01:00
|
|
|
SessionStatusBanner banner = CreateBanner();
|
postIt: wire DarkMode, drop dead themeVariant, add UI tests for the banner
Three related changes that close the loop on the DarkMode
field and lay the first stone of a UI test scaffold for
PostIt.
1. Settings.DarkMode was previously a dead field. It round-
tripped through postit-settings.json and the SettingsPage
CheckBox, OnDarkModeChanged flipped IsDirty, and that was
it — no consumer ever read the value, so toggling the
CheckBox had no visible effect. The fix is in
App.OnFrameworkInitializationCompleted: read the value
Load() just populated and set
Application.Current.RequestedThemeVariant accordingly
(so a dark-mode user lands on a dark window on first
launch, not on a default-light window that flips after
the user touches the toggle), then subscribe to
settings.PropertyChanged and update the theme on every
DarkMode change. The consumer lives in App.axaml.cs, not
in Settings, so the Settings model stays free of any
Avalonia.Application dependency and the SettingsLoadTests
(which construct Settings outside an Avalonia host)
still pass unchanged.
2. MainPageViewModel had a vestigial [ObservableProperty]
ThemeVariant themeVariant = ThemeVariant.Default that no
XAML, no code, and no test ever read. It was the start of
a half-finished attempt to expose the theme variant on
the page VM. The dark-mode wiring above makes it
irrelevant: the theme is now driven by Application, not
by a VM property. The field is removed, along with the
using Avalonia.Styling; it pulled in (now unused).
3. SessionStatusBannerTests adds the first set of UI tests
for PostIt. They mount a real MainWindow via the headless
Avalonia host declared in TestApp.cs, attach a
SessionStatusViewModel as the banner's DataContext, and
assert the actual visual tree contents: three buttons
render (Se déconnecter, Se connecter, Paramètres), the
Login button is visible when logged out, the Logout
button is hidden when logged out, the Paramètres button
is visible regardless of session, and the session label
text reflects the VM. The pattern follows what
UnitTest1.MainPage_Should_Load already established:
[AvaloniaFact] (from Avalonia.Headless.XUnit) plus
new MainWindow() / window.Show(). A plain [Fact] cannot
drive Window..ctor() because the headless platform's
PlatformManager.CreateWindow() has no service registered
outside a dispatcher-aware test context; the
AvaloniaFact attribute provides that context. The
DataContext is set on the banner directly because
App.OnFrameworkInitializationCompleted is not called in
a unit test (production wiring is exercised by the
manual launch, not here).
Build: 0 errors. Tests: 5/5 SessionStatusBannerTests,
3/3 SettingsLoadTests, 1/1 MainPageTests (the existing
scaffold test, unchanged). The other PostIt.Tests suites
depend on the OIDC stub WebApplicationFactory and time out
on this network-restricted host.
2026-07-09 22:17:56 +01:00
|
|
|
|
2026-08-25 23:01:00 +01:00
|
|
|
var settings = banner.GetVisualDescendants()
|
postIt: wire DarkMode, drop dead themeVariant, add UI tests for the banner
Three related changes that close the loop on the DarkMode
field and lay the first stone of a UI test scaffold for
PostIt.
1. Settings.DarkMode was previously a dead field. It round-
tripped through postit-settings.json and the SettingsPage
CheckBox, OnDarkModeChanged flipped IsDirty, and that was
it — no consumer ever read the value, so toggling the
CheckBox had no visible effect. The fix is in
App.OnFrameworkInitializationCompleted: read the value
Load() just populated and set
Application.Current.RequestedThemeVariant accordingly
(so a dark-mode user lands on a dark window on first
launch, not on a default-light window that flips after
the user touches the toggle), then subscribe to
settings.PropertyChanged and update the theme on every
DarkMode change. The consumer lives in App.axaml.cs, not
in Settings, so the Settings model stays free of any
Avalonia.Application dependency and the SettingsLoadTests
(which construct Settings outside an Avalonia host)
still pass unchanged.
2. MainPageViewModel had a vestigial [ObservableProperty]
ThemeVariant themeVariant = ThemeVariant.Default that no
XAML, no code, and no test ever read. It was the start of
a half-finished attempt to expose the theme variant on
the page VM. The dark-mode wiring above makes it
irrelevant: the theme is now driven by Application, not
by a VM property. The field is removed, along with the
using Avalonia.Styling; it pulled in (now unused).
3. SessionStatusBannerTests adds the first set of UI tests
for PostIt. They mount a real MainWindow via the headless
Avalonia host declared in TestApp.cs, attach a
SessionStatusViewModel as the banner's DataContext, and
assert the actual visual tree contents: three buttons
render (Se déconnecter, Se connecter, Paramètres), the
Login button is visible when logged out, the Logout
button is hidden when logged out, the Paramètres button
is visible regardless of session, and the session label
text reflects the VM. The pattern follows what
UnitTest1.MainPage_Should_Load already established:
[AvaloniaFact] (from Avalonia.Headless.XUnit) plus
new MainWindow() / window.Show(). A plain [Fact] cannot
drive Window..ctor() because the headless platform's
PlatformManager.CreateWindow() has no service registered
outside a dispatcher-aware test context; the
AvaloniaFact attribute provides that context. The
DataContext is set on the banner directly because
App.OnFrameworkInitializationCompleted is not called in
a unit test (production wiring is exercised by the
manual launch, not here).
Build: 0 errors. Tests: 5/5 SessionStatusBannerTests,
3/3 SettingsLoadTests, 1/1 MainPageTests (the existing
scaffold test, unchanged). The other PostIt.Tests suites
depend on the OIDC stub WebApplicationFactory and time out
on this network-restricted host.
2026-07-09 22:17:56 +01:00
|
|
|
.OfType<Button>()
|
|
|
|
|
.Single(b => b.Content as string == "Paramètres");
|
|
|
|
|
|
2026-10-11 07:28:17 +01:00
|
|
|
// Paramètres has no IsVisible binding and is always shown.
|
postIt: wire DarkMode, drop dead themeVariant, add UI tests for the banner
Three related changes that close the loop on the DarkMode
field and lay the first stone of a UI test scaffold for
PostIt.
1. Settings.DarkMode was previously a dead field. It round-
tripped through postit-settings.json and the SettingsPage
CheckBox, OnDarkModeChanged flipped IsDirty, and that was
it — no consumer ever read the value, so toggling the
CheckBox had no visible effect. The fix is in
App.OnFrameworkInitializationCompleted: read the value
Load() just populated and set
Application.Current.RequestedThemeVariant accordingly
(so a dark-mode user lands on a dark window on first
launch, not on a default-light window that flips after
the user touches the toggle), then subscribe to
settings.PropertyChanged and update the theme on every
DarkMode change. The consumer lives in App.axaml.cs, not
in Settings, so the Settings model stays free of any
Avalonia.Application dependency and the SettingsLoadTests
(which construct Settings outside an Avalonia host)
still pass unchanged.
2. MainPageViewModel had a vestigial [ObservableProperty]
ThemeVariant themeVariant = ThemeVariant.Default that no
XAML, no code, and no test ever read. It was the start of
a half-finished attempt to expose the theme variant on
the page VM. The dark-mode wiring above makes it
irrelevant: the theme is now driven by Application, not
by a VM property. The field is removed, along with the
using Avalonia.Styling; it pulled in (now unused).
3. SessionStatusBannerTests adds the first set of UI tests
for PostIt. They mount a real MainWindow via the headless
Avalonia host declared in TestApp.cs, attach a
SessionStatusViewModel as the banner's DataContext, and
assert the actual visual tree contents: three buttons
render (Se déconnecter, Se connecter, Paramètres), the
Login button is visible when logged out, the Logout
button is hidden when logged out, the Paramètres button
is visible regardless of session, and the session label
text reflects the VM. The pattern follows what
UnitTest1.MainPage_Should_Load already established:
[AvaloniaFact] (from Avalonia.Headless.XUnit) plus
new MainWindow() / window.Show(). A plain [Fact] cannot
drive Window..ctor() because the headless platform's
PlatformManager.CreateWindow() has no service registered
outside a dispatcher-aware test context; the
AvaloniaFact attribute provides that context. The
DataContext is set on the banner directly because
App.OnFrameworkInitializationCompleted is not called in
a unit test (production wiring is exercised by the
manual launch, not here).
Build: 0 errors. Tests: 5/5 SessionStatusBannerTests,
3/3 SettingsLoadTests, 1/1 MainPageTests (the existing
scaffold test, unchanged). The other PostIt.Tests suites
depend on the OIDC stub WebApplicationFactory and time out
on this network-restricted host.
2026-07-09 22:17:56 +01:00
|
|
|
Assert.True(settings.IsVisible);
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-11 07:28:17 +01:00
|
|
|
private SessionStatusBanner CreateBanner()
|
2026-08-25 23:01:00 +01:00
|
|
|
{
|
2026-10-11 07:28:17 +01:00
|
|
|
_window = new MainWindow();
|
|
|
|
|
_window.Show();
|
|
|
|
|
var banner = _window.GetVisualDescendants()
|
|
|
|
|
.OfType<SessionStatusBanner>()
|
|
|
|
|
.Single();
|
|
|
|
|
banner.DataContext = new SessionStatusViewModel();
|
2026-08-25 23:01:00 +01:00
|
|
|
return banner;
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-11 07:28:17 +01:00
|
|
|
public void Dispose() => _window?.Close();
|
|
|
|
|
|
postIt: wire DarkMode, drop dead themeVariant, add UI tests for the banner
Three related changes that close the loop on the DarkMode
field and lay the first stone of a UI test scaffold for
PostIt.
1. Settings.DarkMode was previously a dead field. It round-
tripped through postit-settings.json and the SettingsPage
CheckBox, OnDarkModeChanged flipped IsDirty, and that was
it — no consumer ever read the value, so toggling the
CheckBox had no visible effect. The fix is in
App.OnFrameworkInitializationCompleted: read the value
Load() just populated and set
Application.Current.RequestedThemeVariant accordingly
(so a dark-mode user lands on a dark window on first
launch, not on a default-light window that flips after
the user touches the toggle), then subscribe to
settings.PropertyChanged and update the theme on every
DarkMode change. The consumer lives in App.axaml.cs, not
in Settings, so the Settings model stays free of any
Avalonia.Application dependency and the SettingsLoadTests
(which construct Settings outside an Avalonia host)
still pass unchanged.
2. MainPageViewModel had a vestigial [ObservableProperty]
ThemeVariant themeVariant = ThemeVariant.Default that no
XAML, no code, and no test ever read. It was the start of
a half-finished attempt to expose the theme variant on
the page VM. The dark-mode wiring above makes it
irrelevant: the theme is now driven by Application, not
by a VM property. The field is removed, along with the
using Avalonia.Styling; it pulled in (now unused).
3. SessionStatusBannerTests adds the first set of UI tests
for PostIt. They mount a real MainWindow via the headless
Avalonia host declared in TestApp.cs, attach a
SessionStatusViewModel as the banner's DataContext, and
assert the actual visual tree contents: three buttons
render (Se déconnecter, Se connecter, Paramètres), the
Login button is visible when logged out, the Logout
button is hidden when logged out, the Paramètres button
is visible regardless of session, and the session label
text reflects the VM. The pattern follows what
UnitTest1.MainPage_Should_Load already established:
[AvaloniaFact] (from Avalonia.Headless.XUnit) plus
new MainWindow() / window.Show(). A plain [Fact] cannot
drive Window..ctor() because the headless platform's
PlatformManager.CreateWindow() has no service registered
outside a dispatcher-aware test context; the
AvaloniaFact attribute provides that context. The
DataContext is set on the banner directly because
App.OnFrameworkInitializationCompleted is not called in
a unit test (production wiring is exercised by the
manual launch, not here).
Build: 0 errors. Tests: 5/5 SessionStatusBannerTests,
3/3 SettingsLoadTests, 1/1 MainPageTests (the existing
scaffold test, unchanged). The other PostIt.Tests suites
depend on the OIDC stub WebApplicationFactory and time out
on this network-restricted host.
2026-07-09 22:17:56 +01:00
|
|
|
[AvaloniaFact]
|
|
|
|
|
public void Banner_session_label_reflects_DataContext()
|
|
|
|
|
{
|
2026-08-25 23:01:00 +01:00
|
|
|
SessionStatusBanner banner = CreateBanner();
|
|
|
|
|
var label = banner.GetVisualDescendants()
|
postIt: wire DarkMode, drop dead themeVariant, add UI tests for the banner
Three related changes that close the loop on the DarkMode
field and lay the first stone of a UI test scaffold for
PostIt.
1. Settings.DarkMode was previously a dead field. It round-
tripped through postit-settings.json and the SettingsPage
CheckBox, OnDarkModeChanged flipped IsDirty, and that was
it — no consumer ever read the value, so toggling the
CheckBox had no visible effect. The fix is in
App.OnFrameworkInitializationCompleted: read the value
Load() just populated and set
Application.Current.RequestedThemeVariant accordingly
(so a dark-mode user lands on a dark window on first
launch, not on a default-light window that flips after
the user touches the toggle), then subscribe to
settings.PropertyChanged and update the theme on every
DarkMode change. The consumer lives in App.axaml.cs, not
in Settings, so the Settings model stays free of any
Avalonia.Application dependency and the SettingsLoadTests
(which construct Settings outside an Avalonia host)
still pass unchanged.
2. MainPageViewModel had a vestigial [ObservableProperty]
ThemeVariant themeVariant = ThemeVariant.Default that no
XAML, no code, and no test ever read. It was the start of
a half-finished attempt to expose the theme variant on
the page VM. The dark-mode wiring above makes it
irrelevant: the theme is now driven by Application, not
by a VM property. The field is removed, along with the
using Avalonia.Styling; it pulled in (now unused).
3. SessionStatusBannerTests adds the first set of UI tests
for PostIt. They mount a real MainWindow via the headless
Avalonia host declared in TestApp.cs, attach a
SessionStatusViewModel as the banner's DataContext, and
assert the actual visual tree contents: three buttons
render (Se déconnecter, Se connecter, Paramètres), the
Login button is visible when logged out, the Logout
button is hidden when logged out, the Paramètres button
is visible regardless of session, and the session label
text reflects the VM. The pattern follows what
UnitTest1.MainPage_Should_Load already established:
[AvaloniaFact] (from Avalonia.Headless.XUnit) plus
new MainWindow() / window.Show(). A plain [Fact] cannot
drive Window..ctor() because the headless platform's
PlatformManager.CreateWindow() has no service registered
outside a dispatcher-aware test context; the
AvaloniaFact attribute provides that context. The
DataContext is set on the banner directly because
App.OnFrameworkInitializationCompleted is not called in
a unit test (production wiring is exercised by the
manual launch, not here).
Build: 0 errors. Tests: 5/5 SessionStatusBannerTests,
3/3 SettingsLoadTests, 1/1 MainPageTests (the existing
scaffold test, unchanged). The other PostIt.Tests suites
depend on the OIDC stub WebApplicationFactory and time out
on this network-restricted host.
2026-07-09 22:17:56 +01:00
|
|
|
.OfType<TextBlock>()
|
|
|
|
|
.First(t => t.Text == "Déconnecté" || t.Text == "Connecté");
|
|
|
|
|
|
|
|
|
|
// Default SessionLabel is "Déconnecté" until Refresh()
|
|
|
|
|
// is called with a valid session. This pins the default
|
|
|
|
|
// so a future refactor that breaks the initial value
|
|
|
|
|
// (e.g. by removing the field initialiser) is caught.
|
|
|
|
|
Assert.Equal("Déconnecté", label.Text);
|
|
|
|
|
}
|
|
|
|
|
}
|