Remove `WaitService`

- use `MvcTestFixture` instead of `TestHelper`
  - part of #3139
- continue to test e2e interaction of `FlushAsync()` with sections, partials, et cetera
- remove `FlushPointTest.FlushBeforeCallingLayout()`
  - `RazorPageTest.FlushAsync_ThrowsIfTheLayoutHasBeenSet()` unit test covers the scenario
This commit is contained in:
Doug Bunting 2015-10-27 09:58:22 -07:00
parent b4eb423e07
commit ff19702db5
13 changed files with 67 additions and 257 deletions

View File

@ -1,90 +1,58 @@
// Copyright (c) .NET Foundation. All rights reserved. // Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System; using System.Net.Http;
using System.IO;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNet.Builder;
using Microsoft.Extensions.DependencyInjection;
using RazorWebSite;
using Xunit; using Xunit;
namespace Microsoft.AspNet.Mvc.FunctionalTests namespace Microsoft.AspNet.Mvc.FunctionalTests
{ {
public class FlushPointTest public class FlushPointTest : IClassFixture<MvcTestFixture<RazorWebSite.Startup>>
{ {
private const string SiteName = nameof(RazorWebSite); public FlushPointTest(MvcTestFixture<RazorWebSite.Startup> fixture)
private readonly Action<IApplicationBuilder> _app = new Startup().Configure; {
private readonly Action<IServiceCollection> _configureServices = new Startup().ConfigureServices; Client = fixture.Client;
}
public HttpClient Client { get; }
[Fact] [Fact]
public async Task FlushPointsAreExecutedForPagesWithLayouts() public async Task FlushPointsAreExecutedForPagesWithLayouts()
{ {
var waitService = new WaitService(); var expected = @"<title>Page With Layout</title>
var server = TestHelper.CreateServer(_app, SiteName,
services => RenderBody content
{
_configureServices(services);
services.AddInstance(waitService); <span>Content that takes time to produce</span>
});
var client = server.CreateClient(); ";
// Act // Act
var stream = await client.GetStreamAsync("http://localhost/FlushPoint/PageWithLayout"); var body = await Client.GetStringAsync("http://localhost/FlushPoint/PageWithLayout");
// Assert - 1 // Assert
Assert.Equal(@"<title>Page With Layout</title>", GetTrimmedString(stream)); Assert.Equal(expected, body, ignoreLineEndingDifferences: true);
waitService.WaitForServer();
// Assert - 2
Assert.Equal(@"RenderBody content", GetTrimmedString(stream));
waitService.WaitForServer();
// Assert - 3
Assert.Equal(@"<span>Content that takes time to produce</span>",
GetTrimmedString(stream));
} }
[Fact] [Fact]
public async Task FlushPointsAreExecutedForPagesWithoutLayouts() public async Task FlushPointsAreExecutedForPagesWithoutLayouts()
{ {
var waitService = new WaitService(); var expected = @"Initial content
var server = TestHelper.CreateServer(_app, SiteName,
services => Secondary content
{
_configureServices(services); Inside partial
services.AddInstance(waitService);
}); After flush inside partial<form action=""/FlushPoint/PageWithoutLayout"" method=""post"">" +
var client = server.CreateClient(); @"<input id=""Name1"" name=""Name1"" type=""text"" value="""" />" +
@"<input id=""Name2"" name=""Name2"" type=""text"" value="""" /></form>";
// Act // Act
var stream = await client.GetStreamAsync("http://localhost/FlushPoint/PageWithoutLayout"); var body = await Client.GetStringAsync("http://localhost/FlushPoint/PageWithoutLayout");
// Assert - 1 // Assert
Assert.Equal("Initial content", GetTrimmedString(stream)); Assert.Equal(expected, body, ignoreLineEndingDifferences: true);
waitService.WaitForServer();
// Assert - 2
Assert.Equal("Secondary content", GetTrimmedString(stream));
waitService.WaitForServer();
// Assert - 3
Assert.Equal("Inside partial", GetTrimmedString(stream));
waitService.WaitForServer();
// Assert - 4
Assert.Equal(
@"After flush inside partial<form action=""/FlushPoint/PageWithoutLayout"" method=""post"">" +
@"<input id=""Name1"" name=""Name1"" type=""text"" value="""" />",
GetTrimmedString(stream),
ignoreLineEndingDifferences: true);
waitService.WaitForServer();
// Assert - 5
Assert.Equal(
@"<input id=""Name2"" name=""Name2"" type=""text"" value="""" /></form>",
GetTrimmedString(stream));
} }
[Theory] [Theory]
@ -92,112 +60,44 @@ namespace Microsoft.AspNet.Mvc.FunctionalTests
[InlineData("PageWithRenderSectionAsync", "FlushAsync invoked inside RenderSectionAsync")] [InlineData("PageWithRenderSectionAsync", "FlushAsync invoked inside RenderSectionAsync")]
public async Task FlushPointsAreExecutedForPagesWithComponentsPartialsAndSections(string action, string title) public async Task FlushPointsAreExecutedForPagesWithComponentsPartialsAndSections(string action, string title)
{ {
var waitService = new WaitService(); var expected = $@"<title>{ title }</title>
var server = TestHelper.CreateServer(_app, SiteName, RenderBody content
services =>
{
_configureServices(services);
services.AddInstance(waitService);
});
var client = server.CreateClient();
// Act
var stream = await client.GetStreamAsync("http://localhost/FlushPoint/" + action);
// Assert - 1 partial-content
Assert.Equal(
$@"<title>{ title }</title>
RenderBody content",
GetTrimmedString(stream),
ignoreLineEndingDifferences: true);
waitService.WaitForServer();
// Assert - 2
Assert.Equal(
@"partial-content
Value from TaskReturningString Value from TaskReturningString
<p>section-content</p>", <p>section-content</p>
GetTrimmedString(stream), component-content
ignoreLineEndingDifferences: true);
waitService.WaitForServer();
// Assert - 3
Assert.Equal(
@"component-content
<span>Content that takes time to produce</span> <span>Content that takes time to produce</span>
More content from layout", More content from layout
GetTrimmedString(stream), ";
ignoreLineEndingDifferences: true);
// Act
var body = await Client.GetStringAsync("http://localhost/FlushPoint/" + action);
// Assert
Assert.Equal(expected, body, ignoreLineEndingDifferences: true);
} }
[Fact] [Fact]
public async Task FlushPointsNestedLayout() public async Task FlushPointsNestedLayout()
{ {
// Arrange // Arrange
var waitService = new WaitService(); var expected = @"Inside Nested Layout
var server = TestHelper.CreateServer(_app, SiteName, <title>Nested Page With Layout</title>
services =>
{
_configureServices(services);
services.AddInstance(waitService); <span>Nested content that takes time to produce</span>
}); ";
var client = server.CreateClient();
// Act // Act
var stream = await client.GetStreamAsync("http://localhost/FlushPoint/PageWithNestedLayout"); var body = await Client.GetStringAsync("http://localhost/FlushPoint/PageWithNestedLayout");
// Assert - 1 // Assert
Assert.Equal( Assert.Equal(expected, body, ignoreLineEndingDifferences: true);
@"Inside Nested Layout
<title>Nested Page With Layout</title>",
GetTrimmedString(stream),
ignoreLineEndingDifferences: true);
waitService.WaitForServer();
// Assert - 2
Assert.Equal("<span>Nested content that takes time to produce</span>", GetTrimmedString(stream));
}
[Fact]
public async Task FlushBeforeCallingLayout()
{
var waitService = new WaitService();
var server = TestHelper.CreateServer(_app, SiteName,
services =>
{
_configureServices(services);
services.AddInstance(waitService);
});
var client = server.CreateClient();
var expectedMessage = "Layout page '/Views/FlushPoint/PageWithFlushBeforeLayout.cshtml'" +
" cannot be rendered after 'FlushAsync' has been invoked.";
// Act
var stream = await client.GetStreamAsync("http://localhost/FlushPoint/PageWithFlushBeforeLayout");
// Assert - 1
Assert.Equal("Initial content", GetTrimmedString(stream));
waitService.WaitForServer();
// Assert - 2
try
{
GetTrimmedString(stream);
}
catch (Exception ex)
{
Assert.Equal(expectedMessage, ex.InnerException.Message);
}
}
private string GetTrimmedString(Stream stream)
{
var buffer = new byte[1024];
var count = stream.Read(buffer, 0, buffer.Length);
return Encoding.UTF8.GetString(buffer, 0, count).Trim();
} }
} }
} }

