Fix tests and changed TagHelper activates property accessors.

- Changed TagHelper property accessors from private to protected internal.
- Changed throw tests to be shorter.
- Changed reflection setting to now use the internal accessibility of the TagHelpers
- Removed activator to just use internal accessibility of TagHelpers.
- Changed new StringWriter() instances where we didn't need the StringWriter to be TextWriter.Null
This commit is contained in:
N. Taylor Mullen 2014-10-16 16:52:56 -07:00 committed by NTaylorMullen
parent f8b0249918
commit f8f08f0903
11 changed files with 64 additions and 127 deletions

View File

@ -18,8 +18,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
private const string RouteAttributePrefix = "route-";
private const string Href = "href";
// Protected to ensure subclasses are correctly activated. Internal for ease of use when testing.
[Activate]
private IHtmlGenerator Generator { get; set; }
protected internal IHtmlGenerator Generator { get; set; }
/// <summary>
/// The name of the action method.

View File

@ -18,11 +18,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{
private const string RouteAttributePrefix = "route-";
// Protected to ensure subclasses are correctly activated. Internal for ease of use when testing.
[Activate]
private ViewContext ViewContext { get; set; }
protected internal ViewContext ViewContext { get; set; }
// Protected to ensure subclasses are correctly activated. Internal for ease of use when testing.
[Activate]
private IHtmlGenerator Generator { get; set; }
protected internal IHtmlGenerator Generator { get; set; }
/// <summary>
/// The name of the action method.

View File

@ -13,11 +13,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
[ContentBehavior(ContentBehavior.Replace)]
public class TextAreaTagHelper : TagHelper
{
// Protected to ensure subclasses are correctly activated. Internal for ease of use when testing.
[Activate]
private IHtmlGenerator Generator { get; set; }
protected internal IHtmlGenerator Generator { get; set; }
// Protected to ensure subclasses are correctly activated. Internal for ease of use when testing.
[Activate]
private ViewContext ViewContext { get; set; }
protected internal ViewContext ViewContext { get; set; }
/// <summary>
/// An expression to be evaluated against the current model.

View File

@ -14,11 +14,13 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
[ContentBehavior(ContentBehavior.Modify)]
public class ValidationMessageTagHelper : TagHelper
{
// Protected to ensure subclasses are correctly activated. Internal for ease of use when testing.
[Activate]
private ViewContext ViewContext { get; set; }
protected internal ViewContext ViewContext { get; set; }
// Protected to ensure subclasses are correctly activated. Internal for ease of use when testing.
[Activate]
private IHtmlGenerator Generator { get; set; }
protected internal IHtmlGenerator Generator { get; set; }
/// <summary>
/// Name to be validated on the current model.

View File

@ -3,10 +3,8 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Razor;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Moq;
@ -65,9 +63,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var viewContext = TestableHtmlGenerator.GetViewContext(model: null,
htmlGenerator: htmlGenerator,
metadataProvider: metadataProvider);
var activator = new DefaultTagHelperActivator();
activator.Activate(anchorTagHelper, viewContext);
anchorTagHelper.Generator = htmlGenerator;
// Act
await anchorTagHelper.ProcessAsync(tagHelperContext, output);
@ -106,8 +102,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
string.Empty, "Default", "http", "contoso.com", "hello=world", null, null))
.Returns(new TagBuilder("a"))
.Verifiable();
SetGenerator(anchorTagHelper, generator.Object);
anchorTagHelper.Generator = generator.Object;
// Act & Assert
await anchorTagHelper.ProcessAsync(context, output);
@ -142,8 +137,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
string.Empty, "Index", "Home", "http", "contoso.com", "hello=world", null, null))
.Returns(new TagBuilder("a"))
.Verifiable();
SetGenerator(anchorTagHelper, generator.Object);
anchorTagHelper.Generator = generator.Object;
// Act & Assert
await anchorTagHelper.ProcessAsync(context, output);
@ -188,10 +182,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Act & Assert
var ex = await Assert.ThrowsAsync<InvalidOperationException>(
async () =>
{
await anchorTagHelper.ProcessAsync(context: null, output: output);
});
() => anchorTagHelper.ProcessAsync(context: null, output: output));
Assert.Equal(expectedErrorMessage, ex.Message);
}
@ -216,20 +207,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
// Act & Assert
var ex = await Assert.ThrowsAsync<InvalidOperationException>(
async () =>
{
await anchorTagHelper.ProcessAsync(context: null, output: output);
});
() => anchorTagHelper.ProcessAsync(context: null, output: output));
Assert.Equal(expectedErrorMessage, ex.Message);
}
private void SetGenerator(ITagHelper tagHelper, IHtmlGenerator generator)
{
var tagHelperType = tagHelper.GetType();
tagHelperType.GetProperty("Generator", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(tagHelper, generator);
}
}
}

