From 7530ad9a26a8c38583b147030efa14fa177238fd Mon Sep 17 00:00:00 2001 From: Steve Sanderson Date: Mon, 15 Oct 2018 14:26:55 +0100 Subject: [PATCH] E2E tests for cascading parameters generally --- .../ServerExecutionTests/TestSubclasses.cs | 8 ++ .../Tests/CascadingValueTest.cs | 86 +++++++++++++++++++ .../CascadingValueIntermediary.cshtml | 9 ++ .../CascadingValueReceiveByName.cshtml | 16 ++++ .../CascadingValueReceiveByType.cshtml | 8 ++ ...scadingValueReceiveFixedByInterface.cshtml | 21 +++++ .../CascadingValueSupplier.cshtml | 33 +++++++ .../CascadingValueTest/CascadingValueTypes.cs | 20 +++++ test/testapps/BasicTestApp/Index.cshtml | 1 + 9 files changed, 202 insertions(+) create mode 100644 test/Microsoft.AspNetCore.Blazor.E2ETest/Tests/CascadingValueTest.cs create mode 100644 test/testapps/BasicTestApp/CascadingValueTest/CascadingValueIntermediary.cshtml create mode 100644 test/testapps/BasicTestApp/CascadingValueTest/CascadingValueReceiveByName.cshtml create mode 100644 test/testapps/BasicTestApp/CascadingValueTest/CascadingValueReceiveByType.cshtml create mode 100644 test/testapps/BasicTestApp/CascadingValueTest/CascadingValueReceiveFixedByInterface.cshtml create mode 100644 test/testapps/BasicTestApp/CascadingValueTest/CascadingValueSupplier.cshtml create mode 100644 test/testapps/BasicTestApp/CascadingValueTest/CascadingValueTypes.cs diff --git a/test/Microsoft.AspNetCore.Blazor.E2ETest/ServerExecutionTests/TestSubclasses.cs b/test/Microsoft.AspNetCore.Blazor.E2ETest/ServerExecutionTests/TestSubclasses.cs index 0cd17d7704..00afaa67b0 100644 --- a/test/Microsoft.AspNetCore.Blazor.E2ETest/ServerExecutionTests/TestSubclasses.cs +++ b/test/Microsoft.AspNetCore.Blazor.E2ETest/ServerExecutionTests/TestSubclasses.cs @@ -56,4 +56,12 @@ namespace Microsoft.AspNetCore.Blazor.E2ETest.ServerExecutionTests { } } + + public class ServerCascadingValueTest : CascadingValueTest + { + public ServerCascadingValueTest(BrowserFixture browserFixture, ToggleExecutionModeServerFixture serverFixture, ITestOutputHelper output) + : base(browserFixture, serverFixture.WithServerExecution(), output) + { + } + } } diff --git a/test/Microsoft.AspNetCore.Blazor.E2ETest/Tests/CascadingValueTest.cs b/test/Microsoft.AspNetCore.Blazor.E2ETest/Tests/CascadingValueTest.cs new file mode 100644 index 0000000000..50c455627a --- /dev/null +++ b/test/Microsoft.AspNetCore.Blazor.E2ETest/Tests/CascadingValueTest.cs @@ -0,0 +1,86 @@ +// 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 BasicTestApp; +using Microsoft.AspNetCore.Blazor.E2ETest.Infrastructure; +using Microsoft.AspNetCore.Blazor.E2ETest.Infrastructure.ServerFixtures; +using OpenQA.Selenium; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.AspNetCore.Blazor.E2ETest.Tests +{ + public class CascadingValueTest : BasicTestAppTestBase + { + public CascadingValueTest( + BrowserFixture browserFixture, + ToggleExecutionModeServerFixture serverFixture, + ITestOutputHelper output) + : base(browserFixture, serverFixture, output) + { + Navigate(ServerPathBase, noReload: !serverFixture.UsingAspNetHost); + MountTestComponent(); + } + + [Fact] + public void CanUpdateValuesMatchedByType() + { + var currentCount = Browser.FindElement(By.Id("current-count")); + var incrementButton = Browser.FindElement(By.Id("increment-count")); + + // We have the correct initial value + WaitAssert.Equal("100", () => currentCount.Text); + + // Updates are propagated + incrementButton.Click(); + WaitAssert.Equal("101", () => currentCount.Text); + incrementButton.Click(); + WaitAssert.Equal("102", () => currentCount.Text); + + // Didn't re-render unrelated descendants + Assert.Equal("1", Browser.FindElement(By.Id("receive-by-interface-num-renders")).Text); + } + + [Fact] + public void CanUpdateValuesMatchedByName() + { + var currentFlag1Value = Browser.FindElement(By.Id("flag-1")); + var currentFlag2Value = Browser.FindElement(By.Id("flag-2")); + + WaitAssert.Equal("False", () => currentFlag1Value.Text); + WaitAssert.Equal("False", () => currentFlag2Value.Text); + + // Observe that the correct cascading parameter updates + Browser.FindElement(By.Id("toggle-flag-1")).Click(); + WaitAssert.Equal("True", () => currentFlag1Value.Text); + WaitAssert.Equal("False", () => currentFlag2Value.Text); + Browser.FindElement(By.Id("toggle-flag-2")).Click(); + WaitAssert.Equal("True", () => currentFlag1Value.Text); + WaitAssert.Equal("True", () => currentFlag2Value.Text); + + // Didn't re-render unrelated descendants + Assert.Equal("1", Browser.FindElement(By.Id("receive-by-interface-num-renders")).Text); + } + + [Fact] + public void CanUpdateFixedValuesMatchedByInterface() + { + var currentCount = Browser.FindElement(By.Id("current-count")); + var decrementButton = Browser.FindElement(By.Id("decrement-count")); + + // We have the correct initial value + WaitAssert.Equal("100", () => currentCount.Text); + + // Updates are propagated + decrementButton.Click(); + WaitAssert.Equal("99", () => currentCount.Text); + decrementButton.Click(); + WaitAssert.Equal("98", () => currentCount.Text); + + // Renders the descendant the same number of times we triggered + // events on it, because we always re-render components after they + // have an event + Assert.Equal("3", Browser.FindElement(By.Id("receive-by-interface-num-renders")).Text); + } + } +} diff --git a/test/testapps/BasicTestApp/CascadingValueTest/CascadingValueIntermediary.cshtml b/test/testapps/BasicTestApp/CascadingValueTest/CascadingValueIntermediary.cshtml new file mode 100644 index 0000000000..b6db3ef1c3 --- /dev/null +++ b/test/testapps/BasicTestApp/CascadingValueTest/CascadingValueIntermediary.cshtml @@ -0,0 +1,9 @@ +@* + The only purpose of this component is to validate that cascaded value updates + can pass through entirely unrelated components that wouldn't normally rerender + their children when they themselves are being rerendered. +*@ + + + + diff --git a/test/testapps/BasicTestApp/CascadingValueTest/CascadingValueReceiveByName.cshtml b/test/testapps/BasicTestApp/CascadingValueTest/CascadingValueReceiveByName.cshtml new file mode 100644 index 0000000000..a0d14e571a --- /dev/null +++ b/test/testapps/BasicTestApp/CascadingValueTest/CascadingValueReceiveByName.cshtml @@ -0,0 +1,16 @@ +@* + This component is to show that we can differentiate cascaded values + by name if they are of the same type. +*@ + +

