using XFESystem.Core;
using XFESystem.Desktop;
using Xunit;
namespace XFESystem.Core.Tests;
public sealed class ChromeAnimationTests
{
private sealed class Canvas : IDesktopCanvas
{
public int Width => 1280;
public int Height => 800;
public bool SupportsSceneCache => true;
public List<DesktopBounds> Damage { get; } = [];
public List<string> Texts { get; } = [];
public void Fill(uint rgb, int x, int y, int width, int height) { }
public void Line(uint rgb, int x1, int y1, int x2, int y2) { }
public void Text(string text, uint rgb, int x, int y) => Texts.Add(text);
public void Present() { }
public void SaveScene(DesktopBounds damage) => Damage.Add(damage);
}
[Fact]
public void ReversibleAnimationPassesThroughMiddleAndStopsAtEndpoints()
{
var animation = new DesktopChromeAnimation();
animation.SetTargets(1000, true, true, true, true);
Assert.True(animation.IsAnimating); Assert.Equal(0, animation.CloseProgress);
var changed = animation.Advance(1090);
Assert.Equal(DesktopChromeAnimationChanges.Minimize | DesktopChromeAnimationChanges.Close | DesktopChromeAnimationChanges.TitleHint | DesktopChromeAnimationChanges.Resize, changed);
Assert.Equal(0.5, animation.CloseProgress, 5); Assert.Equal(0.5, animation.MinimizeProgress, 5);
Assert.Equal(0.5, animation.TitleHintProgress, 5); Assert.Equal(0.5, animation.ResizeProgress, 5);
animation.SetTargets(1090, false, false, false, false);
Assert.Equal(0.5, animation.CloseProgress, 5);
animation.Advance(1135); Assert.InRange(animation.CloseProgress, 0.1, 0.2);
animation.Advance(1180); Assert.Equal(0, animation.CloseProgress); Assert.False(animation.IsAnimating);
Assert.Equal(DesktopChromeAnimationChanges.None, animation.Advance(2000));
}
[Fact]
public void RepeatedTargetsAndBackwardsClockCannotRestartOrJumpAnimation()
{
var animation = new DesktopChromeAnimation(); animation.SetTargets(100, false, true, false, false);
animation.Advance(145); double before = animation.CloseProgress;
Assert.Equal(DesktopChromeAnimationChanges.None, animation.Advance(140)); Assert.Equal(before, animation.CloseProgress);
animation.SetTargets(145, false, true, false, false); Assert.Equal(before, animation.CloseProgress);
animation.Advance(280); Assert.Equal(1, animation.CloseProgress); Assert.False(animation.IsAnimating);
Assert.Equal(DesktopChromeAnimationChanges.None, animation.Advance(281));
}
[Fact]
public void DesktopHasNoSystemTopbarAndSettingsIsFifthDesktopEntrance()
{
var canvas = new Canvas(); var desktop = new DesktopSession(canvas, new MemoryWorkspace());
Assert.Equal(new DesktopBounds(0, 0, 1280, 752), desktop.WorkArea);
desktop.Render(); Assert.Contains("Settings", canvas.Texts); Assert.DoesNotContain("C# Native Desktop", canvas.Texts);
desktop.Pointer(50, 492, true, timestampMs: 100); desktop.Pointer(50, 492, false, timestampMs: 101);
Assert.Equal(DesktopApplication.Settings, desktop.ActiveWindow!.Application);
}
[Fact]
public void CaptionHoverAnimatesOnlyCaptionDamageAndSettlesWithoutIdleFrames()
{
var canvas = new Canvas(); var desktop = new DesktopSession(canvas, new MemoryWorkspace());
var window = desktop.Open(DesktopApplication.Files); desktop.Render(); var b = window.Bounds;
desktop.Pointer(b.X + b.Width - 16, b.Y + 16, false, timestampMs: 1000); desktop.Render();
desktop.AdvanceFeedback(1090); Assert.Equal(0.5, window.ChromeAnimation.CloseProgress, 5);
desktop.Render(); Assert.True(canvas.Damage[^1].Width <= 34); Assert.True(canvas.Damage[^1].Height <= 34);
desktop.AdvanceFeedback(1180); desktop.Render(); Assert.Equal(1, window.ChromeAnimation.CloseProgress);
desktop.AdvanceFeedback(2000); Assert.False(desktop.NeedsRender);
desktop.Pointer(b.X + 200, b.Y + 100, false, timestampMs: 2010); desktop.Render();
desktop.AdvanceFeedback(2100); Assert.InRange(window.ChromeAnimation.CloseProgress, 0.45, 0.55);
desktop.AdvanceFeedback(2190); desktop.Render(); Assert.Equal(0, window.ChromeAnimation.CloseProgress);
desktop.AdvanceFeedback(3000); Assert.False(desktop.NeedsRender);
}
[Fact]
public void TitleAndResizeHintsRemainOnDuringCaptureEvenOutsideHoverTarget()
{
var canvas = new Canvas(); var desktop = new DesktopSession(canvas, new MemoryWorkspace());
var window = desktop.Open(DesktopApplication.Files); var b = window.Bounds;
desktop.Pointer(b.X + 200, b.Y + 16, true, timestampMs: 1000);
desktop.Pointer(1279, 10, true, timestampMs: 1050);
desktop.AdvanceFeedback(1180); Assert.Equal(1, window.ChromeAnimation.TitleHintProgress);
desktop.Pointer(1279, 10, false, timestampMs: 1190);
desktop.AdvanceFeedback(1370); Assert.Equal(0, window.ChromeAnimation.TitleHintProgress);
b = window.Bounds;
desktop.Pointer(b.X + b.Width - 2, b.Y + b.Height - 2, true, timestampMs: 2000);
desktop.Pointer(0, 0, true, timestampMs: 2050);
desktop.AdvanceFeedback(2180); Assert.Equal(1, window.ChromeAnimation.ResizeProgress);
desktop.Pointer(0, 0, false, timestampMs: 2190);
desktop.AdvanceFeedback(2370); Assert.Equal(0, window.ChromeAnimation.ResizeProgress);
}
}
using XFESystem.Core;
using XFESystem.Desktop;
using Xunit;
namespace XFESystem.Core.Tests;
public sealed class ChromeAnimationTests
{
private sealed class Canvas : IDesktopCanvas
{
public int Width => 1280;
public int Height => 800;
public bool SupportsSceneCache => true;
public List<DesktopBounds> Damage { get; } = [];
public List<string> Texts { get; } = [];
public void Fill(uint rgb, int x, int y, int width, int height) { }
public void Line(uint rgb, int x1, int y1, int x2, int y2) { }
public void Text(string text, uint rgb, int x, int y) => Texts.Add(text);
public void Present() { }
public void SaveScene(DesktopBounds damage) => Damage.Add(damage);
}
[Fact]
public void ReversibleAnimationPassesThroughMiddleAndStopsAtEndpoints()
{
var animation = new DesktopChromeAnimation();
animation.SetTargets(1000, true, true, true, true);
Assert.True(animation.IsAnimating); Assert.Equal(0, animation.CloseProgress);
var changed = animation.Advance(1090);
Assert.Equal(DesktopChromeAnimationChanges.Minimize | DesktopChromeAnimationChanges.Close | DesktopChromeAnimationChanges.TitleHint | DesktopChromeAnimationChanges.Resize, changed);
Assert.Equal(0.5, animation.CloseProgress, 5); Assert.Equal(0.5, animation.MinimizeProgress, 5);
Assert.Equal(0.5, animation.TitleHintProgress, 5); Assert.Equal(0.5, animation.ResizeProgress, 5);
animation.SetTargets(1090, false, false, false, false);
Assert.Equal(0.5, animation.CloseProgress, 5);
animation.Advance(1135); Assert.InRange(animation.CloseProgress, 0.1, 0.2);
animation.Advance(1180); Assert.Equal(0, animation.CloseProgress); Assert.False(animation.IsAnimating);
Assert.Equal(DesktopChromeAnimationChanges.None, animation.Advance(2000));
}
[Fact]
public void RepeatedTargetsAndBackwardsClockCannotRestartOrJumpAnimation()
{
var animation = new DesktopChromeAnimation(); animation.SetTargets(100, false, true, false, false);
animation.Advance(145); double before = animation.CloseProgress;
Assert.Equal(DesktopChromeAnimationChanges.None, animation.Advance(140)); Assert.Equal(before, animation.CloseProgress);
animation.SetTargets(145, false, true, false, false); Assert.Equal(before, animation.CloseProgress);
animation.Advance(280); Assert.Equal(1, animation.CloseProgress); Assert.False(animation.IsAnimating);
Assert.Equal(DesktopChromeAnimationChanges.None, animation.Advance(281));
}
[Fact]
public void DesktopHasNoSystemTopbarAndSettingsIsFifthDesktopEntrance()
{
var canvas = new Canvas(); var desktop = new DesktopSession(canvas, new MemoryWorkspace());
Assert.Equal(new DesktopBounds(0, 0, 1280, 752), desktop.WorkArea);
desktop.Render(); Assert.Contains("Settings", canvas.Texts); Assert.DoesNotContain("C# Native Desktop", canvas.Texts);
desktop.Pointer(50, 492, true, timestampMs: 100); desktop.Pointer(50, 492, false, timestampMs: 101);
Assert.Equal(DesktopApplication.Settings, desktop.ActiveWindow!.Application);
}
[Fact]
public void CaptionHoverAnimatesOnlyCaptionDamageAndSettlesWithoutIdleFrames()
{
var canvas = new Canvas(); var desktop = new DesktopSession(canvas, new MemoryWorkspace());
var window = desktop.Open(DesktopApplication.Files); desktop.Render(); var b = window.Bounds;
desktop.Pointer(b.X + b.Width - 16, b.Y + 16, false, timestampMs: 1000); desktop.Render();
desktop.AdvanceFeedback(1090); Assert.Equal(0.5, window.ChromeAnimation.CloseProgress, 5);
desktop.Render(); Assert.True(canvas.Damage[^1].Width <= 34); Assert.True(canvas.Damage[^1].Height <= 34);
desktop.AdvanceFeedback(1180); desktop.Render(); Assert.Equal(1, window.ChromeAnimation.CloseProgress);
desktop.AdvanceFeedback(2000); Assert.False(desktop.NeedsRender);
desktop.Pointer(b.X + 200, b.Y + 100, false, timestampMs: 2010); desktop.Render();
desktop.AdvanceFeedback(2100); Assert.InRange(window.ChromeAnimation.CloseProgress, 0.45, 0.55);
desktop.AdvanceFeedback(2190); desktop.Render(); Assert.Equal(0, window.ChromeAnimation.CloseProgress);
desktop.AdvanceFeedback(3000); Assert.False(desktop.NeedsRender);
}
[Fact]
public void TitleAndResizeHintsRemainOnDuringCaptureEvenOutsideHoverTarget()
{
var canvas = new Canvas(); var desktop = new DesktopSession(canvas, new MemoryWorkspace());
var window = desktop.Open(DesktopApplication.Files); var b = window.Bounds;
desktop.Pointer(b.X + 200, b.Y + 16, true, timestampMs: 1000);
desktop.Pointer(1279, 10, true, timestampMs: 1050);
desktop.AdvanceFeedback(1180); Assert.Equal(1, window.ChromeAnimation.TitleHintProgress);
desktop.Pointer(1279, 10, false, timestampMs: 1190);
desktop.AdvanceFeedback(1370); Assert.Equal(0, window.ChromeAnimation.TitleHintProgress);
b = window.Bounds;
desktop.Pointer(b.X + b.Width - 2, b.Y + b.Height - 2, true, timestampMs: 2000);
desktop.Pointer(0, 0, true, timestampMs: 2050);
desktop.AdvanceFeedback(2180); Assert.Equal(1, window.ChromeAnimation.ResizeProgress);
desktop.Pointer(0, 0, false, timestampMs: 2190);
desktop.AdvanceFeedback(2370); Assert.Equal(0, window.ChromeAnimation.ResizeProgress);
}
}