Skip to content
Merged
Show file tree
Hide file tree
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
@@ -0,0 +1,211 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#nullable enable

using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using Moq;
using Moq.Protected;

namespace System.Windows.Forms.Design.Tests;

public class SelectionUIHandlerTests : IDisposable
{
private readonly Mock<SelectionUIHandler> _selectionUIHandlerMock;
private readonly Control _control;
private readonly IComponent _component;
private readonly Mock<IDesignerHost> _designerHostMock;
private readonly Mock<IComponentChangeService> _changedServiceMock;

public SelectionUIHandlerTests()
{
_selectionUIHandlerMock = new() { CallBase = true };
_control = new();
_component = new Mock<IComponent>().Object;
_designerHostMock = new();
_changedServiceMock = new();

_selectionUIHandlerMock.Protected().Setup<IComponent>("GetComponent").Returns(_component);
_selectionUIHandlerMock.Protected().Setup<Control>("GetControl").Returns(_control);
_selectionUIHandlerMock.Protected().Setup<Control>("GetControl", ItExpr.IsAny<IComponent>()).Returns(_control);
_selectionUIHandlerMock.Protected().Setup<Size>("GetCurrentSnapSize").Returns(new Size(10, 10));
_selectionUIHandlerMock.Protected().Setup<bool>("GetShouldSnapToGrid").Returns(true);
_selectionUIHandlerMock.Protected().Setup<object>("GetService", typeof(IDesignerHost)).Returns(_designerHostMock.Object);
_selectionUIHandlerMock.Protected().Setup<object>("GetService", typeof(IComponentChangeService)).Returns(_changedServiceMock.Object);
}

public void Dispose()
{
_control.Dispose();
_component.Dispose();
}

[Fact]
public void BeginDrag_ShouldReturnTrueAndInitializeDragState()
{
object[] components = [_component];
bool result = _selectionUIHandlerMock.Object.BeginDrag(components, SelectionRules.Moveable, 0, 0);

result.Should().BeTrue();

Control[] dragControls = _selectionUIHandlerMock.Object.TestAccessor().Dynamic._dragControls;

dragControls.Should().NotBeNull();
dragControls.Should().HaveCount(1);
dragControls[0].Should().Be(_control);
}

[Fact]
public void DragMoved_ShouldUpdateDragOffset()
{
object[] components = [_component];
Rectangle offset = new(10, 10, 0, 0);

// Ensure BeginDrag is called to initialize the drag state
_selectionUIHandlerMock.Object.BeginDrag(components, SelectionRules.Moveable, 0, 0);

_selectionUIHandlerMock.Object.DragMoved(components, offset);

Rectangle dragOffset = _selectionUIHandlerMock.Object.TestAccessor().Dynamic._dragOffset;

dragOffset.Should().Be(offset);
}

[Fact]
public void EndDrag_ShouldResetDragState()
{
object[] components = [_component];

// Ensure BeginDrag is called to initialize the drag state
_selectionUIHandlerMock.Object.BeginDrag(components, SelectionRules.Moveable, 0, 0);

_selectionUIHandlerMock.Object.EndDrag(components, cancel: false);

Control[]? dragControls = _selectionUIHandlerMock.Object.TestAccessor().Dynamic._dragControls;
object? originalCoordinates = _selectionUIHandlerMock.Object.TestAccessor().Dynamic._originalCoordinates;
Rectangle dragOffset = _selectionUIHandlerMock.Object.TestAccessor().Dynamic._dragOffset;

dragControls.Should().BeNull();
originalCoordinates.Should().BeNull();
dragOffset.Should().Be(Rectangle.Empty);
}

[Fact]
public void QueryBeginDrag_ShouldReturnFalse_WhenCheckoutExceptionIsThrown()
{
_changedServiceMock.Setup(cs => cs.OnComponentChanging(It.IsAny<object>(), It.IsAny<PropertyDescriptor>())).Throws(CheckoutException.Canceled);

object[] components = [_component];
bool result = _selectionUIHandlerMock.Object.QueryBeginDrag(components);

result.Should().BeFalse();
}

[Fact]
public void QueryBeginDrag_ShouldReturnFalse_WhenInvalidOperationExceptionIsThrown()
{
_changedServiceMock.Setup(cs => cs.OnComponentChanging(It.IsAny<object>(), It.IsAny<PropertyDescriptor>())).Throws<InvalidOperationException>();

object[] components = [_component];
bool result = _selectionUIHandlerMock.Object.QueryBeginDrag(components);

result.Should().BeFalse();
}

[Fact]
public void QueryBeginDrag_ShouldReturnTrueForValidComponents()
{
object[] components = [_component];
bool result = _selectionUIHandlerMock.Object.QueryBeginDrag(components);

result.Should().BeTrue();
}

[Fact]
public void QueryBeginDrag_ShouldReturnFalseForInvalidComponents()
{
object[] components = Array.Empty<object>();
bool result = _selectionUIHandlerMock.Object.QueryBeginDrag(components);

result.Should().BeFalse();
}

[Fact]
public void GetUpdatedRect_ShouldReturnUpdatedRectangle()
{
Rectangle originalRect = new(10, 10, 100, 100);
Rectangle dragRect = new(15, 15, 110, 110);
bool updateSize = true;

_selectionUIHandlerMock.Setup(h => h.GetUpdatedRect(originalRect, dragRect, updateSize))
.Returns(dragRect);

Rectangle result = _selectionUIHandlerMock.Object.GetUpdatedRect(originalRect, dragRect, updateSize);

result.Should().Be(dragRect);
}

[Fact]
public void GetUpdatedRect_ShouldReturnOriginalRectangleWhenNoUpdate()
{
Rectangle originalRect = new(10, 10, 100, 100);
Rectangle dragRect = new(15, 15, 110, 110);
bool updateSize = false;

_selectionUIHandlerMock.Setup(h => h.GetUpdatedRect(originalRect, dragRect, updateSize))
.Returns(originalRect);

Rectangle result = _selectionUIHandlerMock.Object.GetUpdatedRect(originalRect, dragRect, updateSize);

result.Should().Be(originalRect);
}

[Fact]
public void SetCursor_ShouldNotThrowAndSetCorrectCursor()
{
Cursor expectedCursor = Cursors.Hand;
_selectionUIHandlerMock.Setup(h => h.SetCursor()).Callback(() => _control.Cursor = expectedCursor);

Action act = _selectionUIHandlerMock.Object.SetCursor;

act.Should().NotThrow();
_control.Cursor.Should().Be(expectedCursor);
}

[Fact]
public void OleDragEnter_ShouldNotThrow()
{
DragEventArgs dragEventArgs = new(new DataObject(), 0, 0, 0, DragDropEffects.None, DragDropEffects.None);
Action act = () => _selectionUIHandlerMock.Object.OleDragEnter(dragEventArgs);

act.Should().NotThrow();
}

[Fact]
public void OleDragDrop_ShouldNotThrow()
{
DragEventArgs dragEventArgs = new(new DataObject(), 0, 0, 0, DragDropEffects.None, DragDropEffects.None);
Action act = () => _selectionUIHandlerMock.Object.OleDragDrop(dragEventArgs);

act.Should().NotThrow();
}

[Fact]
public void OleDragOver_ShouldNotThrow()
{
DragEventArgs dragEventArgs = new(new DataObject(), 0, 0, 0, DragDropEffects.None, DragDropEffects.None);
Action act = () => _selectionUIHandlerMock.Object.OleDragOver(dragEventArgs);

act.Should().NotThrow();
}

[Fact]
public void OleDragLeave_ShouldNotThrow()
{
Action act = _selectionUIHandlerMock.Object.OleDragLeave;

act.Should().NotThrow();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@

#nullable enable

using System.Collections;
using System.ComponentModel;
using System.ComponentModel.Design;
using Moq;

namespace System.Windows.Forms.Design.Tests;

Expand Down Expand Up @@ -43,155 +42,10 @@ public void ToolStripCollectionEditor_EditValue_NullProvider_ReturnsNull()
[Fact]
public void ToolStripCollectionEditor_EditValue_WithProvider_ReturnsExpected()
{
object? result = _editor.EditValue(new MockTypeDescriptorContext(), new MockServiceProvider(), new object());
Mock<ITypeDescriptorContext> mockTypeDescriptorContext = new();
Mock<IServiceProvider> mockServiceProvider = new();
object? result = _editor.EditValue(mockTypeDescriptorContext.Object, mockServiceProvider.Object, new object());

result.Should().NotBeNull();
}

private class MockServiceProvider : IServiceProvider
{
public object? GetService(Type serviceType)
{
if (serviceType == typeof(ISelectionService))
{
return new MockSelectionService();
}

if (serviceType == typeof(IDesignerHost))
{
return new MockDesignerHost();
}

return null;
}
}

private class MockSelectionService : ISelectionService
{
public event EventHandler? SelectionChanged
{
add { }
remove { }
}

public event EventHandler? SelectionChanging
{
add { }
remove { }
}

public ICollection GetSelectedComponents() => Array.Empty<object>();

public bool GetComponentSelected(object component) => false;

public object? PrimarySelection => null;

public int SelectionCount => 0;

public void SetSelectedComponents(ICollection? components) { }

public void SetSelectedComponents(ICollection? components, SelectionTypes selectionType) { }
}

private class MockDesignerHost : IDesignerHost
{
public IContainer Container => new Container();

public bool InTransaction => false;

public IComponent RootComponent => null!;

public string TransactionDescription => string.Empty;

public bool Loading => false;

public string RootComponentClassName => string.Empty;

public void Activate() { }

public IComponent CreateComponent(Type componentClass) => throw new NotImplementedException();

public IComponent CreateComponent(Type componentClass, string name) => throw new NotImplementedException();

public DesignerTransaction CreateTransaction() => throw new NotImplementedException();

public DesignerTransaction CreateTransaction(string description) => throw new NotImplementedException();

public void DestroyComponent(IComponent component) { }

public IDesigner? GetDesigner(IComponent component) => null;

public Type GetType(string typeName) => throw new NotImplementedException();

public void AddService(Type serviceType, ServiceCreatorCallback callback) { }

public void AddService(Type serviceType, ServiceCreatorCallback callback, bool promote) { }

public void AddService(Type serviceType, object serviceInstance) { }

public void AddService(Type serviceType, object serviceInstance, bool promote) { }

public void RemoveService(Type serviceType) { }

public void RemoveService(Type serviceType, bool promote) { }

public object? GetService(Type serviceType) => null;

public event EventHandler? Activated
{
add { }
remove { }
}

public event EventHandler? Deactivated
{
add { }
remove { }
}

public event EventHandler? LoadComplete
{
add { }
remove { }
}

public event DesignerTransactionCloseEventHandler? TransactionClosed
{
add { }
remove { }
}

public event DesignerTransactionCloseEventHandler? TransactionClosing
{
add { }
remove { }
}

public event EventHandler? TransactionOpened
{
add { }
remove { }
}

public event EventHandler? TransactionOpening
{
add { }
remove { }
}
}

private class MockTypeDescriptorContext : ITypeDescriptorContext
{
public IContainer? Container => null;

public object? Instance => null;

public PropertyDescriptor? PropertyDescriptor => null;

public bool OnComponentChanging() => true;

public void OnComponentChanged() { }

public object? GetService(Type serviceType) => null;
}
}