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:
parent
b4eb423e07
commit
ff19702db5
|
|
@ -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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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";
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
}
|
}
|
||||||
|
|
@ -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";
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
@ -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();
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
Loading…
Reference in New Issue