mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-27 12:17:42 +08:00
187 lines
8.1 KiB
C#
187 lines
8.1 KiB
C#
using System.Xml.Linq;
|
|
using AtomUI.Controls;
|
|
using Avalonia;
|
|
using Avalonia.Controls;
|
|
using Avalonia.Headless;
|
|
using Avalonia.Styling;
|
|
using Avalonia.Threading;
|
|
using Avalonia.VisualTree;
|
|
using Shouldly;
|
|
using Xunit;
|
|
using AvaloniaWindow = Avalonia.Controls.Window;
|
|
|
|
namespace AtomUI.Desktop.Controls.Tests.Upload;
|
|
|
|
public class UploadDropVisualContractTests
|
|
{
|
|
private static readonly XNamespace AvaloniaNamespace = "https://github.com/avaloniaui";
|
|
|
|
[Fact]
|
|
public void Drop_Themes_Keep_The_Existing_Default_Visual_Contract()
|
|
{
|
|
var dropZoneTheme = XDocument.Load(GetRepoFile(
|
|
"src/AtomUI.Desktop.Controls/Upload/Themes/UploadDropZoneTheme.axaml"));
|
|
var dropAreaTheme = XDocument.Load(GetRepoFile(
|
|
"src/AtomUI.Desktop.Controls/Upload/Themes/UploadDefaultDropAreaTheme.axaml"));
|
|
|
|
var dropZoneTemplate = dropZoneTheme.Descendants(AvaloniaNamespace + "ControlTemplate").Single();
|
|
var dropZoneRoot = dropZoneTemplate.Elements().Single();
|
|
dropZoneRoot.Name.LocalName.ShouldBe("ContentPresenter");
|
|
((string?)dropZoneRoot.Attribute("Name")).ShouldBe("PART_ContentPresenter");
|
|
((string?)dropZoneRoot.Attribute("Content")).ShouldBe("{TemplateBinding Content}");
|
|
((string?)dropZoneRoot.Attribute("ContentTemplate")).ShouldBe("{TemplateBinding ContentTemplate}");
|
|
((string?)dropZoneRoot.Attribute("HorizontalContentAlignment"))
|
|
.ShouldBe("{TemplateBinding HorizontalContentAlignment}");
|
|
((string?)dropZoneRoot.Attribute("VerticalContentAlignment"))
|
|
.ShouldBe("{TemplateBinding VerticalContentAlignment}");
|
|
|
|
var dropAreaTemplate = dropAreaTheme.Descendants(AvaloniaNamespace + "ControlTemplate").Single();
|
|
var frame = dropAreaTemplate.Elements().Single();
|
|
frame.Name.LocalName.ShouldBe("DashedBorder");
|
|
((string?)frame.Attribute("Name")).ShouldBe("Frame");
|
|
((string?)frame.Attribute("Background")).ShouldBe("{TemplateBinding Background}");
|
|
((string?)frame.Attribute("BorderBrush")).ShouldBe("{TemplateBinding BorderBrush}");
|
|
((string?)frame.Attribute("BorderThickness")).ShouldBe("{TemplateBinding BorderThickness}");
|
|
((string?)frame.Attribute("CornerRadius")).ShouldBe("{TemplateBinding CornerRadius}");
|
|
((string?)frame.Attribute("Padding")).ShouldBe("{TemplateBinding Padding}");
|
|
|
|
var stackPanel = frame.Elements().Single();
|
|
stackPanel.Name.LocalName.ShouldBe("StackPanel");
|
|
((string?)stackPanel.Attribute("Orientation")).ShouldBe("Vertical");
|
|
stackPanel.Elements().Select(element => (element.Name.LocalName, (string?)element.Attribute("Name")))
|
|
.ShouldBe([
|
|
("IconPresenter", "IconPresenter"),
|
|
("ContentPresenter", "HeaderContentPresenter"),
|
|
("ContentPresenter", "SubHeaderContentPresenter")
|
|
]);
|
|
|
|
var source = File.ReadAllText(GetRepoFile(
|
|
"src/AtomUI.Desktop.Controls/Upload/Themes/UploadDefaultDropAreaTheme.axaml"));
|
|
source.ShouldContain("<Setter Property=\"Background\" Value=\"{atom:SharedTokenResource ColorFillAlter}\"/>");
|
|
source.ShouldContain("<Setter Property=\"CornerRadius\" Value=\"{atom:SharedTokenResource BorderRadiusLG}\"/>");
|
|
source.ShouldContain("<Setter Property=\"BorderBrush\" Value=\"{atom:SharedTokenResource ColorBorder}\"/>");
|
|
source.ShouldContain("<Setter Property=\"BorderThickness\" Value=\"{atom:SharedTokenResource BorderThickness}\"/>");
|
|
source.ShouldContain("<Setter Property=\"Padding\" Value=\"{atom:SharedTokenResource Padding}\"/>");
|
|
source.ShouldContain("<Setter Property=\"Header\" Value=\"{atom:UploadLangResource DragUploadHead}\"/>");
|
|
source.ShouldContain("<Setter Property=\"IsMotionEnabled\" Value=\"{atom:SharedTokenResource EnableMotion}\"/>");
|
|
source.ShouldContain("<Style Selector=\"^:pointerover\">");
|
|
source.ShouldContain("<Style Selector=\"^:disabled\">");
|
|
source.ShouldContain("<Style Selector=\"^[IsMotionEnabled=True]\">");
|
|
source.ShouldContain("<atom:SolidColorBrushTransition Property=\"BorderBrush\"");
|
|
}
|
|
|
|
[Fact]
|
|
public void Default_Drop_Area_Is_Visual_Only_And_Default_Themes_Ignore_Drag_State()
|
|
{
|
|
var dropAreaSource = File.ReadAllText(GetRepoFile(
|
|
"src/AtomUI.Desktop.Controls/Upload/UploadDefaultDropArea.cs"));
|
|
var dropAreaTheme = File.ReadAllText(GetRepoFile(
|
|
"src/AtomUI.Desktop.Controls/Upload/Themes/UploadDefaultDropAreaTheme.axaml"));
|
|
var dropZoneTheme = File.ReadAllText(GetRepoFile(
|
|
"src/AtomUI.Desktop.Controls/Upload/Themes/UploadDropZoneTheme.axaml"));
|
|
|
|
dropAreaSource.ShouldNotContain("Avalonia.Input");
|
|
dropAreaSource.ShouldNotContain("IStorageFile");
|
|
dropAreaSource.ShouldNotContain("IDataTransfer");
|
|
dropAreaSource.ShouldNotContain("FilesDropped");
|
|
dropAreaSource.ShouldNotContain("HandleDrop");
|
|
dropAreaTheme.ShouldNotContain("DragDrop.AllowDrop");
|
|
|
|
foreach (var pseudoClass in new[]
|
|
{
|
|
":drag-over",
|
|
":drag-accepting",
|
|
":drag-rejecting",
|
|
":drop-processing"
|
|
})
|
|
{
|
|
dropAreaTheme.ShouldNotContain(pseudoClass);
|
|
dropZoneTheme.ShouldNotContain(pseudoClass);
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void Default_Drop_Area_Keeps_Stable_Logical_Layout_In_Theme_And_Scaling_Matrix()
|
|
{
|
|
var dropArea = new UploadDefaultDropArea();
|
|
var upload = new Desktop.Controls.Upload
|
|
{
|
|
AutoUpload = false,
|
|
TriggerContent = new UploadDropZone
|
|
{
|
|
Content = dropArea
|
|
}
|
|
};
|
|
var window = new AvaloniaWindow
|
|
{
|
|
Width = 640,
|
|
Height = 360,
|
|
Content = upload,
|
|
RequestedThemeVariant = ThemeVariant.Light
|
|
};
|
|
|
|
try
|
|
{
|
|
window.Show();
|
|
Dispatcher.UIThread.RunJobs();
|
|
|
|
var baselineSize = dropArea.Bounds.Size;
|
|
baselineSize.Width.ShouldBeGreaterThan(0);
|
|
baselineSize.Height.ShouldBeGreaterThan(0);
|
|
var lightSizeByScaling = new Dictionary<double, Size>();
|
|
|
|
foreach (var useDarkTheme in new[] { false, true })
|
|
{
|
|
foreach (var renderScaling in new[] { 1.0, 1.5 })
|
|
{
|
|
var theme = useDarkTheme ? ThemeVariant.Dark : ThemeVariant.Light;
|
|
window.RequestedThemeVariant = theme;
|
|
window.SetRenderScaling(renderScaling);
|
|
Dispatcher.UIThread.RunJobs();
|
|
|
|
dropArea.ActualThemeVariant.ShouldBe(theme);
|
|
window.RenderScaling.ShouldBe(renderScaling);
|
|
dropArea.Bounds.Width.ShouldBe(baselineSize.Width);
|
|
Math.Abs(dropArea.Bounds.Height - baselineSize.Height).ShouldBeLessThanOrEqualTo(1);
|
|
|
|
if (useDarkTheme)
|
|
{
|
|
dropArea.Bounds.Size.ShouldBe(lightSizeByScaling[renderScaling]);
|
|
}
|
|
else
|
|
{
|
|
lightSizeByScaling.Add(renderScaling, dropArea.Bounds.Size);
|
|
}
|
|
|
|
dropArea.GetVisualDescendants()
|
|
.OfType<Control>()
|
|
.Single(control => control.Name == "Frame")
|
|
.Bounds.Size.ShouldBe(dropArea.Bounds.Size);
|
|
}
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
window.Close();
|
|
Dispatcher.UIThread.RunJobs();
|
|
}
|
|
}
|
|
|
|
private static string GetRepoFile(string relativePath)
|
|
{
|
|
var directory = new DirectoryInfo(AppContext.BaseDirectory);
|
|
while (directory is not null)
|
|
{
|
|
var candidate = Path.Combine(directory.FullName, relativePath);
|
|
if (File.Exists(candidate))
|
|
{
|
|
return candidate;
|
|
}
|
|
|
|
directory = directory.Parent;
|
|
}
|
|
|
|
throw new FileNotFoundException($"Unable to locate repository file '{relativePath}'.");
|
|
}
|
|
}
|