1
+ // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved.
2
+ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3
+
4
+ using System ;
5
+ using System . Collections . Generic ;
6
+ using System . IO ;
7
+ using System . Reflection ;
8
+ using Microsoft . AspNet . Http ;
9
+ using Microsoft . AspNet . Mvc . ModelBinding ;
10
+ using Microsoft . AspNet . Mvc . Rendering ;
11
+ using Microsoft . AspNet . Razor . Runtime . TagHelpers ;
12
+ using Microsoft . AspNet . Routing ;
13
+ using Moq ;
14
+ using Xunit ;
15
+
16
+ namespace Microsoft . AspNet . Mvc . TagHelpers
17
+ {
18
+ public class FormTagHelperTest
19
+ {
20
+ [ Theory ]
21
+ [ InlineData ( true , "<input />" ) ]
22
+ [ InlineData ( false , "" ) ]
23
+ [ InlineData ( null , "<input />" ) ]
24
+ public void Process_GeneratesAntiForgeryCorrectly ( bool ? antiForgery , string expectedContent )
25
+ {
26
+ // Arrange
27
+ var expectedViewContext = CreateViewContext ( ) ;
28
+ var formTagHelper = new FormTagHelper
29
+ {
30
+ Action = "Index" ,
31
+ AntiForgery = antiForgery
32
+ } ;
33
+ var context = new TagHelperContext (
34
+ allAttributes : new Dictionary < string , object > ( ) ) ;
35
+ var output = new TagHelperOutput (
36
+ "form" ,
37
+ attributes : new Dictionary < string , string > ( ) ,
38
+ content : string . Empty ) ;
39
+
40
+ var generator = new Mock < IHtmlGenerator > ( ) ;
41
+ generator . Setup ( mock =>
42
+ mock . GenerateForm ( It . IsAny < ViewContext > ( ) ,
43
+ It . IsAny < string > ( ) ,
44
+ It . IsAny < string > ( ) ,
45
+ It . IsAny < object > ( ) ,
46
+ It . IsAny < string > ( ) ,
47
+ It . IsAny < object > ( ) ) )
48
+ . Returns ( new TagBuilder ( "form" ) ) ;
49
+ generator . Setup ( mock => mock . GenerateAntiForgery ( It . IsAny < ViewContext > ( ) ) )
50
+ . Returns ( new TagBuilder ( "input" ) ) ;
51
+
52
+ SetViewContextAndGenerator ( formTagHelper ,
53
+ expectedViewContext ,
54
+ generator . Object ) ;
55
+
56
+ // Act
57
+ formTagHelper . Process ( context , output ) ;
58
+
59
+ // Assert
60
+ Assert . Equal ( expectedContent , output . Content ) ;
61
+ }
62
+
63
+ [ Fact ]
64
+ public void Process_UnderstandsRouteValues ( )
65
+ {
66
+ // Arrange
67
+ var testViewContext = CreateViewContext ( ) ;
68
+ var formTagHelper = new FormTagHelper
69
+ {
70
+ Action = "Index" ,
71
+ AntiForgery = false
72
+ } ;
73
+ var context = new TagHelperContext (
74
+ allAttributes : new Dictionary < string , object > ( ) ) ;
75
+ var output = new TagHelperOutput (
76
+ "form" ,
77
+ attributes : new Dictionary < string , string > ( )
78
+ {
79
+ { "route-val" , "hello" } ,
80
+ { "roUte--Foo" , "bar" } ,
81
+ { "ROUTEE-NotRoute" , "something" }
82
+ } ,
83
+ content : string . Empty ) ;
84
+ var called = false ;
85
+ var generator = new Mock < IHtmlGenerator > ( ) ;
86
+ generator . Setup ( mock =>
87
+ mock . GenerateForm ( It . IsAny < ViewContext > ( ) ,
88
+ It . IsAny < string > ( ) ,
89
+ It . IsAny < string > ( ) ,
90
+ It . IsAny < object > ( ) ,
91
+ It . IsAny < string > ( ) ,
92
+ It . IsAny < object > ( ) ) )
93
+ . Callback < ViewContext , string , string , object , string , object > (
94
+ ( viewContext , actionName , controllerName , routeValues , method , htmlAttributes ) =>
95
+ {
96
+ called = true ;
97
+
98
+ var routeValueDictionary = ( Dictionary < string , object > ) routeValues ;
99
+ var routeValue = Assert . Single ( routeValueDictionary , kvp => kvp . Key . Equals ( "val" ) ) ;
100
+ Assert . Equal ( "hello" , routeValue . Value ) ;
101
+ routeValue = Assert . Single ( routeValueDictionary , kvp => kvp . Key . Equals ( "-Foo" ) ) ;
102
+ Assert . Equal ( "bar" , routeValue . Value ) ;
103
+ } )
104
+ . Returns ( new TagBuilder ( "form" ) ) ;
105
+
106
+ SetViewContextAndGenerator ( formTagHelper ,
107
+ testViewContext ,
108
+ generator . Object ) ;
109
+
110
+ // Act & Assert
111
+ formTagHelper . Process ( context , output ) ;
112
+
113
+ var attribute = Assert . Single ( output . Attributes , kvp => kvp . Key . Equals ( "ROUTEE-NotRoute" ) ) ;
114
+ Assert . Equal ( "something" , attribute . Value ) ;
115
+ Assert . True ( called ) ;
116
+ }
117
+
118
+ [ Fact ]
119
+ public void Process_CallsIntoGenerateFormWithExpectedParameters ( )
120
+ {
121
+ // Arrange
122
+ var expectedViewContext = CreateViewContext ( ) ;
123
+ var formTagHelper = new FormTagHelper
124
+ {
125
+ Action = "Index" ,
126
+ Controller = "Home" ,
127
+ Method = "POST" ,
128
+ AntiForgery = false
129
+ } ;
130
+ var called = false ;
131
+ var context = new TagHelperContext (
132
+ allAttributes : new Dictionary < string , object > ( ) ) ;
133
+ var output = new TagHelperOutput (
134
+ "form" ,
135
+ attributes : new Dictionary < string , string > ( ) ,
136
+ content : string . Empty ) ;
137
+
138
+ var generator = new Mock < IHtmlGenerator > ( ) ;
139
+ generator . Setup ( mock =>
140
+ mock . GenerateForm ( It . IsAny < ViewContext > ( ) ,
141
+ It . IsAny < string > ( ) ,
142
+ It . IsAny < string > ( ) ,
143
+ It . IsAny < object > ( ) ,
144
+ It . IsAny < string > ( ) ,
145
+ It . IsAny < object > ( ) ) )
146
+ . Callback < ViewContext , string , string , object , string , object > (
147
+ ( viewContext , actionName , controllerName , routeValues , method , htmlAttributes ) =>
148
+ {
149
+ called = true ;
150
+
151
+ Assert . Same ( expectedViewContext , viewContext ) ;
152
+ Assert . Equal ( "Index" , actionName ) ;
153
+ Assert . Equal ( "Home" , controllerName ) ;
154
+ Assert . Null ( routeValues ) ;
155
+ Assert . Equal ( "POST" , method ) ;
156
+ Assert . Null ( htmlAttributes ) ;
157
+ } )
158
+ . Returns ( new TagBuilder ( "form" ) ) ;
159
+
160
+ SetViewContextAndGenerator ( formTagHelper ,
161
+ expectedViewContext ,
162
+ generator . Object ) ;
163
+
164
+ // Act & Assert
165
+ formTagHelper . Process ( context , output ) ;
166
+
167
+ Assert . True ( called ) ;
168
+ }
169
+
170
+ [ Fact ]
171
+ public void Process_RestoresBoundAttributesIfActionIsURL ( )
172
+ {
173
+ // Arrange
174
+ var formTagHelper = new FormTagHelper
175
+ {
176
+ Action = "http://www.contoso.com" ,
177
+ Method = "POST"
178
+ } ;
179
+ var output = new TagHelperOutput ( "form" ,
180
+ attributes : new Dictionary < string , string > ( ) ,
181
+ content : string . Empty ) ;
182
+ var context = new TagHelperContext (
183
+ allAttributes : new Dictionary < string , object > ( )
184
+ {
185
+ { "aCTiON" , "http://www.contoso.com" } ,
186
+ { "METhod" , "POST" }
187
+ } ) ;
188
+
189
+ // Act
190
+ formTagHelper . Process ( context , output ) ;
191
+
192
+ // Assert
193
+ var attribute = Assert . Single ( output . Attributes , kvp => kvp . Key . Equals ( "aCTiON" ) ) ;
194
+ Assert . Equal ( "http://www.contoso.com" , attribute . Value ) ;
195
+ attribute = Assert . Single ( output . Attributes , kvp => kvp . Key . Equals ( "METhod" ) ) ;
196
+ Assert . Equal ( "POST" , attribute . Value ) ;
197
+ }
198
+
199
+ [ Theory ]
200
+ [ InlineData ( true , "<input />" ) ]
201
+ [ InlineData ( false , "" ) ]
202
+ [ InlineData ( null , "" ) ]
203
+ public void Process_AllowsAntiForgeryIfActionIsURL ( bool ? antiForgery , string expectedContent )
204
+ {
205
+ // Arrange
206
+ var expectedViewContext = CreateViewContext ( ) ;
207
+ var generator = new Mock < IHtmlGenerator > ( ) ;
208
+ generator . Setup ( mock => mock . GenerateAntiForgery ( It . IsAny < ViewContext > ( ) ) )
209
+ . Returns ( new TagBuilder ( "input" ) ) ;
210
+ var formTagHelper = new FormTagHelper
211
+ {
212
+ Action = "http://www.contoso.com" ,
213
+ AntiForgery = antiForgery ,
214
+ } ;
215
+ SetViewContextAndGenerator ( formTagHelper ,
216
+ expectedViewContext ,
217
+ generator . Object ) ;
218
+ var output = new TagHelperOutput ( "form" ,
219
+ attributes : new Dictionary < string , string > ( ) ,
220
+ content : string . Empty ) ;
221
+ var context = new TagHelperContext (
222
+ allAttributes : new Dictionary < string , object > ( )
223
+ {
224
+ { "aCTiON" , "http://www.contoso.com" }
225
+ } ) ;
226
+
227
+ // Act
228
+ formTagHelper . Process ( context , output ) ;
229
+
230
+ // Assert
231
+ Assert . Equal ( expectedContent , output . Content ) ;
232
+ }
233
+
234
+ [ Fact ]
235
+ public void Process_ThrowsIfActionIsUrlWithSpecifiedController ( )
236
+ {
237
+ // Arrange
238
+ var formTagHelper = new FormTagHelper
239
+ {
240
+ Action = "http://www.contoso.com" ,
241
+ Controller = "Home" ,
242
+ Method = "POST"
243
+ } ;
244
+ var expectedErrorMessage = "Cannot determine an Action for FormTagHelper. A FormTagHelper with a " +
245
+ "speicified URL based Action must not have a Controller attribute." ;
246
+
247
+ // Act & Assert
248
+ var ex = Assert . Throws < InvalidOperationException > ( ( ) =>
249
+ {
250
+ formTagHelper . Process ( context : null , output : null ) ;
251
+ } ) ;
252
+
253
+ Assert . Equal ( expectedErrorMessage , ex . Message ) ;
254
+ }
255
+
256
+ private ViewContext CreateViewContext ( )
257
+ {
258
+ var actionContext = new ActionContext (
259
+ new Mock < HttpContext > ( ) . Object ,
260
+ new RouteData ( ) ,
261
+ new ActionDescriptor ( ) ) ;
262
+
263
+ return new ViewContext (
264
+ actionContext ,
265
+ Mock . Of < IView > ( ) ,
266
+ new ViewDataDictionary (
267
+ new DataAnnotationsModelMetadataProvider ( ) ) ,
268
+ new StringWriter ( ) ) ;
269
+ }
270
+
271
+ private void SetViewContextAndGenerator ( ITagHelper tagHelper ,
272
+ ViewContext viewContext ,
273
+ IHtmlGenerator generator )
274
+ {
275
+ var tagHelperType = tagHelper . GetType ( ) ;
276
+
277
+ tagHelperType . GetProperty ( "ViewContext" , BindingFlags . NonPublic | BindingFlags . Instance )
278
+ . SetValue ( tagHelper , viewContext ) ;
279
+ tagHelperType . GetProperty ( "Generator" , BindingFlags . NonPublic | BindingFlags . Instance )
280
+ . SetValue ( tagHelper , generator ) ;
281
+ }
282
+ }
283
+ }
0 commit comments