mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-18 22:46:38 +08:00
220 lines
9.2 KiB
C#
220 lines
9.2 KiB
C#
using AtomUI.Controls.Primitives;
|
|
using AtomUI.Desktop.Controls.DesignTokens;
|
|
using AtomUI.Theme.Resources;
|
|
using Avalonia;
|
|
using Avalonia.Controls;
|
|
using Avalonia.Controls.Presenters;
|
|
using Avalonia.Headless;
|
|
using Avalonia.Layout;
|
|
using Avalonia.Media;
|
|
using Avalonia.Threading;
|
|
using Avalonia.VisualTree;
|
|
using Shouldly;
|
|
using Xunit;
|
|
using AvaloniaWindow = Avalonia.Controls.Window;
|
|
using AtomUISizeType = AtomUI.SizeType;
|
|
|
|
namespace AtomUI.Desktop.Controls.Tests.Steps;
|
|
|
|
public class StepsPanelVisualTests
|
|
{
|
|
static StepsPanelVisualTests()
|
|
{
|
|
AvaloniaTestApp.EnsureInitialized();
|
|
}
|
|
|
|
[Fact]
|
|
public void Panel_Variant_API_Is_Explicitly_Panel_Scoped()
|
|
{
|
|
var steps = new Desktop.Controls.Steps();
|
|
|
|
Desktop.Controls.Steps.PanelVariantProperty.Name.ShouldBe(nameof(Desktop.Controls.Steps.PanelVariant));
|
|
steps.PanelVariant.ShouldBe(Desktop.Controls.StepsPanelVariant.Filled);
|
|
typeof(Desktop.Controls.Steps).GetProperty("Variant").ShouldBeNull();
|
|
typeof(Desktop.Controls.Steps).GetField("VariantProperty").ShouldBeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public void Panel_Uses_Equal_Width_Items_And_Only_Shows_Arrow_On_NonLast_Items()
|
|
{
|
|
var steps = CreateSteps(Desktop.Controls.StepsPanelVariant.Filled, Orientation.Vertical);
|
|
|
|
ShowInWindow(steps, () =>
|
|
{
|
|
var items = steps.Items.Cast<Desktop.Controls.StepsItem>().ToArray();
|
|
items.Select(item => item.Bounds.Width).ShouldAllBe(width => width == items[0].Bounds.Width);
|
|
items.Select(item => item.Bounds.X).ShouldBe([0d, 240d, 480d]);
|
|
|
|
for (var index = 0; index < items.Length; index++)
|
|
{
|
|
var item = items[index];
|
|
FindControl(item, "PART_Indicator").IsVisible.ShouldBeFalse();
|
|
FindControl(item, "Connector").IsVisible.ShouldBeFalse();
|
|
FindControl(item, "PanelArrow").IsVisible.ShouldBe(index < items.Length - 1);
|
|
FindControl(item, "NavigationArrow").IsVisible.ShouldBeFalse();
|
|
|
|
var wrapper = FindControl(item, "ItemWrapper");
|
|
wrapper.Bounds.Size.ShouldBe(item.Bounds.Size);
|
|
}
|
|
});
|
|
}
|
|
|
|
[Fact]
|
|
public void Panel_Outlined_Uses_Container_Background_And_Current_Primary_Background()
|
|
{
|
|
var steps = CreateSteps(Desktop.Controls.StepsPanelVariant.Outlined, Orientation.Horizontal);
|
|
|
|
ShowInWindow(steps, () =>
|
|
{
|
|
var items = steps.Items.Cast<Desktop.Controls.StepsItem>().ToArray();
|
|
var current = items[1];
|
|
var expectedBackground = GetThemeResource<IBrush>(SharedTokenKind.ColorBgContainer);
|
|
var expectedActive = GetThemeResource<IBrush>(SharedTokenKind.ColorPrimaryBg);
|
|
var expectedOutlinedText = GetThemeResource<IBrush>(StepsTokenKind.PanelProcessTextColor);
|
|
|
|
GetColor(items[0].Background).ShouldBe(GetColor(expectedBackground));
|
|
GetColor(current.Background).ShouldBe(GetColor(expectedActive));
|
|
current.BorderBrush.ShouldNotBeNull();
|
|
GetColor(current.Foreground).ShouldBe(GetColor(expectedOutlinedText));
|
|
GetColor(((ContentPresenter)FindControl(current, "SubHeaderPresenter")).Foreground).ShouldBe(GetColor(expectedOutlinedText));
|
|
GetColor(((ContentPresenter)FindControl(current, "ContentPresenter")).Foreground).ShouldBe(GetColor(expectedOutlinedText));
|
|
|
|
var currentArrow = (Desktop.Controls.StepsPanelArrow)FindControl(current, "PanelArrow");
|
|
var strokeInset = currentArrow.StrokeThickness / 2;
|
|
currentArrow.Bounds.Top.ShouldBe(strokeInset);
|
|
currentArrow.Bounds.Bottom.ShouldBe(current.Bounds.Height - strokeInset);
|
|
|
|
steps.PanelVariant = Desktop.Controls.StepsPanelVariant.Filled;
|
|
Dispatcher.UIThread.RunJobs();
|
|
AvaloniaHeadlessPlatform.ForceRenderTimerTick(1);
|
|
Dispatcher.UIThread.RunJobs();
|
|
GetColor(current.Background).ShouldBe(GetColor(GetThemeResource<IBrush>(StepsTokenKind.ProcessIconBgColor)));
|
|
var expectedFilledText = GetThemeResource<IBrush>(StepsTokenKind.PanelActiveTextColor);
|
|
GetColor(current.Foreground).ShouldBe(GetColor(expectedFilledText));
|
|
GetColor(((ContentPresenter)FindControl(current, "SubHeaderPresenter")).Foreground).ShouldBe(GetColor(expectedFilledText));
|
|
GetColor(((ContentPresenter)FindControl(current, "ContentPresenter")).Foreground).ShouldBe(GetColor(expectedFilledText));
|
|
currentArrow.Bounds.Top.ShouldBe(0);
|
|
currentArrow.Bounds.Bottom.ShouldBe(current.Bounds.Height);
|
|
});
|
|
}
|
|
|
|
[Fact]
|
|
public void Panel_Outlined_NonCurrent_Error_Uses_Container_Background_And_Error_Border()
|
|
{
|
|
var steps = CreateSteps(Desktop.Controls.StepsPanelVariant.Outlined, Orientation.Horizontal);
|
|
steps.Current = 0;
|
|
var error = steps.Items.Cast<Desktop.Controls.StepsItem>().ElementAt(1);
|
|
error.Status = Desktop.Controls.StepsStatus.Error;
|
|
|
|
ShowInWindow(steps, () =>
|
|
{
|
|
GetColor(error.Background).ShouldBe(GetColor(GetThemeResource<IBrush>(SharedTokenKind.ColorBgContainer)));
|
|
GetColor(error.BorderBrush).ShouldBe(GetColor(GetThemeResource<IBrush>(SharedTokenKind.ColorError)));
|
|
GetColor(error.Foreground).ShouldBe(GetColor(GetThemeResource<IBrush>(StepsTokenKind.PanelErrorTextColor)));
|
|
|
|
steps.Current = 1;
|
|
Dispatcher.UIThread.RunJobs();
|
|
GetColor(error.Background).ShouldBe(GetColor(GetThemeResource<IBrush>(SharedTokenKind.ColorErrorBg)));
|
|
GetColor(error.Foreground).ShouldBe(GetColor(GetThemeResource<IBrush>(StepsTokenKind.PanelErrorTextColor)));
|
|
});
|
|
}
|
|
|
|
[Fact]
|
|
public void Panel_Arrow_Uses_Rtl_Overflow_Direction()
|
|
{
|
|
var steps = CreateSteps(Desktop.Controls.StepsPanelVariant.Filled, Orientation.Horizontal);
|
|
steps.FlowDirection = FlowDirection.RightToLeft;
|
|
|
|
ShowInWindow(steps, () =>
|
|
{
|
|
var first = steps.Items.Cast<Desktop.Controls.StepsItem>().First();
|
|
var arrow = FindControl(first, "PanelArrow");
|
|
arrow.Bounds.Right.ShouldBeLessThanOrEqualTo(2);
|
|
arrow.Bounds.Left.ShouldBeLessThan(0);
|
|
});
|
|
}
|
|
|
|
[Fact]
|
|
public void Panel_Filled_Clips_NonFirst_ItemFrame_And_Reserves_Arrow_Inset_For_Content()
|
|
{
|
|
var steps = CreateSteps(Desktop.Controls.StepsPanelVariant.Filled, Orientation.Horizontal);
|
|
|
|
ShowInWindow(steps, () =>
|
|
{
|
|
var items = steps.Items.Cast<Desktop.Controls.StepsItem>().ToArray();
|
|
var firstArrow = (Desktop.Controls.StepsPanelArrow)FindControl(items[0], "PanelArrow");
|
|
var secondWrapper = (Desktop.Controls.StepsPanelItemFrame)FindControl(items[1], "ItemWrapper");
|
|
var secondHeader = FindControl(items[1], "HeaderPresenter");
|
|
var secondContent = FindControl(items[1], "ContentPresenter");
|
|
|
|
firstArrow.Width.ShouldBeGreaterThan(0);
|
|
secondWrapper.BackgroundSizing.ShouldBe(BackgroundSizing.OuterBorderEdge);
|
|
secondWrapper.Clip.ShouldNotBeNull();
|
|
secondHeader.Bounds.Left.ShouldBeGreaterThanOrEqualTo(firstArrow.Width);
|
|
secondContent.Bounds.Left.ShouldBeGreaterThanOrEqualTo(firstArrow.Width);
|
|
});
|
|
}
|
|
|
|
private static Desktop.Controls.Steps CreateSteps(
|
|
Desktop.Controls.StepsPanelVariant panelVariant,
|
|
Orientation orientation)
|
|
{
|
|
var steps = new Desktop.Controls.Steps
|
|
{
|
|
Width = 720,
|
|
Height = 120,
|
|
Type = Desktop.Controls.StepsType.Panel,
|
|
PanelVariant = panelVariant,
|
|
Orientation = orientation,
|
|
SizeType = AtomUISizeType.Middle,
|
|
Current = 1
|
|
};
|
|
steps.Items.Add(new Desktop.Controls.StepsItem { Header = "First", SubHeader = "00:01", Content = "Content" });
|
|
steps.Items.Add(new Desktop.Controls.StepsItem { Header = "Second", SubHeader = "00:02", Content = "Content" });
|
|
steps.Items.Add(new Desktop.Controls.StepsItem { Header = "Last", SubHeader = "00:03", Content = "Content" });
|
|
return steps;
|
|
}
|
|
|
|
private static Control FindControl(Desktop.Controls.StepsItem item, string name)
|
|
{
|
|
return item.GetVisualDescendants().OfType<Control>().Single(control => control.Name == name);
|
|
}
|
|
|
|
private static T GetThemeResource<T>(object key)
|
|
{
|
|
var application = Application.Current.ShouldNotBeNull();
|
|
application.TryGetResource(key, application.ActualThemeVariant, out var value).ShouldBeTrue();
|
|
value.ShouldBeAssignableTo<T>();
|
|
return (T)value!;
|
|
}
|
|
|
|
private static Color GetColor(IBrush? brush)
|
|
{
|
|
brush.ShouldNotBeNull();
|
|
return ((ISolidColorBrush)brush!).Color;
|
|
}
|
|
|
|
private static void ShowInWindow(Control content, Action assertion)
|
|
{
|
|
var window = new AvaloniaWindow
|
|
{
|
|
Width = 900,
|
|
Height = 360,
|
|
Content = content
|
|
};
|
|
|
|
try
|
|
{
|
|
window.Show();
|
|
Dispatcher.UIThread.RunJobs();
|
|
AvaloniaHeadlessPlatform.ForceRenderTimerTick(1);
|
|
Dispatcher.UIThread.RunJobs();
|
|
assertion();
|
|
}
|
|
finally
|
|
{
|
|
window.Close();
|
|
}
|
|
}
|
|
}
|