Skip to content

Commit

Permalink
[MouseJump]Refactor code to allow later introduction of customizable …
Browse files Browse the repository at this point in the history
…appearance (#32838)

* [Mouse Jump] - move code shared with FancyMouse into "Common" folder (#25482)

* [Mouse Jump] - updates to NativeMethods (#25482)

* [Mouse Jump] - added new drawing / layout / style classes (#25482)

* [Mouse Jump] - new style-based preview rendering (actual preview visual style unchanged) (#25482)

* [Mouse Jump] - add words to spell checker (#25482)

* [Mouse Jump] - small tweak to error handling (#25482)

* [Mouse Jump] - fixed failing test (#25482)
  • Loading branch information
mikeclayton committed Jun 12, 2024
1 parent 3e07b9b commit 651f2e4
Show file tree
Hide file tree
Showing 83 changed files with 2,968 additions and 954 deletions.
1 change: 1 addition & 0 deletions .github/actions/spell-check/expect.txt
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ bootstrapper
BOOTSTRAPPERINSTALLFOLDER
bostrot
BOTTOMALIGN
boxmodel
BPBF
bpmf
bpp
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Reflection;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using MouseJumpUI.Common.Helpers;
using MouseJumpUI.Common.Imaging;
using MouseJumpUI.Common.Models.Drawing;
using MouseJumpUI.Common.Models.Styles;
using MouseJumpUI.Helpers;

namespace MouseJumpUI.UnitTests.Common.Helpers;

[TestClass]
public static class DrawingHelperTests
{
[TestClass]
public sealed class GetPreviewLayoutTests
{
public sealed class TestCase
{
public TestCase(PreviewStyle previewStyle, List<RectangleInfo> screens, PointInfo activatedLocation, string desktopImageFilename, string expectedImageFilename)
{
this.PreviewStyle = previewStyle;
this.Screens = screens;
this.ActivatedLocation = activatedLocation;
this.DesktopImageFilename = desktopImageFilename;
this.ExpectedImageFilename = expectedImageFilename;
}

public PreviewStyle PreviewStyle { get; }

public List<RectangleInfo> Screens { get; }

public PointInfo ActivatedLocation { get; }

public string DesktopImageFilename { get; }

public string ExpectedImageFilename { get; }
}

public static IEnumerable<object[]> GetTestCases()
{
/* 4-grid */
yield return new object[]
{
new TestCase(
previewStyle: StyleHelper.DefaultPreviewStyle,
screens: new List<RectangleInfo>()
{
new(0, 0, 500, 500),
new(500, 0, 500, 500),
new(500, 500, 500, 500),
new(0, 500, 500, 500),
},
activatedLocation: new(x: 50, y: 50),
desktopImageFilename: "Common/Helpers/_test-4grid-desktop.png",
expectedImageFilename: "Common/Helpers/_test-4grid-expected.png"),
};
/* win 11 */
yield return new object[]
{
new TestCase(
previewStyle: StyleHelper.DefaultPreviewStyle,
screens: new List<RectangleInfo>()
{
new(5120, 349, 1920, 1080),
new(0, 0, 5120, 1440),
},
activatedLocation: new(x: 50, y: 50),
desktopImageFilename: "Common/Helpers/_test-win11-desktop.png",
expectedImageFilename: "Common/Helpers/_test-win11-expected.png"),
};
}

[TestMethod]
[DynamicData(nameof(GetTestCases), DynamicDataSourceType.Method)]
public void RunTestCases(TestCase data)
{
// load the fake desktop image
using var desktopImage = GetPreviewLayoutTests.LoadImageResource(data.DesktopImageFilename);

// draw the preview image
var previewLayout = LayoutHelper.GetPreviewLayout(
previewStyle: data.PreviewStyle,
screens: data.Screens,
activatedLocation: data.ActivatedLocation);
var imageCopyService = new StaticImageRegionCopyService(desktopImage);
using var actual = DrawingHelper.RenderPreview(previewLayout, imageCopyService);

// load the expected image
var expected = GetPreviewLayoutTests.LoadImageResource(data.ExpectedImageFilename);

// compare the images
var screens = System.Windows.Forms.Screen.AllScreens;
AssertImagesEqual(expected, actual);
}

private static Bitmap LoadImageResource(string filename)
{
var assembly = Assembly.GetExecutingAssembly();
var assemblyName = new AssemblyName(assembly.FullName ?? throw new InvalidOperationException());
var resourceName = $"Microsoft.{assemblyName.Name}.{filename.Replace("/", ".")}";
var resourceNames = assembly.GetManifestResourceNames();
if (!resourceNames.Contains(resourceName))
{
throw new InvalidOperationException($"Embedded resource '{resourceName}' does not exist.");
}

var stream = assembly.GetManifestResourceStream(resourceName)
?? throw new InvalidOperationException();
var image = (Bitmap)Image.FromStream(stream);
return image;
}

/// <summary>
/// Naive / brute force image comparison - we can optimise this later :-)
/// </summary>
private static void AssertImagesEqual(Bitmap expected, Bitmap actual)
{
Assert.AreEqual(
expected.Width,
actual.Width,
$"expected width: {expected.Width}, actual width: {actual.Width}");
Assert.AreEqual(
expected.Height,
actual.Height,
$"expected height: {expected.Height}, actual height: {actual.Height}");
for (var y = 0; y < expected.Height; y++)
{
for (var x = 0; x < expected.Width; x++)
{
var expectedPixel = expected.GetPixel(x, y);
var actualPixel = actual.GetPixel(x, y);

// allow a small tolerance for rounding differences in gdi
Assert.IsTrue(
(Math.Abs(expectedPixel.A - actualPixel.A) <= 1) &&
(Math.Abs(expectedPixel.R - actualPixel.R) <= 1) &&
(Math.Abs(expectedPixel.G - actualPixel.G) <= 1) &&
(Math.Abs(expectedPixel.B - actualPixel.B) <= 1),
$"images differ at pixel ({x}, {y}) - expected: {expectedPixel}, actual: {actualPixel}");
}
}
}
}
}
Loading

0 comments on commit 651f2e4

Please sign in to comment.