View File

@ -1,44 +0,0 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Threading;
namespace RazorWebSite
{
public class WaitService
{
private static readonly TimeSpan _waitTime = TimeSpan.FromSeconds(60);
private readonly ManualResetEventSlim _serverResetEvent = new ManualResetEventSlim();
private readonly ManualResetEventSlim _clientResetEvent = new ManualResetEventSlim();
public void NotifyClient()
{
_clientResetEvent.Set();
}
public void WaitForClient()
{
_clientResetEvent.Set();
if (!_serverResetEvent.Wait(_waitTime))
{
throw new InvalidOperationException("Timeout exceeded");
}
_serverResetEvent.Reset();
}
public void WaitForServer()
{
_serverResetEvent.Set();
if (!_clientResetEvent.Wait(_waitTime))
{
throw new InvalidOperationException("Timeout exceeded");
}
_clientResetEvent.Reset();
}
}
}

View File

@ -1,9 +1,5 @@
@inject WaitService WaitService Initial content
Initial content
@await FlushAsync() @await FlushAsync()
@{
WaitService.WaitForClient();
}
@{ @{
Layout = "/Views/Shared/_LayoutWithFlush.cshtml"; Layout = "/Views/Shared/_LayoutWithFlush.cshtml";

View File

@ -1,5 +1,4 @@
@inject WaitService WaitService @{
@{
Layout = "/Views/Shared/_LayoutWithFlush.cshtml"; Layout = "/Views/Shared/_LayoutWithFlush.cshtml";
ViewBag.Title = "Page With Layout"; ViewBag.Title = "Page With Layout";
} }
@ -8,7 +7,6 @@ RenderBody content
{ {
@{ @{
await FlushAsync(); await FlushAsync();
WaitService.WaitForClient();
} }
<span>Content that takes time to produce</span> <span>Content that takes time to produce</span>
} }

View File

@ -1,5 +1,4 @@
@inject WaitService WaitService @{
@{
Layout = "/Views/Shared/_NestedLayoutWithFlush.cshtml"; Layout = "/Views/Shared/_NestedLayoutWithFlush.cshtml";
ViewBag.Title = "Nested Page With Layout"; ViewBag.Title = "Nested Page With Layout";
} }

View File

@ -1,5 +1,4 @@
@inject WaitService WaitService @inject TaskReturningService TaskReturningService
@inject TaskReturningService TaskReturningService
@{ @{
Layout = "/Views/Shared/_LayoutWithPartialAndFlush.cshtml"; Layout = "/Views/Shared/_LayoutWithPartialAndFlush.cshtml";
@ -12,7 +11,6 @@ RenderBody content
<p>section-content</p> <p>section-content</p>
@{ @{
await FlushAsync(); await FlushAsync();
WaitService.WaitForClient();
} }
@await Component.InvokeAsync("ComponentThatSetsTitle") @await Component.InvokeAsync("ComponentThatSetsTitle")
<span>Content that takes time to produce</span> <span>Content that takes time to produce</span>

View File

@ -1,5 +1,4 @@
@inject WaitService WaitService @inject TaskReturningService TaskReturningService
@inject TaskReturningService TaskReturningService
@{ @{
Layout = "/Views/Shared/_LayoutWithRenderSectionAsync.cshtml"; Layout = "/Views/Shared/_LayoutWithRenderSectionAsync.cshtml";
@ -12,7 +11,6 @@ RenderBody content
<p>section-content</p> <p>section-content</p>
@{ @{
await FlushAsync(); await FlushAsync();
WaitService.WaitForClient();
} }
@await Component.InvokeAsync("ComponentThatSetsTitle") @await Component.InvokeAsync("ComponentThatSetsTitle")
<span>Content that takes time to produce</span> <span>Content that takes time to produce</span>

View File

@ -1,14 +1,7 @@
@inject WaitService WaitService Initial content
Initial content
@await FlushAsync() @await FlushAsync()
@{
WaitService.WaitForClient();
}
Secondary content Secondary content
@await FlushAsync() @await FlushAsync()
@{
WaitService.WaitForClient();
}
@{ @{
await Html.RenderPartialAsync("_PartialWithFlush"); await Html.RenderPartialAsync("_PartialWithFlush");
} }
@ -16,9 +9,5 @@ Secondary content
{ {
@Html.TextBox("Name1") @Html.TextBox("Name1")
@await FlushAsync() @await FlushAsync()
WaitService.WaitForClient();
@Html.TextBox("Name2") @Html.TextBox("Name2")
} }
@{
WaitService.NotifyClient();
}

View File

@ -1,11 +1,4 @@
@inject WaitService WaitService <title>@ViewBag.Title</title>
<title>@ViewBag.Title</title>
@await FlushAsync() @await FlushAsync()
@{
WaitService.WaitForClient();
}
@RenderBody() @RenderBody()
@await RenderSectionAsync("content") @await RenderSectionAsync("content")
@{
WaitService.NotifyClient();
}

View File

@ -1,13 +1,6 @@
@inject WaitService WaitService <title>@ViewBag.Title</title>
<title>@ViewBag.Title</title>
@RenderBody() @RenderBody()
@await FlushAsync() @await FlushAsync()
@{
WaitService.WaitForClient();
}
@await Html.PartialAsync("_PartialThatSetsTitle") @await Html.PartialAsync("_PartialThatSetsTitle")
@await RenderSectionAsync("content") @RenderSection("content")
More content from layout More content from layout
@{
WaitService.NotifyClient();
}

View File

@ -1,10 +1,6 @@
@inject WaitService WaitService <title>@ViewBag.Title</title>
<title>@ViewBag.Title</title>
@RenderBody() @RenderBody()
@{ @await FlushAsync()
await FlushAsync();
WaitService.WaitForClient();
}
@await Html.PartialAsync("_PartialThatSetsTitle") @await Html.PartialAsync("_PartialThatSetsTitle")
@await RenderSectionAsync("content") @await RenderSectionAsync("content")
More content from layout More content from layout

View File

@ -1,5 +1,4 @@
@inject WaitService WaitService @{
@{
Layout = "/Views/Shared/_LayoutWithRenderSectionOnly.cshtml"; Layout = "/Views/Shared/_LayoutWithRenderSectionOnly.cshtml";
ViewBag.Title = "Page With Layout"; ViewBag.Title = "Page With Layout";
} }
@ -9,7 +8,6 @@ Inside Nested Layout
{ {
@{ @{
await FlushAsync(); await FlushAsync();
WaitService.WaitForClient();
} }
<span>Nested content that takes time to produce</span> <span>Nested content that takes time to produce</span>
} }

View File

@ -1,7 +1,3 @@
@inject WaitService WaitService Inside partial
Inside partial
@await FlushAsync() @await FlushAsync()
@{
WaitService.WaitForClient();
}
After flush inside partial After flush inside partial