Skip to content

Commit fb6216b

Browse files
authored
Add code coverage for RadioButtonBaseAdapter (#13726)
* Add code coverage for RadioButtonBaseAdapter * Address FeedBacks * Address FeedBacks
1 parent 9f6fa39 commit fb6216b

File tree

1 file changed

+314
-0
lines changed

1 file changed

+314
-0
lines changed
Lines changed: 314 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,314 @@
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.Drawing;
5+
using System.Windows.Forms.ButtonInternal;
6+
using static System.Windows.Forms.ButtonInternal.ButtonBaseAdapter;
7+
8+
namespace System.Windows.Forms.Tests;
9+
10+
public class RadioButtonBaseAdapterTests
11+
{
12+
private class TestRadioButton : RadioButton
13+
{
14+
public TestRadioButton()
15+
{
16+
}
17+
18+
public void InvokeOnMouseDown(MouseEventArgs e)
19+
{
20+
base.OnMouseDown(e);
21+
}
22+
23+
public void InvokeOnMouseUp(MouseEventArgs e)
24+
{
25+
base.OnMouseUp(e);
26+
}
27+
}
28+
29+
private class TestRadioButtonBaseAdapter : RadioButtonBaseAdapter
30+
{
31+
public TestRadioButtonBaseAdapter(RadioButton control) : base(control)
32+
{
33+
}
34+
35+
public new RadioButton Control => base.Control;
36+
37+
public void DrawFlatCheckMark(PaintEventArgs e, LayoutData layout, Color checkColor, Color checkBackground, Color checkBorder)
38+
=> DrawCheckFlat(e, layout, checkColor, checkBackground, checkBorder);
39+
40+
public void DrawBackgroundFlatMark(PaintEventArgs e, Rectangle bounds, Color borderColor, Color checkBackground)
41+
=> DrawCheckBackgroundFlat(e, bounds, borderColor, checkBackground);
42+
43+
public void DrawBackground3DLiteMark(PaintEventArgs e, Rectangle bounds, Color checkBackground, ColorData colors, bool disabledColors)
44+
=> DrawCheckBackground3DLite(e, bounds, checkBackground, colors, disabledColors);
45+
46+
public void DrawCheckOnlyMark(PaintEventArgs e, LayoutData layout, Color checkColor, bool disabledColors)
47+
=> DrawCheckOnly(e, layout, checkColor, disabledColors);
48+
49+
public ButtonState GetStateMark() => GetState();
50+
51+
public void DrawCheckBoxMark(PaintEventArgs e, LayoutData layout)
52+
=> DrawCheckBox(e, layout);
53+
54+
public void AdjustFocusRectangleMark(LayoutData layout)
55+
=> AdjustFocusRectangle(layout);
56+
57+
public LayoutOptions GetLayoutOptions() => CommonLayout();
58+
internal override void PaintOver(PaintEventArgs e, CheckState state)
59+
{
60+
}
61+
62+
internal override void PaintUp(PaintEventArgs e, CheckState state)
63+
{
64+
}
65+
66+
internal override void PaintDown(PaintEventArgs e, CheckState state)
67+
{
68+
}
69+
70+
protected override LayoutOptions Layout(PaintEventArgs e)
71+
{
72+
return new LayoutOptions();
73+
}
74+
75+
protected override ButtonBaseAdapter CreateButtonAdapter()
76+
{
77+
return this;
78+
}
79+
}
80+
81+
private static (TestRadioButton, TestRadioButtonBaseAdapter) CreateAdapter()
82+
{
83+
using TestRadioButton radioButton = new();
84+
TestRadioButtonBaseAdapter radioButtonBaseAdapter = new(radioButton);
85+
86+
return (radioButton, radioButtonBaseAdapter);
87+
}
88+
89+
/// <summary>
90+
/// Determines whether any pixel within the specified bounds of the bitmap differs from the reference pixel
91+
/// at the top-left corner of the bounds. Used to verify if drawing operations have modified the bitmap.
92+
/// </summary>
93+
/// <param name="bmp">The bitmap to inspect.</param>
94+
/// <param name="bounds">The rectangle area within the bitmap to check for changes.</param>
95+
/// <returns>
96+
/// <see langword="true"/> if any pixel in the bounds differs from the reference pixel; otherwise, <see langword="false"/>.
97+
/// </returns>
98+
private static bool HasPixelChanged(Bitmap bmp, Rectangle bounds)
99+
{
100+
Color referenceColor = bmp.GetPixel(bounds.X, bounds.Y);
101+
102+
for (int x = bounds.X; x < bounds.Right; x++)
103+
{
104+
for (int y = bounds.Y; y < bounds.Bottom; y++)
105+
{
106+
if (bmp.GetPixel(x, y) != referenceColor)
107+
{
108+
return true;
109+
}
110+
}
111+
}
112+
113+
return false;
114+
}
115+
116+
[WinFormsFact]
117+
public void DrawCheckFlat_CallsBackgroundAndCheckOnly()
118+
{
119+
(_, TestRadioButtonBaseAdapter radioButtonBaseAdapter) = CreateAdapter();
120+
using Bitmap bmp = new(20, 20);
121+
using Graphics g = Graphics.FromImage(bmp);
122+
using PaintEventArgs e = new(g, new Rectangle(0, 0, 20, 20));
123+
LayoutData layout = new(new LayoutOptions());
124+
125+
radioButtonBaseAdapter.DrawFlatCheckMark(e, layout, Color.Red, Color.Blue, Color.Green);
126+
127+
bool anyPixelChanged = HasPixelChanged(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height));
128+
129+
anyPixelChanged.Should().BeTrue("DrawCheckFlat should modify the bitmap.");
130+
}
131+
132+
[WinFormsFact]
133+
public void DrawCheckBackgroundFlat_EnabledAndDisabled_ChangesColors()
134+
{
135+
(TestRadioButton radioButton, TestRadioButtonBaseAdapter radioButtonBaseAdapter) = CreateAdapter();
136+
using Bitmap bmp = new(20, 20);
137+
using Graphics g = Graphics.FromImage(bmp);
138+
using PaintEventArgs e = new(g, new Rectangle(0, 0, 20, 20));
139+
Rectangle bounds = new(1, 1, 12, 12);
140+
141+
radioButton.Enabled = true;
142+
radioButtonBaseAdapter.DrawBackgroundFlatMark(e, bounds, Color.Black, Color.White);
143+
144+
bool anyPixelChangedEnabled = HasPixelChanged(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height));
145+
146+
anyPixelChangedEnabled.Should().BeTrue("drawing the background when enabled should modify the bitmap in the bounds area");
147+
148+
using (Graphics clearG = Graphics.FromImage(bmp))
149+
{
150+
clearG.Clear(Color.Empty);
151+
}
152+
153+
radioButton.Enabled = false;
154+
radioButtonBaseAdapter.DrawBackgroundFlatMark(e, bounds, Color.Black, Color.White);
155+
156+
bool anyPixelChangedDisabled = HasPixelChanged(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height));
157+
158+
anyPixelChangedDisabled.Should().BeTrue("drawing the background when disabled should modify the bitmap in the bounds area");
159+
}
160+
161+
[WinFormsFact]
162+
public void DrawCheckBackground3DLite_EnabledAndDisabled_UsesCorrectColors()
163+
{
164+
(TestRadioButton radioButton, TestRadioButtonBaseAdapter radioButtonBaseAdapter) = CreateAdapter();
165+
using Bitmap bmp = new(20, 20);
166+
using Graphics g = Graphics.FromImage(bmp);
167+
using PaintEventArgs e = new(g, new Rectangle(0, 0, 20, 20));
168+
Rectangle bounds = new(1, 1, 12, 12);
169+
ColorData colors = new(
170+
new ColorOptions(
171+
g,
172+
Color.Black,
173+
Color.White
174+
)
175+
)
176+
{
177+
ButtonFace = Color.Gray,
178+
ButtonShadow = Color.DarkGray,
179+
Highlight = Color.LightGray
180+
};
181+
182+
radioButton.Enabled = true;
183+
radioButtonBaseAdapter.DrawBackground3DLiteMark(e, bounds, Color.White, colors, disabledColors: false);
184+
185+
bool anyPixelChangedEnabled = HasPixelChanged(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height));
186+
187+
anyPixelChangedEnabled.Should().BeTrue("drawing the 3D lite background when enabled should modify the bitmap in the bounds area");
188+
189+
using (Graphics clearG = Graphics.FromImage(bmp))
190+
{
191+
clearG.Clear(Color.Empty);
192+
}
193+
194+
radioButton.Enabled = false;
195+
radioButtonBaseAdapter.DrawBackground3DLiteMark(e, bounds, Color.White, colors, disabledColors: true);
196+
197+
bool anyPixelChangedDisabled = HasPixelChanged(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height));
198+
199+
anyPixelChangedDisabled.Should().BeTrue("drawing the 3D lite background when disabled should modify the bitmap in the bounds area");
200+
}
201+
202+
[WinFormsFact]
203+
public void DrawCheckOnly_CheckedAndUnchecked_DrawsOrSkips()
204+
{
205+
(TestRadioButton radioButton, TestRadioButtonBaseAdapter radioButtonBaseAdapter) = CreateAdapter();
206+
using Bitmap bmp = new(20, 20);
207+
using Graphics g = Graphics.FromImage(bmp);
208+
using PaintEventArgs e = new(g, new Rectangle(0, 0, 20, 20));
209+
LayoutData layoutData = new(new LayoutOptions())
210+
{
211+
CheckBounds = new Rectangle(2, 2, 12, 12)
212+
};
213+
214+
radioButton.Checked = false;
215+
radioButtonBaseAdapter.DrawCheckOnlyMark(e, layoutData, Color.Black, disabledColors: false);
216+
217+
bool anyPixelChangedUnchecked = HasPixelChanged(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height));
218+
219+
anyPixelChangedUnchecked.Should().BeFalse("DrawCheckOnly should not modify the bitmap when unchecked.");
220+
221+
radioButton.Checked = true;
222+
radioButton.Enabled = true;
223+
radioButtonBaseAdapter.DrawCheckOnlyMark(e, layoutData, Color.Black, disabledColors: false);
224+
225+
bool anyPixelChangedChecked = HasPixelChanged(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height));
226+
227+
anyPixelChangedChecked.Should().BeTrue("DrawCheckOnly should modify the bitmap when checked and enabled.");
228+
229+
radioButton.Enabled = false;
230+
radioButtonBaseAdapter.DrawCheckOnlyMark(e, layoutData, Color.Black, disabledColors: true);
231+
232+
bool anyPixelChangedCheckedDisabled = HasPixelChanged(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height));
233+
234+
anyPixelChangedCheckedDisabled.Should().BeTrue("DrawCheckOnly should modify the bitmap when checked and disabled.");
235+
}
236+
237+
[WinFormsFact]
238+
public void GetState_ReturnsCorrectButtonState()
239+
{
240+
(TestRadioButton radioButton, TestRadioButtonBaseAdapter radioButtonBaseAdapter) = CreateAdapter();
241+
242+
radioButton.Checked = false;
243+
radioButton.Enabled = true;
244+
radioButton.InvokeOnMouseUp(new MouseEventArgs(MouseButtons.Left, 1, 0, 0, 0));
245+
ButtonState state = radioButtonBaseAdapter.GetStateMark();
246+
247+
state.Should().Be(ButtonState.Normal);
248+
249+
radioButton.Checked = true;
250+
state = radioButtonBaseAdapter.GetStateMark();
251+
252+
state.HasFlag(ButtonState.Checked).Should().BeTrue();
253+
254+
radioButton.Enabled = false;
255+
state = radioButtonBaseAdapter.GetStateMark();
256+
257+
state.HasFlag(ButtonState.Inactive).Should().BeTrue();
258+
259+
radioButton.Enabled = true;
260+
radioButton.InvokeOnMouseDown(new MouseEventArgs(MouseButtons.Left, 1, 0, 0, 0));
261+
state = radioButtonBaseAdapter.GetStateMark();
262+
263+
state.HasFlag(ButtonState.Pushed).Should().BeTrue();
264+
}
265+
266+
[WinFormsFact]
267+
public void DrawCheckBox_VisualStylesAndNoVisualStyles_DoesNotThrow()
268+
{
269+
(_, TestRadioButtonBaseAdapter radioButtonBaseAdapter) = CreateAdapter();
270+
using Bitmap bmp = new(20, 20);
271+
using Graphics g = Graphics.FromImage(bmp);
272+
using PaintEventArgs e = new(g, new Rectangle(0, 0, 20, 20));
273+
LayoutData layoutData = new(new LayoutOptions())
274+
{
275+
CheckBounds = new Rectangle(2, 2, 12, 12)
276+
};
277+
278+
radioButtonBaseAdapter.DrawCheckBoxMark(e, layoutData);
279+
280+
bool anyPixelChanged = HasPixelChanged(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height));
281+
282+
anyPixelChanged.Should().BeTrue("DrawCheckBox should modify the bitmap.");
283+
}
284+
285+
[WinFormsFact]
286+
public void AdjustFocusRectangle_AutoSizeAndNoText_ChangesFocus()
287+
{
288+
(TestRadioButton radioButton, TestRadioButtonBaseAdapter radioButtonBaseAdapter) = CreateAdapter();
289+
LayoutData layoutData = new(new LayoutOptions())
290+
{
291+
CheckBounds = new Rectangle(1, 2, 3, 4),
292+
Field = new Rectangle(5, 6, 7, 8)
293+
};
294+
295+
radioButton.Text = string.Empty;
296+
radioButton.AutoSize = true;
297+
radioButtonBaseAdapter.AdjustFocusRectangleMark(layoutData);
298+
layoutData.Focus.Should().Be(layoutData.CheckBounds);
299+
300+
radioButton.AutoSize = false;
301+
radioButtonBaseAdapter.AdjustFocusRectangleMark(layoutData);
302+
layoutData.Focus.Should().Be(layoutData.Field);
303+
}
304+
305+
[WinFormsFact]
306+
public void CommonLayout_SetsCheckAlign()
307+
{
308+
(TestRadioButton radioButton, TestRadioButtonBaseAdapter radioButtonBaseAdapter) = CreateAdapter();
309+
radioButton.CheckAlign = ContentAlignment.BottomRight;
310+
LayoutOptions layoutOptions = radioButtonBaseAdapter.CommonLayout();
311+
312+
layoutOptions.CheckAlign.Should().Be(ContentAlignment.BottomRight);
313+
}
314+
}

0 commit comments

Comments
 (0)