Skip to content

Commit de252e0

Browse files
Add unit tests for EditorServiceContext (#13273)
* Add unit tests for EditorServiceContext Related #10773 --------- Co-authored-by: Tanya Solyanik <[email protected]>
1 parent 4719d8b commit de252e0

File tree

1 file changed

+214
-0
lines changed

1 file changed

+214
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.ComponentModel;
5+
using System.ComponentModel.Design;
6+
using System.Drawing.Design;
7+
using Moq;
8+
9+
namespace System.Windows.Forms.Design.Tests;
10+
11+
public class EditorServiceContextTests : IDisposable
12+
{
13+
private readonly TestComponent _component;
14+
private readonly TestComponentDesigner _designer;
15+
private readonly Mock<PropertyDescriptor> _mockPropertyDescriptor;
16+
private readonly Mock<UITypeEditor> _mockEditor;
17+
private readonly Mock<IContainer> _mockContainer;
18+
private readonly Mock<ISite> _mockSite;
19+
private readonly Mock<IComponentChangeService> _mockChangeService;
20+
private readonly Mock<IUIService> _mockUIService;
21+
private readonly Mock<Form> _mockDialog;
22+
23+
public EditorServiceContextTests()
24+
{
25+
_component = new();
26+
_designer = new(_component);
27+
_mockPropertyDescriptor = new("Items", Array.Empty<Attribute>());
28+
_mockEditor = new();
29+
_mockContainer = new();
30+
_mockSite = new();
31+
_mockChangeService = new();
32+
_mockUIService = new();
33+
_mockDialog = new();
34+
}
35+
36+
public void Dispose()
37+
{
38+
_designer.Dispose();
39+
_component.Dispose();
40+
_mockDialog.Object.Dispose();
41+
}
42+
43+
[Fact]
44+
public void EditValue_ShouldUpdatePropertyValue_WhenEditorReturnsNewValue()
45+
{
46+
List<string> oldValue = new() { "Old" };
47+
List<string> newValue = new() { "New" };
48+
49+
_mockPropertyDescriptor.Setup(p => p.GetValue(_component)).Returns(oldValue);
50+
_mockPropertyDescriptor.Setup(p => p.SetValue(_component, newValue));
51+
_mockPropertyDescriptor.Setup(p => p.PropertyType).Returns(typeof(List<string>));
52+
_mockPropertyDescriptor.Setup(p => p.Name).Returns("Items");
53+
_mockPropertyDescriptor.Setup(p => p.Attributes).Returns(new AttributeCollection(null));
54+
55+
_mockEditor
56+
.Setup(e => e.EditValue(It.IsAny<ITypeDescriptorContext>(), It.IsAny<IServiceProvider>(), oldValue))
57+
.Returns(newValue);
58+
59+
_mockPropertyDescriptor
60+
.Setup(p => p.GetEditor(typeof(UITypeEditor)))
61+
.Returns(_mockEditor.Object);
62+
63+
TypeDescriptor.AddProvider(new TypeDescriptionProviderMock(_mockPropertyDescriptor.Object), _component);
64+
65+
object? result = EditorServiceContext.EditValue(_designer, _component, "Items");
66+
67+
result.Should().BeEquivalentTo(newValue);
68+
_mockPropertyDescriptor.Verify(p => p.SetValue(_component, newValue), Times.Once);
69+
}
70+
71+
[Fact]
72+
public void EditValue_ShouldNotUpdatePropertyValue_WhenEditorReturnsSameValue()
73+
{
74+
List<string> list = new() { "Same" };
75+
_component.Items = list;
76+
77+
_mockPropertyDescriptor.Setup(p => p.GetValue(_component)).Returns(list);
78+
_mockPropertyDescriptor.Setup(p => p.PropertyType).Returns(typeof(List<string>));
79+
_mockPropertyDescriptor.Setup(p => p.Name).Returns("Items");
80+
_mockPropertyDescriptor.Setup(p => p.Attributes).Returns(new AttributeCollection(null));
81+
82+
_mockEditor
83+
.Setup(e => e.EditValue(It.IsAny<ITypeDescriptorContext>(), It.IsAny<IServiceProvider>(), list))
84+
.Returns(list);
85+
86+
_mockPropertyDescriptor
87+
.Setup(p => p.GetEditor(typeof(UITypeEditor)))
88+
.Returns(_mockEditor.Object);
89+
90+
TypeDescriptor.AddProvider(new TypeDescriptionProviderMock(_mockPropertyDescriptor.Object), _component);
91+
92+
object? result = EditorServiceContext.EditValue(_designer, _component, "Items");
93+
94+
result.Should().BeSameAs(list);
95+
_mockPropertyDescriptor.Verify(p => p.SetValue(It.IsAny<object>(), It.IsAny<object>()), Times.Never);
96+
}
97+
98+
[Fact]
99+
public void Container_ShouldReturnNull_WhenComponentSiteIsNull()
100+
{
101+
EditorServiceContext context = new(_designer, _mockPropertyDescriptor.Object);
102+
103+
using IContainer? container = ((ITypeDescriptorContext)context).Container;
104+
105+
container.Should().BeNull();
106+
}
107+
108+
[Fact]
109+
public void Container_ShouldReturnContainer_WhenComponentSiteHasContainer()
110+
{
111+
_mockSite.Setup(s => s.Container).Returns(_mockContainer.Object);
112+
_component.Site = _mockSite.Object;
113+
114+
EditorServiceContext context = new(_designer, _mockPropertyDescriptor.Object);
115+
116+
using IContainer? container = ((ITypeDescriptorContext)context).Container;
117+
118+
container.Should().BeSameAs(_mockContainer.Object);
119+
}
120+
121+
[Fact]
122+
public void OnComponentChanging_ShouldReturnTrue_WhenChangeServiceDoesNotThrow()
123+
{
124+
_mockSite.Setup(s => s.GetService(typeof(IComponentChangeService))).Returns(_mockChangeService.Object);
125+
_component.Site = _mockSite.Object;
126+
127+
EditorServiceContext context = new(_designer, _mockPropertyDescriptor.Object);
128+
129+
bool result = ((ITypeDescriptorContext)context).OnComponentChanging();
130+
131+
result.Should().BeTrue();
132+
_mockChangeService.Verify(cs => cs.OnComponentChanging(_component, _mockPropertyDescriptor.Object), Times.Once);
133+
}
134+
135+
[Fact]
136+
public void OnComponentChanging_ShouldReturnFalse_WhenChangeServiceThrowsCheckoutExceptionCanceled()
137+
{
138+
_mockChangeService
139+
.Setup(cs => cs.OnComponentChanging(It.IsAny<object>(), It.IsAny<PropertyDescriptor>()))
140+
.Throws(CheckoutException.Canceled);
141+
142+
_mockSite.Setup(s => s.GetService(typeof(IComponentChangeService))).Returns(_mockChangeService.Object);
143+
_component.Site = _mockSite.Object;
144+
145+
EditorServiceContext context = new(_designer, _mockPropertyDescriptor.Object);
146+
147+
bool result = ((ITypeDescriptorContext)context).OnComponentChanging();
148+
149+
result.Should().BeFalse();
150+
_mockChangeService.Verify(cs => cs.OnComponentChanging(_component, _mockPropertyDescriptor.Object), Times.Once);
151+
}
152+
153+
[Fact]
154+
public void ShowDialog_ShouldUseIUIService_WhenAvailable()
155+
{
156+
_mockSite.Setup(s => s.GetService(typeof(IUIService))).Returns(_mockUIService.Object);
157+
_component.Site = _mockSite.Object;
158+
159+
EditorServiceContext context = new(_designer, _mockPropertyDescriptor.Object);
160+
161+
_mockUIService.Setup(s => s.ShowDialog(_mockDialog.Object)).Returns(DialogResult.OK);
162+
163+
DialogResult result = ((IWindowsFormsEditorService)context).ShowDialog(_mockDialog.Object);
164+
165+
result.Should().Be(DialogResult.OK);
166+
_mockUIService.Verify(s => s.ShowDialog(_mockDialog.Object), Times.Once);
167+
}
168+
169+
[Fact]
170+
public void ShowDialog_ShouldFallbackToFormShowDialog_WhenIUIServiceNotAvailable()
171+
{
172+
_mockSite.Setup(s => s.GetService(typeof(IUIService))).Returns((object?)null);
173+
_component.Site = _mockSite.Object;
174+
175+
EditorServiceContext context = new(_designer, _mockPropertyDescriptor.Object);
176+
177+
Mock<IWindowsFormsEditorService> mockEditorService = new();
178+
mockEditorService.Setup(es => es.ShowDialog(It.IsAny<Form>())).Returns(DialogResult.Cancel);
179+
180+
DialogResult result = mockEditorService.Object.ShowDialog(new Form());
181+
182+
result.Should().Be(DialogResult.Cancel);
183+
}
184+
185+
private class TestComponent : Component
186+
{
187+
public List<string> Items { get; set; } = new();
188+
}
189+
190+
private class TestComponentDesigner : ComponentDesigner
191+
{
192+
public TestComponentDesigner(IComponent component) => Initialize(component);
193+
}
194+
195+
private class TypeDescriptionProviderMock : TypeDescriptionProvider
196+
{
197+
private readonly PropertyDescriptor _property;
198+
199+
public TypeDescriptionProviderMock(PropertyDescriptor property) => _property = property;
200+
201+
public override ICustomTypeDescriptor? GetTypeDescriptor(Type objectType, object? instance) => new TypeDescriptorStub(_property);
202+
203+
private class TypeDescriptorStub : CustomTypeDescriptor
204+
{
205+
private readonly PropertyDescriptor _property;
206+
207+
public TypeDescriptorStub(PropertyDescriptor property) => _property = property;
208+
209+
public override PropertyDescriptorCollection GetProperties() => new PropertyDescriptorCollection([_property]);
210+
211+
public override PropertyDescriptorCollection GetProperties(Attribute[]? attributes) => GetProperties();
212+
}
213+
}
214+
}

0 commit comments

Comments
 (0)