Skip to content
This repository was archived by the owner on Dec 14, 2018. It is now read-only.

Commit 3a0403c

Browse files
author
NTaylorMullen
committed
Add tests for ValidationSummaryTagHelper.
- Also addressed code review comments.
1 parent a5939ae commit 3a0403c

File tree

2 files changed

+301
-11
lines changed

2 files changed

+301
-11
lines changed

src/Microsoft.AspNet.Mvc.TagHelpers/ValidationSummaryTagHelper.cs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
1515
[ContentBehavior(ContentBehavior.Append)]
1616
public class ValidationSummaryTagHelper : TagHelper
1717
{
18-
private static readonly bool DefaultModelErrorsOnlyBehavior = false;
18+
private static readonly bool DefaultModelErrorsOnly = false;
1919

2020
[Activate]
2121
private ViewContext ViewContext { get; set; }
@@ -26,17 +26,16 @@ public class ValidationSummaryTagHelper : TagHelper
2626
/// <summary>
2727
/// If <c>true</c> appends a validation summary.
2828
/// </summary>
29-
/// <remarks>If <see cref="ValidationModelErrorsOnly"/> is provided this is assumed <c>true</c> unless
30-
/// specified <c>false</c>.</remarks>
29+
/// <remarks>Defaults to <c>false</c> unless <see cref="ValidationModelErrorsOnly"/> is <c>true</c> in which
30+
/// case this also defaults to <c>true</c></remarks>
3131
[HtmlAttributeName("validation-summary")]
3232
public bool? ValidationSummary { get; set; }
3333

3434
/// <summary>
35-
/// If <c>true</c>, display model-level errors only; otherwise display all errors. Defaults behavior is
36-
/// <c>false</c>.
35+
/// If <c>true</c>, display model-level errors only; otherwise display all errors. Defaults to <c>false</c>.
3736
/// </summary>
3837
/// <remarks>
39-
/// If provided <see cref="ValidationSummary"/> is assumed <c>true</c> unless specified <c>false</c>.
38+
/// Defaults <see cref="ValidationSummary"/> to <c>true</c>.
4039
/// </remarks>
4140
[HtmlAttributeName("validation-model-errors-only")]
4241
public bool? ValidationModelErrorsOnly { get; set; }
@@ -55,17 +54,21 @@ public override void Process(TagHelperContext context, TagHelperOutput output)
5554
// the default behavior (false).
5655
var validationModelErrorsOnly = ValidationModelErrorsOnly.HasValue ?
5756
ValidationModelErrorsOnly.Value :
58-
DefaultModelErrorsOnlyBehavior;
57+
DefaultModelErrorsOnly;
5958

6059
var tagBuilder = Generator.GenerateValidationSummary(
6160
ViewContext,
6261
validationModelErrorsOnly,
63-
// We don't have access to the users message, it's implied by the content of the <div> tag.
64-
message: string.Empty,
65-
headerTag: output.TagName,
62+
message: null,
63+
headerTag: null,
6664
htmlAttributes: null);
6765

68-
output.Merge(tagBuilder);
66+
if (tagBuilder != null)
67+
{
68+
output.MergeAttributes(tagBuilder);
69+
70+
output.Content += tagBuilder.InnerHtml;
71+
}
6972
}
7073
}
7174
}
Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,287 @@
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 System.Threading.Tasks;
9+
using Microsoft.AspNet.Http;
10+
using Microsoft.AspNet.Mvc.ModelBinding;
11+
using Microsoft.AspNet.Mvc.Razor;
12+
using Microsoft.AspNet.Mvc.Rendering;
13+
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
14+
using Microsoft.AspNet.Routing;
15+
using Moq;
16+
using Xunit;
17+
18+
namespace Microsoft.AspNet.Mvc.TagHelpers
19+
{
20+
public class ValidationSummaryTagHelperTest
21+
{
22+
[Fact]
23+
public async Task ProcessAsync_GeneratesExpectedOutput()
24+
{
25+
// Arrange
26+
var metadataProvider = new DataAnnotationsModelMetadataProvider();
27+
var validationSummaryTagHelper = new ValidationSummaryTagHelper
28+
{
29+
ValidationSummary = true
30+
};
31+
32+
var tagHelperContext = new TagHelperContext(new Dictionary<string, object>());
33+
var output = new TagHelperOutput(
34+
"div",
35+
attributes: new Dictionary<string, string>
36+
{
37+
{ "class", "form-control" }
38+
},
39+
content: "Custom Content");
40+
41+
var htmlGenerator = new TestableHtmlGenerator(metadataProvider);
42+
Model model = null;
43+
var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider);
44+
var activator = new DefaultTagHelperActivator();
45+
activator.Activate(validationSummaryTagHelper, viewContext);
46+
47+
// Act
48+
await validationSummaryTagHelper.ProcessAsync(tagHelperContext, output);
49+
50+
// Assert
51+
Assert.Equal(2, output.Attributes.Count);
52+
var attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("class"));
53+
Assert.Equal("form-control validation-summary-valid", attribute.Value);
54+
attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("data-valmsg-summary"));
55+
Assert.Equal("true", attribute.Value);
56+
Assert.Equal("Custom Content<ul><li style=\"display:none\"></li>" + Environment.NewLine + "</ul>",
57+
output.Content);
58+
Assert.Equal("div", output.TagName);
59+
}
60+
61+
[Fact]
62+
public async Task ProcessAsync_CallsIntoGenerateValidationSummaryWithExpectedParameters()
63+
{
64+
// Arrange
65+
var validationSummaryTagHelper = new ValidationSummaryTagHelper
66+
{
67+
ValidationSummary = true,
68+
ValidationModelErrorsOnly = true
69+
};
70+
var output = new TagHelperOutput(
71+
"div",
72+
attributes: new Dictionary<string, string>(),
73+
content: "Content of validation summary");
74+
var expectedViewContext = CreateViewContext();
75+
var generator = new Mock<IHtmlGenerator>();
76+
var setup = generator.Setup(mock =>
77+
mock.GenerateValidationSummary(expectedViewContext, true, null, null, null));
78+
setup.Returns(new TagBuilder("div"));
79+
setup.Verifiable();
80+
81+
SetViewContextAndGenerator(validationSummaryTagHelper, expectedViewContext, generator.Object);
82+
83+
// Act & Assert
84+
await validationSummaryTagHelper.ProcessAsync(context: null, output: output);
85+
86+
generator.Verify();
87+
Assert.Equal("div", output.TagName);
88+
Assert.Empty(output.Attributes);
89+
Assert.Equal("Content of validation summary", output.Content);
90+
}
91+
92+
[Fact]
93+
public async Task ProcessAsync_MergesTagBuilderFromGenerateValidationSummary()
94+
{
95+
// Arrange
96+
var validationSummaryTagHelper = new ValidationSummaryTagHelper
97+
{
98+
ValidationSummary = true,
99+
ValidationModelErrorsOnly = true
100+
};
101+
var output = new TagHelperOutput(
102+
"div",
103+
attributes: new Dictionary<string, string>(),
104+
content: "Content of validation summary");
105+
var tagBuilder = new TagBuilder("span2")
106+
{
107+
InnerHtml = "New HTML"
108+
};
109+
110+
tagBuilder.Attributes.Add("data-foo", "bar");
111+
tagBuilder.Attributes.Add("data-hello", "world");
112+
113+
var expectedViewContext = CreateViewContext();
114+
var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
115+
var setup = generator.Setup(mock =>
116+
mock.GenerateValidationSummary(It.IsAny<ViewContext>(),
117+
It.IsAny<bool>(),
118+
It.IsAny<string>(),
119+
It.IsAny<string>(),
120+
It.IsAny<object>()));
121+
setup.Returns(tagBuilder);
122+
123+
SetViewContextAndGenerator(validationSummaryTagHelper, expectedViewContext, generator.Object);
124+
125+
// Act
126+
await validationSummaryTagHelper.ProcessAsync(context: null, output: output);
127+
128+
// Assert
129+
Assert.Equal(output.TagName, "div");
130+
Assert.Equal(2, output.Attributes.Count);
131+
var attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("data-foo"));
132+
Assert.Equal("bar", attribute.Value);
133+
attribute = Assert.Single(output.Attributes, kvp => kvp.Key.Equals("data-hello"));
134+
Assert.Equal("world", attribute.Value);
135+
Assert.Equal("Content of validation summaryNew HTML", output.Content);
136+
}
137+
138+
[Fact]
139+
public async Task ProcessAsync_DoesNothingIfNullValidationSummary()
140+
{
141+
// Arrange
142+
var validationSummaryTagHelper = new ValidationSummaryTagHelper();
143+
var output = new TagHelperOutput(
144+
"div",
145+
attributes: new Dictionary<string, string>(),
146+
content: "Content of validation message");
147+
148+
var expectedViewContext = CreateViewContext();
149+
var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
150+
151+
SetViewContextAndGenerator(validationSummaryTagHelper, expectedViewContext, generator.Object);
152+
153+
// Act
154+
await validationSummaryTagHelper.ProcessAsync(context: null, output: output);
155+
156+
// Assert
157+
Assert.Equal("div", output.TagName);
158+
Assert.Empty(output.Attributes);
159+
Assert.Equal("Content of validation message", output.Content);
160+
}
161+
162+
[Theory]
163+
[InlineData(true)]
164+
[InlineData(false)]
165+
public async Task ProcessAsync_GeneratesValidationSummaryIfModelErrorsNotNull(bool validationModelErrorsOnly)
166+
{
167+
// Arrange
168+
var validationSummaryTagHelper = new ValidationSummaryTagHelper
169+
{
170+
ValidationModelErrorsOnly = validationModelErrorsOnly
171+
};
172+
var output = new TagHelperOutput(
173+
"div",
174+
attributes: new Dictionary<string, string>(),
175+
content: "Content of validation message");
176+
var tagBuilder = new TagBuilder("span2")
177+
{
178+
InnerHtml = "New HTML"
179+
};
180+
181+
var expectedViewContext = CreateViewContext();
182+
var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
183+
var setup = generator.Setup(mock =>
184+
mock.GenerateValidationSummary(It.IsAny<ViewContext>(),
185+
It.IsAny<bool>(),
186+
It.IsAny<string>(),
187+
It.IsAny<string>(),
188+
It.IsAny<object>()));
189+
setup.Returns(tagBuilder);
190+
setup.Verifiable();
191+
192+
SetViewContextAndGenerator(validationSummaryTagHelper, expectedViewContext, generator.Object);
193+
194+
// Act
195+
await validationSummaryTagHelper.ProcessAsync(context: null, output: output);
196+
197+
// Assert
198+
Assert.Equal("div", output.TagName);
199+
Assert.Empty(output.Attributes);
200+
Assert.Equal("Content of validation messageNew HTML", output.Content);
201+
generator.Verify();
202+
}
203+
204+
[Theory]
205+
[InlineData(true)]
206+
[InlineData(false)]
207+
public async Task ProcessAsync_GeneratesValidationSummaryWhenProvided(bool validationSummary)
208+
{
209+
// Arrange
210+
var validationSummaryTagHelper = new ValidationSummaryTagHelper
211+
{
212+
ValidationSummary = validationSummary
213+
};
214+
var output = new TagHelperOutput(
215+
"div",
216+
attributes: new Dictionary<string, string>(),
217+
content: "Content of validation message");
218+
var tagBuilder = new TagBuilder("span2")
219+
{
220+
InnerHtml = "New HTML"
221+
};
222+
223+
var expectedViewContext = CreateViewContext();
224+
var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
225+
var setup = generator.Setup(mock =>
226+
mock.GenerateValidationSummary(It.IsAny<ViewContext>(),
227+
It.IsAny<bool>(),
228+
It.IsAny<string>(),
229+
It.IsAny<string>(),
230+
It.IsAny<object>()));
231+
setup.Returns(tagBuilder);
232+
setup.Verifiable();
233+
234+
SetViewContextAndGenerator(validationSummaryTagHelper, expectedViewContext, generator.Object);
235+
236+
// Act
237+
await validationSummaryTagHelper.ProcessAsync(context: null, output: output);
238+
239+
// Assert
240+
Assert.Equal("div", output.TagName);
241+
Assert.Empty(output.Attributes);
242+
243+
if (validationSummary)
244+
{
245+
Assert.Equal("Content of validation messageNew HTML", output.Content);
246+
generator.Verify();
247+
}
248+
else
249+
{
250+
Assert.Equal("Content of validation message", output.Content);
251+
}
252+
}
253+
254+
private static ViewContext CreateViewContext()
255+
{
256+
var actionContext = new ActionContext(
257+
new Mock<HttpContext>().Object,
258+
new RouteData(),
259+
new ActionDescriptor());
260+
261+
return new ViewContext(
262+
actionContext,
263+
Mock.Of<IView>(),
264+
new ViewDataDictionary(
265+
new DataAnnotationsModelMetadataProvider()),
266+
new StringWriter());
267+
}
268+
269+
private static void SetViewContextAndGenerator(ITagHelper tagHelper,
270+
ViewContext viewContext,
271+
IHtmlGenerator generator)
272+
{
273+
var tagHelperType = tagHelper.GetType();
274+
275+
tagHelperType.GetProperty("ViewContext", BindingFlags.NonPublic | BindingFlags.Instance)
276+
.SetValue(tagHelper, viewContext);
277+
tagHelperType.GetProperty("Generator", BindingFlags.NonPublic | BindingFlags.Instance)
278+
.SetValue(tagHelper, generator);
279+
}
280+
281+
282+
private class Model
283+
{
284+
public string Text { get; set; }
285+
}
286+
}
287+
}

0 commit comments

Comments
 (0)