View File

@ -4,12 +4,10 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Razor;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.PipelineCore;
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.AspNet.Routing;
using Moq;
@ -65,8 +63,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
metadataProvider: metadataProvider);
var expectedContent = "Something" + htmlGenerator.GenerateAntiForgery(viewContext)
.ToString(TagRenderMode.SelfClosing);
var activator = new DefaultTagHelperActivator();
activator.Activate(formTagHelper, viewContext);
formTagHelper.ViewContext = viewContext;
formTagHelper.Generator = htmlGenerator;
// Act
await formTagHelper.ProcessAsync(tagHelperContext, output);
@ -115,8 +113,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
generator.Setup(mock => mock.GenerateAntiForgery(viewContext))
.Returns(new TagBuilder("input"));
SetViewContextAndGenerator(formTagHelper, viewContext, generator.Object);
formTagHelper.ViewContext = viewContext;
formTagHelper.Generator = generator.Object;
// Act
await formTagHelper.ProcessAsync(context, output);
@ -175,8 +173,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
})
.Returns(new TagBuilder("form"))
.Verifiable();
SetViewContextAndGenerator(formTagHelper, testViewContext, generator.Object);
formTagHelper.ViewContext = testViewContext;
formTagHelper.Generator = generator.Object;
// Act & Assert
await formTagHelper.ProcessAsync(context, output);
@ -211,10 +209,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
.Setup(mock => mock.GenerateForm(viewContext, "Index", "Home", null, "POST", null))
.Returns(new TagBuilder("form"))
.Verifiable();
SetViewContextAndGenerator(formTagHelper,
viewContext,
generator.Object);
formTagHelper.ViewContext = viewContext;
formTagHelper.Generator = generator.Object;
// Act & Assert
await formTagHelper.ProcessAsync(context, output);
@ -273,9 +269,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Action = "http://www.contoso.com",
AntiForgery = antiForgery,
};
SetViewContextAndGenerator(formTagHelper,
viewContext,
generator.Object);
formTagHelper.ViewContext = viewContext;
formTagHelper.Generator = generator.Object;
var output = new TagHelperOutput("form",
attributes: new Dictionary<string, string>(),
content: string.Empty);
@ -313,10 +309,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
content: string.Empty);
// Act & Assert
var ex = await Assert.ThrowsAsync<InvalidOperationException>(async () =>
{
await formTagHelper.ProcessAsync(context: null, output: tagHelperOutput);
});
var ex = await Assert.ThrowsAsync<InvalidOperationException>(
() => formTagHelper.ProcessAsync(context: null, output: tagHelperOutput));
Assert.Equal(expectedErrorMessage, ex.Message);
}
@ -341,10 +335,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
content: string.Empty);
// Act & Assert
var ex = await Assert.ThrowsAsync<InvalidOperationException>(async () =>
{
await formTagHelper.ProcessAsync(context: null, output: tagHelperOutput);
});
var ex = await Assert.ThrowsAsync<InvalidOperationException>(
() => formTagHelper.ProcessAsync(context: null, output: tagHelperOutput));
Assert.Equal(expectedErrorMessage, ex.Message);
}
@ -352,7 +344,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
private static ViewContext CreateViewContext()
{
var actionContext = new ActionContext(
new Mock<HttpContext>().Object,
new DefaultHttpContext(),
new RouteData(),
new ActionDescriptor());
@ -361,19 +353,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Mock.Of<IView>(),
new ViewDataDictionary(
new DataAnnotationsModelMetadataProvider()),
new StringWriter());
}
private static void SetViewContextAndGenerator(ITagHelper tagHelper,
ViewContext viewContext,
IHtmlGenerator generator)
{
var tagHelperType = tagHelper.GetType();
tagHelperType.GetProperty("ViewContext", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(tagHelper, viewContext);
tagHelperType.GetProperty("Generator", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(tagHelper, generator);
TextWriter.Null);
}
}
}

