using Avalonia; using Avalonia.Controls; using Avalonia.Headless.XUnit; using Avalonia.Threading; using Avalonia.VisualTree; using AvParser.Core.Settings; using AvParser.UI.Localization; using AvParser.UI.Navigation; using AvParser.UI.ViewModels; using AvParser.UI.Views; using ReactiveUI.Primitives.Concurrency; namespace AvParser.UI.HeadlessTests; public sealed class LocalizationViewTests : IDisposable { /// Leaves the localizer where the rest of the assembly expects it. public void Dispose() => Localizer.Instance.SetLanguage(AppLanguage.English); private static (ShellView View, ShellViewModel ViewModel) ShowShell() { var navigation = new NavigationService([new FakePage("Page.Dashboard"), new FakePage("Page.Parse")]); var viewModel = new ShellViewModel(navigation, new FakeThemeService(), ImmediateSequencer.Instance); var view = new ShellView { DataContext = viewModel }; new Window { Width = 1400, Height = 800, Content = view, }.Show(); Dispatcher.UIThread.RunJobs(); return (view, viewModel); } private static IReadOnlyList RailLabels(Visual view) => [ .. view.GetVisualDescendants() .OfType() .Where(block => block.Classes.Contains("navLabel")) .Select(block => block.Text ?? string.Empty), ]; [AvaloniaFact] public void Rendered_text_follows_the_language_without_rebuilding_the_view() { Localizer.Instance.SetLanguage(AppLanguage.English); var (view, _) = ShowShell(); var english = RailLabels(view); english.ShouldBe(["Dashboard", "Parse"]); Localizer.Instance.SetLanguage(AppLanguage.Russian); Dispatcher.UIThread.RunJobs(); // The same controls, not a rebuilt tree: this is the whole point of binding through the // localizer's indexer rather than resolving strings once at load. RailLabels(view).ShouldBe(["Обзор", "Разбор"]); } [AvaloniaFact] public void The_title_bar_follows_the_language_too() { Localizer.Instance.SetLanguage(AppLanguage.English); var (view, viewModel) = ShowShell(); var title = view.GetVisualDescendants().OfType().Single(block => block.Name == "ShellTitle"); title.Text.ShouldBe("Dashboard"); Localizer.Instance.SetLanguage(AppLanguage.Russian); Dispatcher.UIThread.RunJobs(); viewModel.Title.ShouldBe("Обзор"); title.Text.ShouldBe("Обзор"); } [AvaloniaFact] public void Loc_markup_resolves_a_static_caption() { Localizer.Instance.SetLanguage(AppLanguage.Russian); var (view, _) = ShowShell(); // Tooltips come from {l:Loc} rather than from a view model, so they exercise the markup // extension itself. var toggle = view.GetVisualDescendants().OfType