+ Flag 1: @MyFlag1 +

+

+ Flag 2: @MyFlag2 +

+ +@functions { + [CascadingParameter(Name = "TestFlag1")] bool MyFlag1 { get; set; } + [CascadingParameter(Name = "TestFlag2")] bool MyFlag2 { get; set; } +} diff --git a/test/testapps/BasicTestApp/CascadingValueTest/CascadingValueReceiveByType.cshtml b/test/testapps/BasicTestApp/CascadingValueTest/CascadingValueReceiveByType.cshtml new file mode 100644 index 0000000000..a1731d14d5 --- /dev/null +++ b/test/testapps/BasicTestApp/CascadingValueTest/CascadingValueReceiveByType.cshtml @@ -0,0 +1,8 @@ +

+ Current count: + @CurrentCounter.NumClicks +

+ +@functions { + [CascadingParameter] CounterDTO CurrentCounter { get; set; } +} diff --git a/test/testapps/BasicTestApp/CascadingValueTest/CascadingValueReceiveFixedByInterface.cshtml b/test/testapps/BasicTestApp/CascadingValueTest/CascadingValueReceiveFixedByInterface.cshtml new file mode 100644 index 0000000000..3878c21e66 --- /dev/null +++ b/test/testapps/BasicTestApp/CascadingValueTest/CascadingValueReceiveFixedByInterface.cshtml @@ -0,0 +1,21 @@ +@* + This component is to show that: + + 1. We can match a cascading parameter based on interface + 2. Since the supplied value is fixed (see CascadingValueSupplier.cshtml), + ancestor renders don't trigger descendant renders even though the + supplied value type is mutable. +*@ + +@{ numRenders++; } +

+ @(nameof(CascadingValueReceiveFixedByInterface)) render count: + @numRenders + +

+ +@functions { + int numRenders = 0; + + [CascadingParameter] ICanDecrement Ancestor { get; set; } +} diff --git a/test/testapps/BasicTestApp/CascadingValueTest/CascadingValueSupplier.cshtml b/test/testapps/BasicTestApp/CascadingValueTest/CascadingValueSupplier.cshtml new file mode 100644 index 0000000000..c83fd982af --- /dev/null +++ b/test/testapps/BasicTestApp/CascadingValueTest/CascadingValueSupplier.cshtml @@ -0,0 +1,33 @@ +@implements ICanDecrement + +@* + While it looks somewhat ridiculous to nest so many CascadingValue components, + it simplifies the E2E test and is not intended as a representative use case. + Each of the CascadingValue components here is configured differently for the test. +*@ + + + + + + + + + + + +

+

+

+ +@functions { + CounterDTO counterState = new CounterDTO { NumClicks = 100 }; + bool currentFlagValue1; + bool currentFlagValue2; + + public void DecrementCount() + { + counterState.NumClicks--; + StateHasChanged(); + } +} diff --git a/test/testapps/BasicTestApp/CascadingValueTest/CascadingValueTypes.cs b/test/testapps/BasicTestApp/CascadingValueTest/CascadingValueTypes.cs new file mode 100644 index 0000000000..e9d08a06cd --- /dev/null +++ b/test/testapps/BasicTestApp/CascadingValueTest/CascadingValueTypes.cs @@ -0,0 +1,20 @@ +// 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. + +namespace BasicTestApp.CascadingValueTest +{ + public class CounterDTO + { + public int NumClicks { get; set; } + + public void IncrementCount() + { + NumClicks++; + } + } + + public interface ICanDecrement + { + void DecrementCount(); + } +} diff --git a/test/testapps/BasicTestApp/Index.cshtml b/test/testapps/BasicTestApp/Index.cshtml index ab0f6f49e1..07d014e4b5 100644 --- a/test/testapps/BasicTestApp/Index.cshtml +++ b/test/testapps/BasicTestApp/Index.cshtml @@ -41,6 +41,7 @@ + @if (SelectedComponentType != null)