View File

@ -5,7 +5,6 @@ using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Razor;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Xunit;
@ -160,8 +159,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var htmlGenerator = new TestableHtmlGenerator(metadataProvider);
Model model = null;
var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider);
var activator = new DefaultTagHelperActivator();
activator.Activate(tagHelper, viewContext);
tagHelper.ViewContext = viewContext;
tagHelper.Generator = htmlGenerator;
// Act
await tagHelper.ProcessAsync(tagHelperContext, output);

View File

@ -4,9 +4,9 @@
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.PipelineCore;
using Microsoft.AspNet.Routing;
using Microsoft.AspNet.Security.DataProtection;
using Microsoft.Framework.OptionsModel;
@ -50,22 +50,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
IHtmlGenerator htmlGenerator,
IModelMetadataProvider metadataProvider)
{
var serviceProvider = new Mock<IServiceProvider>();
serviceProvider
.Setup(provider => provider.GetService(typeof(IHtmlGenerator)))
.Returns(htmlGenerator);
var httpContext = new Mock<HttpContext>();
httpContext
.Setup(context => context.RequestServices)
.Returns(serviceProvider.Object);
var actionContext = new ActionContext(httpContext.Object, new RouteData(), new ActionDescriptor());
var actionContext = new ActionContext(new DefaultHttpContext(), new RouteData(), new ActionDescriptor());
var viewData = new ViewDataDictionary(metadataProvider)
{
Model = model,
};
var viewContext = new ViewContext(actionContext, Mock.Of<IView>(), viewData, new StringWriter());
var viewContext = new ViewContext(actionContext, Mock.Of<IView>(), viewData, TextWriter.Null);
return viewContext;
}

View File

@ -5,7 +5,6 @@ using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Razor;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Xunit;
@ -57,8 +56,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
{ modelWithText, typeof(NestedModel), () => modelWithText.NestedModel.Text, "NestedModel.Text",
Environment.NewLine + "inner text" },
// Top-level indexing does not work end-to-end due to code generation issue #1345.
// TODO: Remove above comment when #1345 is fixed.
// Top-level indexing does not work end-to-end due to code generation issue #1345.
// TODO: Remove above comment when #1345 is fixed.
{ models, typeof(Model), () => models[0].Text, "[0].Text",
Environment.NewLine },
{ models, typeof(Model), () => models[1].Text, "[1].Text",
@ -119,8 +118,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
}
};
var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider);
var activator = new DefaultTagHelperActivator();
activator.Activate(tagHelper, viewContext);
tagHelper.ViewContext = viewContext;
tagHelper.Generator = htmlGenerator;
// Act
await tagHelper.ProcessAsync(tagHelperContext, output);
@ -166,8 +165,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
};
Model model = null;
var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider);
var activator = new DefaultTagHelperActivator();
activator.Activate(tagHelper, viewContext);
tagHelper.ViewContext = viewContext;
tagHelper.Generator = htmlGenerator;
// Act
await tagHelper.ProcessAsync(tagHelperContext, output);

View File

