Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.ComponentModel.Design;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows.Forms.Design.Behavior;
using Moq;

namespace System.Windows.Forms.Design.Tests;

Expand All @@ -12,17 +15,21 @@ public class DesignerUtilsTests :IDisposable
private readonly Graphics _graphics;
private readonly Rectangle _bounds;

public Button Button { get; }

public DesignerUtilsTests()
{
_bitmap = new(20, 20);
_graphics = Graphics.FromImage(_bitmap);
_bounds = new(5, 5, 20, 20);
Button = new() { Width = 50, Height = 50 };
}

public void Dispose()
{
_graphics.Dispose();
_bitmap.Dispose();
Button.Dispose();
}

[WinFormsFact]
Expand Down Expand Up @@ -144,4 +151,253 @@ public void DrawSelectionBorder_ShouldFillRectangle_WhenCalled()
Color pixelColor = _bitmap.GetPixel(6, 6);
pixelColor.ToArgb().Should().NotBe(Color.Empty.ToArgb());
}

[WinFormsFact]
public void LastCursorPoint_ShouldNotThrow_WhenCalled()
{
Exception exception = Record.Exception(() =>
_ = DesignerUtils.LastCursorPoint);

exception.Should().BeNull();
}

[WinFormsFact]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be refactored for greater clarity:

    [WinFormsFact]
    public void LastCursorPoint_ShouldReturnValidCoordinates()
    {
        Point cursorPoint = DesignerUtils.LastCursorPoint;

        Rectangle virtualScreen = SystemInformation.VirtualScreen;
        cursorPoint.X.Should().BeInRange(virtualScreen.Left, virtualScreen.Right);
        cursorPoint.Y.Should().BeInRange(virtualScreen.Top, virtualScreen.Bottom);
    }

That said, I'm still unsure this fully addresses Tanya's concern, as DesignerUtils.LastCursorPoint still relies on a computer-wide resource.

@Tanya-Solyanik , do you think this test is stable enough?

public void LastCursorPoint_ShouldReturnValidCoordinates()
{
Point cursorPoint = DesignerUtils.LastCursorPoint;

cursorPoint.X.Should().BeLessThanOrEqualTo(SystemInformation.VirtualScreen.Right);
cursorPoint.X.Should().BeGreaterThanOrEqualTo(SystemInformation.VirtualScreen.Left);
cursorPoint.Y.Should().BeLessThanOrEqualTo(SystemInformation.VirtualScreen.Bottom);
cursorPoint.Y.Should().BeGreaterThanOrEqualTo(SystemInformation.VirtualScreen.Top);
}

[WinFormsFact]
public void SyncBrushes_ShouldRecreateHoverBrush()
{
DesignerUtils.SyncBrushes();

DesignerUtils.HoverBrush.Should().BeOfType<SolidBrush>();
((SolidBrush)DesignerUtils.HoverBrush).Color.Should().Be(Color.FromArgb(50, SystemColors.Highlight));
}

[WinFormsTheory]
[InlineData(FrameStyle.Dashed, true)]
[InlineData(FrameStyle.Thick, false)]
public void DrawFrame_ShouldUseCorrectBrushBasedOnStyleAndBackColor(FrameStyle style, bool useDarkBackground)
{
using Region region = new(new Rectangle(0, 0, _bounds.Width, _bounds.Height));
Color backColor = useDarkBackground ? Color.Black : Color.White;
Color expectedColor = useDarkBackground ? SystemColors.ControlLight : SystemColors.ControlDarkDark;

DesignerUtils.DrawFrame(_graphics, region, style, backColor);

Color pixelColor = _bitmap.GetPixel(_bounds.Width / 2, _bounds.Height / 2);
pixelColor.ToArgb().Should().Be(expectedColor.ToArgb());
}

[WinFormsTheory]
[BoolData]
public void DrawNoResizeHandle_ShouldNotThrow_WhenCalledWithValidParameters(bool isPrimary)
{
Exception exception = Record.Exception(() =>
DesignerUtils.DrawNoResizeHandle(_graphics, _bounds, isPrimary));

exception.Should().BeNull();
}

[WinFormsTheory]
[BoolData]
public void DrawNoResizeHandle_ShouldDrawHandle_BasedOnSelectionType(bool isPrimary)
{
DesignerUtils.DrawNoResizeHandle(_graphics, _bounds, isPrimary);

Color pixelColor = _bitmap.GetPixel(_bounds.Left + 1, _bounds.Top + 1);
pixelColor.ToArgb().Should().NotBe(Color.Empty.ToArgb());
}

[WinFormsFact]
public void GenerateSnapShot_ShouldGenerateImage_WhenControlSupportsWM_PRINT()
{
int borderSize = 2;
double opacity = 0.5;
Color backColor = Color.White;

DesignerUtils.GenerateSnapShot(Button, out Bitmap image, borderSize, opacity, backColor);

using (image)
{
image.Should().BeOfType<Bitmap>();
image.Width.Should().BeGreaterThan(0);
image.Height.Should().BeGreaterThan(0);
}
}

[WinFormsFact]
public void GenerateSnapShot_ShouldApplyOpacity()
{
int borderSize = 0;
double opacity = 0.5;
Color backColor = Color.White;

DesignerUtils.GenerateSnapShot(Button, out Bitmap image, borderSize, opacity, backColor);

using (image)
{
image.Should().BeOfType<Bitmap>();
Color pixelColor = image.GetPixel(image.Width / 2, image.Height / 2);
pixelColor.A.Should().BeLessThan(255);
}
}

