1
1
// Copyright (c) .NET Foundation. All rights reserved.
2
2
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3
3
4
+ using System ;
5
+ using System . Collections . Generic ;
6
+ using System . Linq . Expressions ;
4
7
using Microsoft . AspNet . Mvc . ModelBinding ;
5
8
using Microsoft . AspNet . Mvc . ModelBinding . Metadata ;
6
9
using Microsoft . AspNet . Mvc . Rendering ;
10
+ using Microsoft . AspNet . Testing ;
7
11
using Moq ;
8
12
using Xunit ;
9
13
@@ -14,6 +18,26 @@ namespace Microsoft.AspNet.Mvc.Core
14
18
/// </summary>
15
19
public class HtmlHelperNameExtensionsTest
16
20
{
21
+ private static List < string > _staticCollection = new List < string > ( ) ;
22
+ private static int _staticIndex = 6 ;
23
+
24
+ private List < string > _collection = new List < string > ( ) ;
25
+ private int _index = 7 ;
26
+ private List < string [ ] > _nestedCollection = new List < string [ ] > ( ) ;
27
+ private string _string = string . Empty ;
28
+
29
+ private static List < string > StaticCollection { get ; }
30
+
31
+ private static int StaticIndex { get ; } = 8 ;
32
+
33
+ private List < string > Collection { get ; }
34
+
35
+ private int Index { get ; } = 9 ;
36
+
37
+ private List < string [ ] > NestedCollection { get ; }
38
+
39
+ private string StringProperty { get ; }
40
+
17
41
[ Fact ]
18
42
public void IdAndNameHelpers_ReturnEmptyForModel ( )
19
43
{
@@ -140,7 +164,7 @@ public void IdAndNameHelpers_DoNotConsultMetadataOrMetadataProvider()
140
164
// Arrange
141
165
var provider = new Mock < IModelMetadataProvider > ( MockBehavior . Strict ) ;
142
166
var metadata = new Mock < ModelMetadata > (
143
- MockBehavior . Loose ,
167
+ MockBehavior . Loose ,
144
168
ModelMetadataIdentity . ForType ( typeof ( DefaultTemplatesUtilities . ObjectTemplateModel ) ) ) ;
145
169
provider
146
170
. Setup ( m => m . GetMetadataForType ( typeof ( DefaultTemplatesUtilities . ObjectTemplateModel ) ) )
@@ -223,28 +247,106 @@ public void IdForAndNameFor_ReturnEmpty_IfExpressionUnsupported()
223
247
Assert . Empty ( nameResult ) ;
224
248
}
225
249
226
- [ Fact ]
227
- public void IdForAndNameFor_ReturnVariableName ( )
250
+ // expression, expected name, expected id
251
+ public static TheoryData StaticExpressionNamesData
252
+ {
253
+ get
254
+ {
255
+ // Give expressions access to non-static fields and properties.
256
+ var test = new HtmlHelperNameExtensionsTest ( ) ;
257
+ return test . ExpressionNamesData ;
258
+ }
259
+ }
260
+
261
+ // expression, expected name, expected id
262
+ private TheoryData ExpressionNamesData
263
+ {
264
+ get
265
+ {
266
+ var collection = new List < string > ( ) ;
267
+ var nestedCollection = new List < string [ ] > ( ) ;
268
+ var index1 = 5 ;
269
+ var index2 = 23 ;
270
+ var unknownKey = "this is a dummy parameter value" ;
271
+
272
+ return new TheoryData < Expression < Func < List < OuterClass > , string > > , string , string >
273
+ {
274
+ { m => unknownKey , "unknownKey" , "unknownKey" } ,
275
+ { m => collection [ index1 ] , "collection[5]" , "collection_5_" } ,
276
+ { m => nestedCollection [ index1 ] [ 23 ] , "nestedCollection[5][23]" , "nestedCollection_5__23_" } ,
277
+ { m => nestedCollection [ index1 ] [ index2 ] , "nestedCollection[5][23]" , "nestedCollection_5__23_" } ,
278
+ { m => nestedCollection [ _index ] [ Index ] , "nestedCollection[7][9]" , "nestedCollection_7__9_" } ,
279
+ { m => nestedCollection [ Index ] [ StaticIndex ] , "nestedCollection[9][8]" , "nestedCollection_9__8_" } ,
280
+ { m => _string , "_string" , "zstring" } ,
281
+ { m => _collection [ _index ] , "_collection[7]" , "zcollection_7_" } ,
282
+ { m => _nestedCollection [ _index ] [ 23 ] , "_nestedCollection[7][23]" , "znestedCollection_7__23_" } ,
283
+ { m => _nestedCollection [ _index ] [ index2 ] , "_nestedCollection[7][23]" , "znestedCollection_7__23_" } ,
284
+ { m => _nestedCollection [ Index ] [ _staticIndex ] , "_nestedCollection[9][6]" , "znestedCollection_9__6_" } ,
285
+ { m => _nestedCollection [ StaticIndex ] [ _index ] , "_nestedCollection[8][7]" , "znestedCollection_8__7_" } ,
286
+ { m => StringProperty , "StringProperty" , "StringProperty" } ,
287
+ { m => Collection [ Index ] , "Collection[9]" , "Collection_9_" } ,
288
+ { m => NestedCollection [ Index ] [ 23 ] , "NestedCollection[9][23]" , "NestedCollection_9__23_" } ,
289
+ { m => NestedCollection [ Index ] [ index2 ] , "NestedCollection[9][23]" , "NestedCollection_9__23_" } ,
290
+ { m => NestedCollection [ _index ] [ Index ] , "NestedCollection[7][9]" , "NestedCollection_7__9_" } ,
291
+ { m => NestedCollection [ Index ] [ StaticIndex ] , "NestedCollection[9][8]" , "NestedCollection_9__8_" } ,
292
+ { m => _staticCollection [ _staticIndex ] , "_staticCollection[6]" , "zstaticCollection_6_" } ,
293
+ { m => _staticCollection [ Index ] , "_staticCollection[9]" , "zstaticCollection_9_" } ,
294
+ { m => _staticCollection [ _index ] , "_staticCollection[7]" , "zstaticCollection_7_" } ,
295
+ { m => StaticCollection [ StaticIndex ] , "StaticCollection[8]" , "StaticCollection_8_" } ,
296
+ { m => StaticCollection [ _staticIndex ] , "StaticCollection[6]" , "StaticCollection_6_" } ,
297
+ { m => StaticCollection [ index1 ] , "StaticCollection[5]" , "StaticCollection_5_" } ,
298
+ { m => m [ index1 ] . Inner . Name , "[5].Inner.Name" , "z5__Inner_Name" } ,
299
+ { m => m [ _staticIndex ] . Inner . Name , "[6].Inner.Name" , "z6__Inner_Name" } ,
300
+ { m => m [ _index ] . Inner . Name , "[7].Inner.Name" , "z7__Inner_Name" } ,
301
+ { m => m [ StaticIndex ] . Inner . Name , "[8].Inner.Name" , "z8__Inner_Name" } ,
302
+ { m => m [ Index ] . Inner . Name , "[9].Inner.Name" , "z9__Inner_Name" } ,
303
+ } ;
304
+ }
305
+ }
306
+
307
+ [ Theory ]
308
+ [ MemberData ( nameof ( StaticExpressionNamesData ) ) ]
309
+ public void IdForAndNameFor_ReturnExpectedValues_WithVariablesInExpression (
310
+ Expression < Func < List < OuterClass > , string > > expression ,
311
+ string expectedName ,
312
+ string expectedId )
228
313
{
229
314
// Arrange
230
- var unknownKey = "this is a dummy parameter value" ;
231
- var helper = DefaultTemplatesUtilities . GetHtmlHelper ( ) ;
315
+ var model = new List < OuterClass > ( ) ;
316
+ var helper = DefaultTemplatesUtilities . GetHtmlHelper ( model ) ;
232
317
233
318
// Act
234
- var idResult = helper . IdFor ( model => unknownKey ) ;
235
- var nameResult = helper . NameFor ( model => unknownKey ) ;
319
+ var idResult = helper . IdFor ( expression ) ;
320
+ var nameResult = helper . NameFor ( expression ) ;
236
321
237
322
// Assert
238
- Assert . Equal ( "unknownKey" , idResult ) ;
239
- Assert . Equal ( "unknownKey" , nameResult ) ;
323
+ Assert . Equal ( expectedId , idResult ) ;
324
+ Assert . Equal ( expectedName , nameResult ) ;
240
325
}
241
326
242
- private sealed class InnerClass
327
+ [ Fact ]
328
+ public void IdForAndNameFor_Throws_WhenParameterUsedAsIndexer ( )
329
+ {
330
+ // Arrange
331
+ var collection = new List < string > ( ) ;
332
+ var index = 24 ;
333
+ var helper = DefaultTemplatesUtilities . GetHtmlHelper ( index ) ;
334
+ var message = "The expression compiler was unable to evaluate the indexer expression 'm' because it " +
335
+ "references the model parameter 'm' which is unavailable." ;
336
+
337
+ // Act & Assert
338
+ ExceptionAssert . Throws < InvalidOperationException > ( ( ) => helper . IdFor ( m => collection [ m ] ) , message ) ;
339
+ ExceptionAssert . Throws < InvalidOperationException > ( ( ) => helper . NameFor ( m => collection [ m ] ) , message ) ;
340
+ }
341
+
342
+ public sealed class InnerClass
243
343
{
244
344
public int Id { get ; set ; }
345
+
346
+ public string Name { get ; set ; }
245
347
}
246
348
247
- private sealed class OuterClass
349
+ public sealed class OuterClass
248
350
{
249
351
public InnerClass Inner { get ; set ; }
250
352
}
0 commit comments