@ -3,12 +3,10 @@
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Razor;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.PipelineCore;
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
using Microsoft.AspNet.Routing;
using Moq;
@ -46,9 +44,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var viewContext = TestableHtmlGenerator.GetViewContext(model: null,
htmlGenerator: htmlGenerator,
metadataProvider: metadataProvider);
var activator = new DefaultTagHelperActivator();
activator.Activate(validationMessageTagHelper, viewContext);
validationMessageTagHelper.ViewContext = viewContext;
validationMessageTagHelper.Generator = htmlGenerator;
// Act
await validationMessageTagHelper.ProcessAsync(tagHelperContext, output);
@ -82,12 +79,12 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
var expectedViewContext = CreateViewContext();
var generator = new Mock<IHtmlGenerator>();
generator
.Setup(mock =>
.Setup(mock =>
mock.GenerateValidationMessage(expectedViewContext, "Hello", null, null, null))
.Returns(new TagBuilder("span"))
.Verifiable();
SetViewContextAndGenerator(validationMessageTagHelper, expectedViewContext, generator.Object);
validationMessageTagHelper.Generator = generator.Object;
validationMessageTagHelper.ViewContext = expectedViewContext;
// Act & Assert
await validationMessageTagHelper.ProcessAsync(context: null, output: output);
@ -120,7 +117,6 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
tagBuilder.Attributes.Add("data-foo", "bar");
tagBuilder.Attributes.Add("data-hello", "world");
var expectedViewContext = CreateViewContext();
var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
var setup = generator
.Setup(mock => mock.GenerateValidationMessage(
@ -130,8 +126,9 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
It.IsAny<string>(),
It.IsAny<object>()))
.Returns(tagBuilder);
SetViewContextAndGenerator(validationMessageTagHelper, expectedViewContext, generator.Object);
var viewContext = CreateViewContext();
validationMessageTagHelper.ViewContext = viewContext;
validationMessageTagHelper.Generator = generator.Object;
// Act
await validationMessageTagHelper.ProcessAsync(context: null, output: output);
@ -155,10 +152,10 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
"span",
attributes: new Dictionary<string, string>(),
content: "Content of validation message");
var expectedViewContext = CreateViewContext();
var viewContext = CreateViewContext();
var generator = new Mock<IHtmlGenerator>(MockBehavior.Strict);
SetViewContextAndGenerator(validationMessageTagHelper, expectedViewContext, generator.Object);
validationMessageTagHelper.ViewContext = viewContext;
validationMessageTagHelper.Generator = generator.Object;
// Act
await validationMessageTagHelper.ProcessAsync(context: null, output: output);
@ -184,7 +181,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
private static ViewContext CreateViewContext()
{
var actionContext = new ActionContext(
new Mock<HttpContext>().Object,
new DefaultHttpContext(),
new RouteData(),
new ActionDescriptor());
@ -193,19 +190,7 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
Mock.Of<IView>(),
new ViewDataDictionary(
new DataAnnotationsModelMetadataProvider()),
new StringWriter());
}
private static void SetViewContextAndGenerator(ITagHelper tagHelper,
ViewContext viewContext,
IHtmlGenerator generator)
{
var tagHelperType = tagHelper.GetType();
tagHelperType.GetProperty("ViewContext", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(tagHelper, viewContext);
tagHelperType.GetProperty("Generator", BindingFlags.NonPublic | BindingFlags.Instance)
.SetValue(tagHelper, generator);
TextWriter.Null);
}
}
}

View File

@ -4,11 +4,8 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNet.Http;
using Microsoft.AspNet.Mvc.ModelBinding;
using Microsoft.AspNet.Mvc.Razor;
using Microsoft.AspNet.Mvc.Rendering;
using Microsoft.AspNet.PipelineCore;
using Microsoft.AspNet.Razor.Runtime.TagHelpers;
@ -259,8 +256,8 @@ namespace Microsoft.AspNet.Mvc.TagHelpers
"are 'All', 'ModelOnly' and 'None'.";
// Act
var ex = await Assert.ThrowsAsync<InvalidOperationException>(() =>
validationSummaryTagHelper.ProcessAsync(context: null, output: output));
var ex = await Assert.ThrowsAsync<InvalidOperationException>(
() => validationSummaryTagHelper.ProcessAsync(context: null, output: output));
// Assert
Assert.Equal(expectedMessage, ex.Message);