[WinFormsFact]
public void GenerateSnapShot_ShouldDrawBorder_WhenBorderSizeIsGreaterThanZero()
{
int borderSize = 2;
double opacity = 1.0;
Color backColor = Color.White;

DesignerUtils.GenerateSnapShot(Button, out Bitmap image, borderSize, opacity, backColor);

using (image)
{
image.Should().BeOfType<Bitmap>();
Color borderPixelColor = image.GetPixel(0, 0);
borderPixelColor.Should().NotBe(backColor);
}
}

[WinFormsTheory]
[InlineData(AdornmentType.GrabHandle, 7, 7)]
[InlineData(AdornmentType.ContainerSelector, 15, 15)]
[InlineData((AdornmentType)999, 0, 0)]
internal void GetAdornmentDimensions_ShouldReturnExpectedSize(AdornmentType adornmentType, int expectedWidth, int expectedHeight)
{
Size result = DesignerUtils.GetAdornmentDimensions(adornmentType);

result.Width.Should().Be(expectedWidth);
result.Height.Should().Be(expectedHeight);
}

[WinFormsFact]
public void UseSnapLines_ShouldReturnTrue_WhenProviderHasNoSnapLinesProperty()
{
Mock<IServiceProvider> mockProvider = new();
mockProvider.Setup(p => p.GetService(typeof(DesignerOptionService))).Returns(null!);

DesignerUtils.UseSnapLines(mockProvider.Object).Should().BeTrue();
}

[WinFormsFact]
public void GetOptionValue_ShouldReturnNull_WhenProviderIsNull()
{
object? result = DesignerUtils.GetOptionValue(provider: null, name: "SomeOption");

result.Should().BeNull();
}

[WinFormsFact]
public void GetOptionValue_ShouldReturnNull_WhenDesignerOptionServiceIsNotAvailable()
{
Mock<IServiceProvider> mockProvider = new();
mockProvider.Setup(p => p.GetService(typeof(DesignerOptionService))).Returns(null!);

object? result = DesignerUtils.GetOptionValue(mockProvider.Object, "SomeOption");

result.Should().BeNull();
}

[WinFormsFact]
public void GetOptionValue_ShouldReturnNull_WhenIDesignerOptionServiceIsNotAvailable()
{
Mock<IServiceProvider> mockProvider = new();
mockProvider.Setup(p => p.GetService(typeof(IDesignerOptionService))).Returns(null!);

object? result = DesignerUtils.GetOptionValue(mockProvider.Object, "SomeOption");

result.Should().BeNull();
}

[WinFormsFact]
public void GetOptionValue_ShouldReturnValue_WhenIDesignerOptionServiceHasOption()
{
Mock<IServiceProvider> mockProvider = new();
Mock<IDesignerOptionService> mockOptionService = new();
mockOptionService.Setup(o => o.GetOptionValue("WindowsFormsDesigner\\General", "SomeOption")).Returns("ExpectedValue");
mockProvider.Setup(p => p.GetService(typeof(IDesignerOptionService))).Returns(mockOptionService.Object);

object? result = DesignerUtils.GetOptionValue(mockProvider.Object, "SomeOption");

result.Should().Be("ExpectedValue");
}

[WinFormsFact]
public void GenerateSnapShotWithBitBlt_ShouldGenerateImage_WhenControlIsValid()
{
DesignerUtils.GenerateSnapShotWithBitBlt(Button, out Bitmap image);

using (image)
{
image.Should().BeOfType<Bitmap>();
image.Width.Should().BeGreaterThan(0);
image.Height.Should().BeGreaterThan(0);
}
}

[WinFormsFact]
public void GenerateSnapShotWithBitBlt_ShouldNotThrow_WhenControlIsValid()
{
Exception exception = Record.Exception(() =>
{
DesignerUtils.GenerateSnapShotWithBitBlt(Button, out Bitmap image);
using (image)
{
image.Should().BeOfType<Bitmap>();
}
});

exception.Should().BeNull();
}

[WinFormsFact]
public void GenerateSnapShotWithWM_PRINT_ShouldReturnTrue_WhenControlRespondsToWM_PRINT()
{
bool result = DesignerUtils.GenerateSnapShotWithWM_PRINT(Button, out Bitmap image);

result.Should().BeTrue();

using (image)
{
image.Should().BeOfType<Bitmap>();
image.Width.Should().BeGreaterThan(0);
image.Height.Should().BeGreaterThan(0);
}
}

[WinFormsTheory]
[InlineData(SelectionBorderGlyphType.Top, 30, 20, 2, 28, 18, 24, 2)]
[InlineData(SelectionBorderGlyphType.Bottom, 10, 20, 2, 8, 40, 24, 2)]
[InlineData(SelectionBorderGlyphType.Left, 10, 20, 2, 8, 18, 2, 24)]
[InlineData(SelectionBorderGlyphType.Right, 10, 20, 2, 30, 18, 2, 24)]
[InlineData(SelectionBorderGlyphType.Body, 10, 20, 2, 10, 20, 20, 20)]
[InlineData((SelectionBorderGlyphType)999, 10, 20, 2, 0, 0, 0, 0)]
internal void GetBoundsForSelectionType_ShouldReturnExpectedBounds(
SelectionBorderGlyphType type,
int x,
int y,
int borderSize,
int expectedX,
int expectedY,
int expectedWidth,
int expectedHeight)
{
Rectangle originalBounds = new(x, y, 20, 20);

Rectangle result = DesignerUtils.GetBoundsForSelectionType(originalBounds, type, borderSize);

result.X.Should().Be(expectedX);
result.Y.Should().Be(expectedY);
result.Width.Should().Be(expectedWidth);
result.Height.Should().Be(expectedHeight);
}
}
Loading