mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-29 07:16:33 +08:00
196 lines
6.7 KiB
C#
196 lines
6.7 KiB
C#
using System.Reflection;
|
|
using AtomUI.Controls.Primitives;
|
|
using AtomUI.Desktop.Controls.DesignTokens;
|
|
using Avalonia;
|
|
using Avalonia.Controls;
|
|
using Avalonia.Headless;
|
|
using Avalonia.Layout;
|
|
using Avalonia.Media;
|
|
using Avalonia.Threading;
|
|
using Avalonia.VisualTree;
|
|
using Shouldly;
|
|
using Xunit;
|
|
using AvaloniaWindow = Avalonia.Controls.Window;
|
|
|
|
namespace AtomUI.Desktop.Controls.Tests.Steps;
|
|
|
|
public class StepsConnectorTests
|
|
{
|
|
static StepsConnectorTests()
|
|
{
|
|
AvaloniaTestApp.EnsureInitialized();
|
|
}
|
|
|
|
[Fact]
|
|
public void Connector_Uses_The_Next_Items_Effective_Status_Color()
|
|
{
|
|
var steps = CreateSteps(Orientation.Horizontal);
|
|
steps.Items[0].ShouldBeOfType<Desktop.Controls.StepsItem>().Status = Desktop.Controls.StepsStatus.Finish;
|
|
steps.Items[1].ShouldBeOfType<Desktop.Controls.StepsItem>().Status = Desktop.Controls.StepsStatus.Error;
|
|
|
|
ShowInWindow(steps, () =>
|
|
{
|
|
var first = steps.Items[0].ShouldBeOfType<Desktop.Controls.StepsItem>();
|
|
var connector = FindConnector(first);
|
|
var expected = GetThemeResource<IBrush>(StepsTokenKind.ErrorTailColor);
|
|
|
|
first.ConnectorStatus.ShouldBe(Desktop.Controls.StepsStatus.Error);
|
|
GetColor(connector.Background).ShouldBe(GetColor(expected));
|
|
});
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(Orientation.Horizontal)]
|
|
[InlineData(Orientation.Vertical)]
|
|
public void Connector_Uses_Orientation_And_Last_Item_Visibility(Orientation orientation)
|
|
{
|
|
var steps = CreateSteps(orientation);
|
|
|
|
ShowInWindow(steps, () =>
|
|
{
|
|
var firstConnector = FindConnector(steps.Items[0].ShouldBeOfType<Desktop.Controls.StepsItem>());
|
|
var lastConnector = FindConnector(steps.Items[2].ShouldBeOfType<Desktop.Controls.StepsItem>());
|
|
|
|
firstConnector.IsVisible.ShouldBeTrue();
|
|
lastConnector.IsVisible.ShouldBeFalse();
|
|
if (orientation == Orientation.Horizontal)
|
|
{
|
|
firstConnector.Bounds.Width.ShouldBeGreaterThan(firstConnector.Bounds.Height);
|
|
}
|
|
else
|
|
{
|
|
firstConnector.Bounds.Height.ShouldBeGreaterThan(firstConnector.Bounds.Width);
|
|
}
|
|
});
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(StepsType.Default, Orientation.Horizontal)]
|
|
[InlineData(StepsType.Default, Orientation.Vertical)]
|
|
[InlineData(StepsType.Dot, Orientation.Horizontal)]
|
|
[InlineData(StepsType.OutlineDot, Orientation.Horizontal)]
|
|
[InlineData(StepsType.Inline, Orientation.Horizontal)]
|
|
public void Natural_Size_Reserves_Visible_Connectors_For_Short_Headings(
|
|
StepsType type, Orientation titlePlacement)
|
|
{
|
|
var steps = new Desktop.Controls.Steps
|
|
{
|
|
HorizontalAlignment = HorizontalAlignment.Left,
|
|
Type = type,
|
|
TitlePlacement = titlePlacement,
|
|
SizeType = AtomUI.SizeType.Small
|
|
};
|
|
for (var index = 1; index <= 4; index++)
|
|
{
|
|
steps.Items.Add(new StepsItem { Header = index.ToString() });
|
|
}
|
|
|
|
ShowInWindow(steps, () =>
|
|
{
|
|
steps.Bounds.Width.ShouldBeLessThan(800);
|
|
var items = steps.Items.Cast<StepsItem>().ToArray();
|
|
foreach (var item in items.Take(3))
|
|
{
|
|
var connector = FindConnector(item);
|
|
connector.IsVisible.ShouldBeTrue();
|
|
connector.Bounds.Width.ShouldBeGreaterThan(connector.Bounds.Height);
|
|
connector.Background.ShouldNotBeNull();
|
|
}
|
|
FindConnector(items[^1]).IsVisible.ShouldBeFalse();
|
|
});
|
|
}
|
|
|
|
[Fact]
|
|
public void Every_Remaining_Steps_Token_Has_A_Theme_Consumer()
|
|
{
|
|
var themeSource = string.Join(
|
|
Environment.NewLine,
|
|
ReadRepoFile("src/AtomUI.Desktop.Controls/Steps/Themes/StepsTheme.axaml"),
|
|
ReadRepoFile("src/AtomUI.Desktop.Controls/Steps/Themes/StepsItemTheme.axaml"),
|
|
ReadRepoFile("src/AtomUI.Desktop.Controls/Steps/Themes/StepsItemIndicatorTheme.axaml"));
|
|
|
|
var unconsumed = typeof(Desktop.Controls.StepsToken)
|
|
.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)
|
|
.Select(property => property.Name)
|
|
.Where(name => !themeSource.Contains($"StepsTokenResource {name}", StringComparison.Ordinal))
|
|
.ToArray();
|
|
|
|
unconsumed.ShouldBeEmpty();
|
|
}
|
|
|
|
private static Desktop.Controls.Steps CreateSteps(Orientation orientation)
|
|
{
|
|
var steps = new Desktop.Controls.Steps
|
|
{
|
|
Width = 720,
|
|
Current = 0,
|
|
Type = Desktop.Controls.StepsType.Default,
|
|
Orientation = orientation
|
|
};
|
|
steps.Items.Add(new Desktop.Controls.StepsItem { Header = "First", Content = "Content" });
|
|
steps.Items.Add(new Desktop.Controls.StepsItem { Header = "Second", Content = "Content" });
|
|
steps.Items.Add(new Desktop.Controls.StepsItem { Header = "Last", Content = "Content" });
|
|
return steps;
|
|
}
|
|
|
|
private static PixelAlignedBorder FindConnector(Desktop.Controls.StepsItem item)
|
|
{
|
|
return item.GetVisualDescendants()
|
|
.OfType<PixelAlignedBorder>()
|
|
.Single(control => control.Name == "Connector");
|
|
}
|
|
|
|
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 string ReadRepoFile(string relativePath)
|
|
{
|
|
for (var directory = new DirectoryInfo(AppContext.BaseDirectory);
|
|
directory is not null;
|
|
directory = directory.Parent)
|
|
{
|
|
var path = Path.Combine(directory.FullName, relativePath);
|
|
if (File.Exists(path))
|
|
{
|
|
return File.ReadAllText(path);
|
|
}
|
|
}
|
|
|
|
throw new FileNotFoundException(relativePath);
|
|
}
|
|
|
|
private static void ShowInWindow(Control content, Action assertion)
|
|
{
|
|
var window = new AvaloniaWindow
|
|
{
|
|
Width = 900,
|
|
Height = 420,
|
|
Content = content
|
|
};
|
|
|
|
try
|
|
{
|
|
window.Show();
|
|
Dispatcher.UIThread.RunJobs();
|
|
AvaloniaHeadlessPlatform.ForceRenderTimerTick(1);
|
|
Dispatcher.UIThread.RunJobs();
|
|
assertion();
|
|
}
|
|
finally
|
|
{
|
|
window.Close();
|
|
}
|
|
}
|
|
}
|