11// Licensed to the .NET Foundation under one or more agreements.
22// The .NET Foundation licenses this file to you under the MIT license.
33
4- using System . ComponentModel ;
54using System . ComponentModel . Design . Serialization ;
5+ using System . ComponentModel ;
6+ using System . Globalization ;
67
78namespace System . Windows . Input ;
89
9- public class MouseActionConverterTests
10+ public sealed class MouseActionConverterTests
1011{
11- [ Fact ]
12- public void ConvertTo_ConvertFrom_ReturnsExpected ( )
12+ [ Theory ]
13+ // Supported type
14+ [ InlineData ( true , typeof ( string ) ) ]
15+ // Unsupported types
16+ [ InlineData ( false , typeof ( InstanceDescriptor ) ) ]
17+ [ InlineData ( false , typeof ( MouseAction ) ) ]
18+ public void CanConvertFrom_ReturnsExpected ( bool expected , Type sourceType )
1319 {
1420 MouseActionConverter converter = new ( ) ;
1521
16- // Test MouseAction.None (Special case)
17- string emptyToNone = string . Empty ;
18- MouseAction constantName = MouseAction . None ;
22+ Assert . Equal ( expected , converter . CanConvertFrom ( null , sourceType ) ) ;
23+ }
1924
20- MouseAction lowerCase = ( MouseAction ) converter . ConvertFrom ( null , null , emptyToNone . ToLowerInvariant ( ) ) ;
21- MouseAction upperCase = ( MouseAction ) converter . ConvertFrom ( null , null , emptyToNone . ToUpperInvariant ( ) ) ;
22- MouseAction normalColor = ( MouseAction ) converter . ConvertFrom ( null , null , emptyToNone ) ;
25+ [ Theory ]
26+ [ MemberData ( nameof ( CanConvertTo_Data ) ) ]
27+ public void CanConvertTo_ReturnsExpected ( bool expected , bool passContext , object ? value , Type ? destinationType )
28+ {
29+ MouseActionConverter converter = new ( ) ;
30+ StandardContextImpl context = new ( ) { Instance = value } ;
2331
24- Assert . Equal < MouseAction > ( constantName , lowerCase ) ;
25- Assert . Equal < MouseAction > ( constantName , upperCase ) ;
26- Assert . Equal < MouseAction > ( constantName , normalColor ) ;
32+ Assert . Equal ( expected , converter . CanConvertTo ( passContext ? context : null , destinationType ) ) ;
33+ }
2734
28- // Test the rest of the enum
29- foreach ( string action in Enum . GetNames < MouseAction > ( ) )
35+ public static IEnumerable < object ? [ ] > CanConvertTo_Data
36+ {
37+ get
3038 {
31- constantName = Enum . Parse < MouseAction > ( action ) ;
39+ // Supported cases
40+ yield return new object [ ] { true , true , MouseAction . None , typeof ( string ) } ;
41+ yield return new object [ ] { true , true , MouseAction . MiddleDoubleClick , typeof ( string ) } ;
3242
33- lowerCase = ( MouseAction ) converter . ConvertFrom ( null , null , action . ToLowerInvariant ( ) ) ;
34- upperCase = ( MouseAction ) converter . ConvertFrom ( null , null , action . ToUpperInvariant ( ) ) ;
35- normalColor = ( MouseAction ) converter . ConvertFrom ( null , null , action ) ;
43+ // Unsupported case (Value is above MouseAction range)
44+ yield return new object [ ] { false , true , MouseAction . MiddleDoubleClick + 1 , typeof ( string ) } ;
3645
37- Assert . Equal < MouseAction > ( constantName , lowerCase ) ;
38- Assert . Equal < MouseAction > ( constantName , upperCase ) ;
39- Assert . Equal < MouseAction > ( constantName , normalColor ) ;
46+ // Unsupported cases
47+ yield return new object [ ] { false , false , MouseAction . None , typeof ( string ) } ;
48+ yield return new object [ ] { false , false , MouseAction . MiddleDoubleClick , typeof ( string ) } ;
49+ yield return new object ? [ ] { false , true , null , typeof ( MouseAction ) } ;
50+ yield return new object ? [ ] { false , true , null , typeof ( string ) } ;
51+ yield return new object ? [ ] { false , false , MouseAction . MiddleDoubleClick , typeof ( string ) } ;
52+ yield return new object ? [ ] { false , false , null , typeof ( string ) } ;
53+ yield return new object ? [ ] { false , false , null , null } ;
4054
41- // Back to the original values
42- string result = ( string ) converter . ConvertTo ( null , null , constantName , typeof ( string ) ) ;
43- result = result == string . Empty ? "None" : result ; // Test for MouseAction.None (Special case)
44- Assert . Equal ( action , result ) ;
55+ yield return new object [ ] { false , true , MouseAction . MiddleDoubleClick + 1 , typeof ( string ) } ;
4556 }
4657 }
4758
4859 [ Fact ]
49- public void ConvertTo_ThrowsArgumentNullException ( )
60+ public void CanConvertTo_ThrowsInvalidCastException ( )
5061 {
5162 MouseActionConverter converter = new ( ) ;
63+ StandardContextImpl context = new ( ) { Instance = 10 } ;
5264
53- Assert . Throws < ArgumentNullException > ( ( ) => converter . ConvertTo ( MouseAction . None , destinationType : null ! ) ) ;
65+ // TODO: CanConvert* methods should not throw but the implementation is faulty
66+ Assert . Throws < InvalidCastException > ( ( ) => converter . CanConvertTo ( context , typeof ( string ) ) ) ;
5467 }
5568
5669 [ Theory ]
57- [ InlineData ( null , typeof ( string ) ) ] // Unsupported value
58- [ InlineData ( MouseAction . None , typeof ( int ) ) ] // Unsupported destinationType
59- public void ConvertTo_ThrowsNotSupportedException ( object ? value , Type destinationType )
70+ [ MemberData ( nameof ( ConvertFrom_ReturnsExpected_Data ) ) ]
71+ public void ConvertFrom_ReturnsExpected ( MouseAction expected , ITypeDescriptorContext context , CultureInfo ? cultureInfo , string value )
6072 {
6173 MouseActionConverter converter = new ( ) ;
6274
63- Assert . Throws < NotSupportedException > ( ( ) => converter . ConvertTo ( value , destinationType ) ) ;
75+ Assert . Equal ( expected , ( MouseAction ) converter . ConvertFrom ( context , cultureInfo , value ) ) ;
6476 }
6577
66- [ Fact ]
67- public void ConvertTo_ThrowsInvalidCastException ( )
78+ public static IEnumerable < object ? [ ] > ConvertFrom_ReturnsExpected_Data
6879 {
69- MouseActionConverter converter = new ( ) ;
70-
71- Assert . Throws < InvalidCastException > ( ( ) => converter . ConvertTo ( null , null , ( int ) ( MouseAction . MiddleDoubleClick ) , typeof ( string ) ) ) ;
72- }
73-
74- [ Fact ]
75- public void ConvertTo_ThrowsInvalidEnumArgumentException ( )
76- {
77- MouseActionConverter converter = new ( ) ;
78-
79- Assert . Throws < InvalidEnumArgumentException > ( ( ) => converter . ConvertTo ( null , null , ( MouseAction ) ( MouseAction . MiddleDoubleClick + 1 ) , typeof ( string ) ) ) ;
80+ get
81+ {
82+ // ConvertTo handles two different inputs as MouseAction.None
83+ yield return new object ? [ ] { MouseAction . None , null , CultureInfo . InvariantCulture , string . Empty } ;
84+ yield return new object ? [ ] { MouseAction . None , null , CultureInfo . InvariantCulture , "None" } ;
85+
86+ // Supported cases (Culture must stay irrelevant)
87+ yield return new object ? [ ] { MouseAction . None , null , CultureInfo . InvariantCulture , string . Empty } ;
88+ yield return new object ? [ ] { MouseAction . LeftClick , null , new CultureInfo ( "ru-RU" ) , "LeftClick" } ;
89+ yield return new object ? [ ] { MouseAction . RightClick , null , CultureInfo . InvariantCulture , "RightClick" } ;
90+ yield return new object ? [ ] { MouseAction . MiddleClick , null , CultureInfo . InvariantCulture , "MiddleClick" } ;
91+ yield return new object ? [ ] { MouseAction . WheelClick , null , new CultureInfo ( "no-NO" ) , "WheelClick" } ;
92+ yield return new object ? [ ] { MouseAction . LeftDoubleClick , null , CultureInfo . InvariantCulture , "LeftDoubleClick" } ;
93+ yield return new object ? [ ] { MouseAction . RightDoubleClick , null , CultureInfo . InvariantCulture , "RightDoubleClick" } ;
94+ yield return new object ? [ ] { MouseAction . MiddleDoubleClick , null , CultureInfo . InvariantCulture , "MiddleDoubleClick" } ;
95+
96+ // Supported cases (fuzzed via whitespace and casing)
97+ yield return new object ? [ ] { MouseAction . None , null , CultureInfo . InvariantCulture , " " } ;
98+ yield return new object ? [ ] { MouseAction . None , null , new CultureInfo ( "ru-RU" ) , " NoNE " } ;
99+ yield return new object ? [ ] { MouseAction . LeftClick , null , CultureInfo . InvariantCulture , " LeFTCliCK " } ;
100+ yield return new object ? [ ] { MouseAction . WheelClick , null , CultureInfo . InvariantCulture , " WHEELCLICK" } ;
101+ yield return new object ? [ ] { MouseAction . MiddleClick , null , new CultureInfo ( "no-NO" ) , " MiDDLeCliCK " } ;
102+ yield return new object ? [ ] { MouseAction . LeftDoubleClick , null , CultureInfo . InvariantCulture , " leftdoubleclick " } ;
103+ yield return new object ? [ ] { MouseAction . RightClick , null , CultureInfo . InvariantCulture , " rightclick" } ;
104+ }
80105 }
81106
82107 [ Theory ]
83108 // Unsupported values (data type)
84109 [ InlineData ( null ) ]
110+ [ InlineData ( Key . VolumeDown ) ]
85111 [ InlineData ( MouseAction . None ) ]
86112 // Unsupported value (bad string)
87113 [ InlineData ( "BadString" ) ]
114+ [ InlineData ( "MouseZClick" ) ]
88115 public void ConvertFrom_ThrowsNotSupportedException ( object ? value )
89116 {
90117 MouseActionConverter converter = new ( ) ;
@@ -93,64 +120,67 @@ public void ConvertFrom_ThrowsNotSupportedException(object? value)
93120 }
94121
95122 [ Theory ]
96- // Supported type
97- [ InlineData ( true , typeof ( string ) ) ]
98- // Unsupported types
99- [ InlineData ( false , typeof ( InstanceDescriptor ) ) ]
100- [ InlineData ( false , typeof ( MouseAction ) ) ]
101- public void CanConvertFrom_ReturnsExpected ( bool expected , Type sourceType )
123+ [ MemberData ( nameof ( ConvertTo_ReturnsExpected_Data ) ) ]
124+ public void ConvertTo_ReturnsExpected ( string expected , ITypeDescriptorContext context , CultureInfo ? cultureInfo , object ? value )
102125 {
103126 MouseActionConverter converter = new ( ) ;
104127
105- Assert . Equal ( expected , converter . CanConvertFrom ( null , sourceType ) ) ;
128+ // Culture and context must not have any meaning
129+ Assert . Equal ( expected , ( string ) converter . ConvertTo ( context , cultureInfo , value , typeof ( string ) ) ) ;
130+ }
131+
132+ public static IEnumerable < object ? [ ] > ConvertTo_ReturnsExpected_Data
133+ {
134+ get
135+ {
136+ // Supported cases (Culture must stay irrelevant)
137+ yield return new object ? [ ] { string . Empty , null , CultureInfo . InvariantCulture , MouseAction . None } ;
138+ yield return new object ? [ ] { "LeftClick" , null , CultureInfo . InvariantCulture , MouseAction . LeftClick } ;
139+ yield return new object ? [ ] { "RightClick" , null , new CultureInfo ( "ru-RU" ) , MouseAction . RightClick } ;
140+ yield return new object ? [ ] { "MiddleClick" , null , CultureInfo . InvariantCulture , MouseAction . MiddleClick } ;
141+ yield return new object ? [ ] { "WheelClick" , null , new CultureInfo ( "no-NO" ) , MouseAction . WheelClick } ;
142+ yield return new object ? [ ] { "LeftDoubleClick" , null , CultureInfo . InvariantCulture , MouseAction . LeftDoubleClick } ;
143+ yield return new object ? [ ] { "RightDoubleClick" , null , null , MouseAction . RightDoubleClick } ;
144+ yield return new object ? [ ] { "MiddleDoubleClick" , null , null , MouseAction . MiddleDoubleClick } ;
145+ }
106146 }
107147
108148 [ Fact ]
109- public void CanConvertTo_ThrowsInvalidCastException ( )
149+ public void ConvertTo_ThrowsArgumentNullException ( )
110150 {
111151 MouseActionConverter converter = new ( ) ;
112- StandardContextImpl context = new ( ) ;
113- context . Instance = 10 ;
114152
115- // NOTE: CanConvert* methods should not throw but the implementation is faulty
116- Assert . Throws < InvalidCastException > ( ( ) => converter . CanConvertTo ( context , typeof ( string ) ) ) ;
153+ Assert . Throws < ArgumentNullException > ( ( ) => converter . ConvertTo ( MouseAction . None , destinationType : null ! ) ) ;
117154 }
118155
119156 [ Theory ]
120- [ MemberData ( nameof ( CanConvertTo_Data ) ) ]
121- public void CanConvertTo_ReturnsExpected ( bool expected , bool passContext , object ? value , Type ? destinationType )
157+ // Unsupported value
158+ [ InlineData ( null , typeof ( string ) ) ]
159+ // Unsupported destinationType
160+ [ InlineData ( MouseAction . None , typeof ( int ) ) ]
161+ [ InlineData ( MouseAction . LeftClick , typeof ( byte ) ) ]
162+ public void ConvertTo_ThrowsNotSupportedException ( object ? value , Type destinationType )
122163 {
123164 MouseActionConverter converter = new ( ) ;
124- StandardContextImpl context = new ( )
125- {
126- Instance = value
127- } ;
128165
129- Assert . Equal ( expected , converter . CanConvertTo ( passContext ? context : null , destinationType ) ) ;
166+ Assert . Throws < NotSupportedException > ( ( ) => converter . ConvertTo ( value , destinationType ) ) ;
130167 }
131168
132- public static IEnumerable < object ? [ ] > CanConvertTo_Data
169+ [ Fact ]
170+ public void ConvertTo_ThrowsInvalidCastException ( )
133171 {
134- get
135- {
136- // Supported cases
137- yield return new object [ ] { true , true , MouseAction . None , typeof ( string ) } ;
138- yield return new object [ ] { true , true , MouseAction . MiddleDoubleClick , typeof ( string ) } ;
172+ MouseActionConverter converter = new ( ) ;
139173
140- // Unsupported case (Value is above MouseAction range)
141- yield return new object [ ] { false , true , MouseAction . MiddleDoubleClick + 1 , typeof ( string ) } ;
174+ // TODO: This should not throw InvalidCastException but NotSupportedException
175+ Assert . Throws < InvalidCastException > ( ( ) => converter . ConvertTo ( null , null , ( int ) ( MouseAction . MiddleDoubleClick ) , typeof ( string ) ) ) ;
176+ }
142177
143- // Unsupported cases
144- yield return new object [ ] { false , false , MouseAction . None , typeof ( string ) } ;
145- yield return new object [ ] { false , false , MouseAction . MiddleDoubleClick , typeof ( string ) } ;
146- yield return new object ? [ ] { false , true , null , typeof ( MouseAction ) } ;
147- yield return new object ? [ ] { false , true , null , typeof ( string ) } ;
148- yield return new object ? [ ] { false , false , MouseAction . MiddleDoubleClick , typeof ( string ) } ;
149- yield return new object ? [ ] { false , false , null , typeof ( string ) } ;
150- yield return new object ? [ ] { false , false , null , null } ;
178+ [ Fact ]
179+ public void ConvertTo_ThrowsInvalidEnumArgumentException ( )
180+ {
181+ MouseActionConverter converter = new ( ) ;
151182
152- yield return new object [ ] { false , true , MouseAction . MiddleDoubleClick + 1 , typeof ( string ) } ;
153- }
183+ Assert . Throws < InvalidEnumArgumentException > ( ( ) => converter . ConvertTo ( null , null , ( MouseAction ) ( MouseAction . MiddleDoubleClick + 1 ) , typeof ( string ) ) ) ;
154184 }
155185
156186 public sealed class StandardContextImpl : ITypeDescriptorContext
0 commit comments