diff --git a/.github/workflows/verification-dotnet-nightly.yml b/.github/workflows/verification-dotnet-nightly.yml
deleted file mode 100644
index 49da31b50..000000000
--- a/.github/workflows/verification-dotnet-nightly.yml
+++ /dev/null
@@ -1,64 +0,0 @@
-name: verification-dotnet-nightly
-
-on:
- schedule:
- - cron: "0 0 * * *"
- workflow_dispatch:
-
-jobs:
- verify-bunit:
- name: ๐ Verify bUnit
- runs-on: ubuntu-latest
- container:
- image: mcr.microsoft.com/dotnet/nightly/sdk:7.0
-
- steps:
- - name: ๐ Show dotnet version
- run: |
- dotnet --info
-
- - name: ๐ Checkout repository
- uses: actions/checkout@v2
- with:
- fetch-depth: 0
-
- - name: ๐จ Setup color
- run: |
- echo "DOTNET_SYSTEM_CONSOLE_ALLOW_ANSI_COLOR_REDIRECTION=1" >> $GITHUB_ENV
- echo "TERM=xterm" >> $GITHUB_ENV
-
- - name: ๐ฆ Setup nuget nightly builds
- run: |
- dotnet restore --verbosity normal -s https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet7/nuget/v3/index.json -s https://api.nuget.org/v3/index.json
-
- - name: ๐งช Run unit tests
- run: |
- dotnet test ./tests/bunit.core.tests/bunit.core.tests.csproj -c release --no-restore -f net7.0 --logger:"console;verbosity=normal" --blame-hang-timeout 15s --blame-hang-dump-type full --blame-crash-dump-type full
- dotnet test ./tests/bunit.web.tests/bunit.web.tests.csproj -c release --no-restore -f net7.0 --logger:"console;verbosity=normal" --blame-hang-timeout 15s --blame-hang-dump-type full --blame-crash-dump-type full
- dotnet test ./tests/AngleSharpWrappers.Tests/AngleSharpWrappers.Tests.csproj -c release --no-restore -f net7.0 --logger:"console;verbosity=normal" --blame-hang-timeout 15s --blame-hang-dump-type full --blame-crash-dump-type full
-
- - name: ๐ Upload hang- and crash-dumps on test failure
- if: failure()
- uses: actions/upload-artifact@v3
- with:
- if-no-files-found: ignore
- name: test-dumps
- path: |
- **/*hangdump.dmp
- **/*crashdump.dmp
-
- - name: ๐งพ Collect dotnet information
- if: failure()
- run: |
- echo "DOTNET_VERSION=$(dotnet --version)" >> $GITHUB_ENV
- echo $DOTNET_VERSION
-
- - name: โก Create issue if failed
- if: failure()
- uses: JasonEtco/create-an-issue@v2
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- ADJECTIVE: DOTNET_VERSION
- with:
- filename: .github/nightly-failed.md
- update_existing: true
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a1aaffd9f..28ee4e258 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@ All notable changes to **bUnit** will be documented in this file. The project ad
## [Unreleased]
+### Added
+- Added the `StateFromJson` method to the `NavigationHistory` type, to make it easy to deserialize navigation state stored as JSON during a call to `NavigationManager.NavigateTo`, e.g. as seen with the new `InteractiveRequestOptions` type available in .NET 7. By [@linkdotnet](https://github.com/linkdotnet) and [@egil](https://github.com/egil).
+
## [1.10.14] - 2022-09-16
### Added
diff --git a/Directory.Build.props b/Directory.Build.props
index fe29a2151..60b5f6fdc 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -48,7 +48,7 @@
-
+
();
+
+ActionToTriggerTheNavigationManager();
+
+// This helper method retrieves the InteractiveRequestOptions object
+var requestOptions = navigationManager.History.Last().StateFromJson();
+Asser.NotNull(requestOptions);
+Assert.Equal(requestOptions.Interaction, InteractionType.SignIn);
+options.TryGetAdditionalParameter("prompt", out string prompt);
+Assert.Equal(prompt, "login");
```
\ No newline at end of file
diff --git a/src/Directory.Build.props b/src/Directory.Build.props
index 74f317d57..4f3431aa3 100644
--- a/src/Directory.Build.props
+++ b/src/Directory.Build.props
@@ -43,7 +43,7 @@
-
+
diff --git a/src/bunit.core/ComponentParameterCollectionBuilder.cs b/src/bunit.core/ComponentParameterCollectionBuilder.cs
index edfb05897..013241b21 100644
--- a/src/bunit.core/ComponentParameterCollectionBuilder.cs
+++ b/src/bunit.core/ComponentParameterCollectionBuilder.cs
@@ -72,7 +72,7 @@ public ComponentParameterCollectionBuilder Add(Expr
/// A lambda function that selects the parameter.
/// The markup string to pass to the .
/// This .
- public ComponentParameterCollectionBuilder Add(Expression> parameterSelector, string markup)
+ public ComponentParameterCollectionBuilder Add(Expression> parameterSelector, [StringSyntax("Html")]string markup)
=> Add(parameterSelector, markup.ToMarkupRenderFragment());
///
@@ -260,7 +260,7 @@ public ComponentParameterCollectionBuilder AddChildContent(RenderFra
///
/// The markup string to pass the ChildContent parameter wrapped in a .
/// This .
- public ComponentParameterCollectionBuilder AddChildContent(string markup)
+ public ComponentParameterCollectionBuilder AddChildContent([StringSyntax("Html")]string markup)
=> AddChildContent(markup.ToMarkupRenderFragment());
///
diff --git a/src/bunit.core/ComponentParameterFactory.cs b/src/bunit.core/ComponentParameterFactory.cs
index 9488dfe5c..668a8c65f 100644
--- a/src/bunit.core/ComponentParameterFactory.cs
+++ b/src/bunit.core/ComponentParameterFactory.cs
@@ -137,7 +137,7 @@ public static ComponentParameter CascadingValue(object value)
///
/// Markup to pass to the child content parameter.
/// The .
- public static ComponentParameter ChildContent(string markup)
+ public static ComponentParameter ChildContent([StringSyntax("Html")]string markup)
{
return RenderFragment(nameof(ChildContent), markup);
}
@@ -173,7 +173,7 @@ public static ComponentParameter ChildContent(RenderFragment renderFragment)
/// Parameter name.
/// Markup to pass to the render fragment parameter.
/// The .
- public static ComponentParameter RenderFragment(string name, string markup)
+ public static ComponentParameter RenderFragment(string name, [StringSyntax("Html")]string markup)
{
return ComponentParameter.CreateParameter(name, markup.ToMarkupRenderFragment());
}
diff --git a/src/bunit.core/Extensions/BlazorExtensions.cs b/src/bunit.core/Extensions/BlazorExtensions.cs
index 0f4cc45f5..daba2f7cf 100644
--- a/src/bunit.core/Extensions/BlazorExtensions.cs
+++ b/src/bunit.core/Extensions/BlazorExtensions.cs
@@ -10,7 +10,7 @@ public static class BlazorExtensions
///
/// Markup to render.
/// The .
- public static RenderFragment ToMarkupRenderFragment(this string? markup)
+ public static RenderFragment ToMarkupRenderFragment([StringSyntax("Html")]this string? markup)
{
if (string.IsNullOrEmpty(markup))
return _ => { };
diff --git a/src/bunit.core/Extensions/WaitForHelpers/WaitForHelper.cs b/src/bunit.core/Extensions/WaitForHelpers/WaitForHelper.cs
index 9bcd8a277..e32dd7d73 100644
--- a/src/bunit.core/Extensions/WaitForHelpers/WaitForHelper.cs
+++ b/src/bunit.core/Extensions/WaitForHelpers/WaitForHelper.cs
@@ -9,6 +9,7 @@ namespace Bunit.Extensions.WaitForHelpers;
///
public abstract class WaitForHelper : IDisposable
{
+ private readonly Timer timer;
private readonly TaskCompletionSource checkPassedCompletionSource;
private readonly Func<(bool CheckPassed, T Content)> completeChecker;
private readonly IRenderedFragmentBase renderedFragment;
@@ -51,7 +52,13 @@ protected WaitForHelper(
logger = renderedFragment.Services.CreateLogger>();
checkPassedCompletionSource = new TaskCompletionSource();
- WaitTask = CreateWaitTask(renderedFragment, timeout);
+ timer = new Timer(_ =>
+ {
+ logger.LogWaiterTimedOut(renderedFragment.ComponentId);
+ checkPassedCompletionSource.TrySetException(new WaitForFailedException(TimeoutErrorMessage, capturedException));
+ });
+ WaitTask = CreateWaitTask(renderedFragment);
+ timer.Change(GetRuntimeTimeout(timeout), Timeout.InfiniteTimeSpan);
InitializeWaiting();
}
@@ -80,6 +87,7 @@ protected virtual void Dispose(bool disposing)
return;
isDisposed = true;
+ timer.Dispose();
checkPassedCompletionSource.TrySetCanceled();
renderedFragment.OnAfterRender -= OnAfterRender;
logger.LogWaiterDisposed(renderedFragment.ComponentId);
@@ -105,9 +113,11 @@ private void InitializeWaiting()
}
}
- private Task CreateWaitTask(IRenderedFragmentBase renderedFragment, TimeSpan? timeout)
+ private Task CreateWaitTask(IRenderedFragmentBase renderedFragment)
{
- var renderer = renderedFragment.Services.GetRequiredService();
+ var renderer = renderedFragment
+ .Services
+ .GetRequiredService();
// Two to failure conditions, that the renderer captures an unhandled
// exception from a component or itself, or that the timeout is reached,
@@ -115,31 +125,18 @@ private Task CreateWaitTask(IRenderedFragmentBase renderedFragment, TimeSpan?
// and the continuations does not happen at the same time.
var failureTask = renderer.Dispatcher.InvokeAsync(() =>
{
- var taskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
-
- var renderException = renderer
+ return renderer
.UnhandledException
.ContinueWith(
x => Task.FromException(x.Result),
CancellationToken.None,
TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.ExecuteSynchronously,
- taskScheduler);
-
- var timeoutTask = Task.Delay(GetRuntimeTimeout(timeout))
- .ContinueWith(
- x =>
- {
- logger.LogWaiterTimedOut(renderedFragment.ComponentId);
- return Task.FromException(new WaitForFailedException(TimeoutErrorMessage, capturedException));
- },
- CancellationToken.None,
- TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.ExecuteSynchronously,
- taskScheduler);
-
- return Task.WhenAny(renderException, timeoutTask).Unwrap();
+ TaskScheduler.FromCurrentSynchronizationContext());
}).Unwrap();
- return Task.WhenAny(failureTask, checkPassedCompletionSource.Task).Unwrap();
+ return Task
+ .WhenAny(checkPassedCompletionSource.Task, failureTask)
+ .Unwrap();
}
private void OnAfterRender(object? sender, EventArgs args)
@@ -170,7 +167,8 @@ private void OnAfterRender(object? sender, EventArgs args)
if (StopWaitingOnCheckException)
{
- checkPassedCompletionSource.TrySetException(new WaitForFailedException(CheckThrowErrorMessage, capturedException));
+ checkPassedCompletionSource.TrySetException(
+ new WaitForFailedException(CheckThrowErrorMessage, capturedException));
Dispose();
}
}
diff --git a/src/bunit.core/StringSyntaxAttribute.cs b/src/bunit.core/StringSyntaxAttribute.cs
new file mode 100644
index 000000000..8817b14fd
--- /dev/null
+++ b/src/bunit.core/StringSyntaxAttribute.cs
@@ -0,0 +1,25 @@
+#if !NET7_0_OR_GREATER
+namespace System.Diagnostics.CodeAnalysis;
+
+/// Fake version of the StringSyntaxAttribute, which was introduced in .NET 7
+[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
+public sealed class StringSyntaxAttribute : Attribute
+{
+ ///
+ /// Initializes the with the identifier of the syntax used.
+ ///
+ public StringSyntaxAttribute(string syntax)
+ {
+ }
+
+ ///
+ /// Initializes the with the identifier of the syntax used.
+ ///
+ public StringSyntaxAttribute(string syntax, params object?[] arguments)
+ {
+ }
+
+ /// The syntax identifier for strings containing URIs.
+ public const string Uri = nameof(Uri);
+}
+#endif
diff --git a/src/bunit.web/Asserting/MarkupMatchesAssertExtensions.cs b/src/bunit.web/Asserting/MarkupMatchesAssertExtensions.cs
index 3474c61ef..4d7c2fe5e 100644
--- a/src/bunit.web/Asserting/MarkupMatchesAssertExtensions.cs
+++ b/src/bunit.web/Asserting/MarkupMatchesAssertExtensions.cs
@@ -20,7 +20,7 @@ public static class MarkupMatchesAssertExtensions
/// The expected markup fragment.
/// A custom user message to display in case the verification fails.
[AssertionMethod]
- public static void MarkupMatches(this string actual, string expected, string? userMessage = null)
+ public static void MarkupMatches([StringSyntax("Html")]this string actual, [StringSyntax("Html")]string expected, string? userMessage = null)
{
if (actual is null)
throw new ArgumentNullException(nameof(actual));
@@ -42,7 +42,7 @@ public static void MarkupMatches(this string actual, string expected, string? us
/// The expected .
/// A custom user message to display in case the verification fails.
[AssertionMethod]
- public static void MarkupMatches(this string actual, IRenderedFragment expected, string? userMessage = null)
+ public static void MarkupMatches([StringSyntax("Html")]this string actual, IRenderedFragment expected, string? userMessage = null)
{
if (actual is null)
throw new ArgumentNullException(nameof(actual));
@@ -62,7 +62,7 @@ public static void MarkupMatches(this string actual, IRenderedFragment expected,
/// The expected .
/// A custom user message to display in case the verification fails.
[AssertionMethod]
- public static void MarkupMatches(this string actual, INodeList expected, string? userMessage = null)
+ public static void MarkupMatches([StringSyntax("Html")]this string actual, INodeList expected, string? userMessage = null)
{
if (actual is null)
throw new ArgumentNullException(nameof(actual));
@@ -82,7 +82,7 @@ public static void MarkupMatches(this string actual, INodeList expected, string?
/// The expected .
/// A custom user message to display in case the verification fails.
[AssertionMethod]
- public static void MarkupMatches(this string actual, INode expected, string? userMessage = null)
+ public static void MarkupMatches([StringSyntax("Html")]this string actual, INode expected, string? userMessage = null)
{
if (actual is null)
throw new ArgumentNullException(nameof(actual));
@@ -102,7 +102,7 @@ public static void MarkupMatches(this string actual, INode expected, string? use
/// The expected markup.
/// A custom user message to display in case the verification fails.
[AssertionMethod]
- public static void MarkupMatches(this IRenderedFragment actual, string expected, string? userMessage = null)
+ public static void MarkupMatches(this IRenderedFragment actual, [StringSyntax("Html")]string expected, string? userMessage = null)
{
if (actual is null)
throw new ArgumentNullException(nameof(actual));
@@ -182,7 +182,7 @@ public static void MarkupMatches(this INode actual, IRenderedFragment expected,
/// The expected markup.
/// A custom user message to display in case the verification fails.
[AssertionMethod]
- public static void MarkupMatches(this INode actual, string expected, string? userMessage = null)
+ public static void MarkupMatches(this INode actual, [StringSyntax("Html")]string expected, string? userMessage = null)
{
if (actual is null)
throw new ArgumentNullException(nameof(actual));
@@ -203,7 +203,7 @@ public static void MarkupMatches(this INode actual, string expected, string? use
/// The expected markup.
/// A custom user message to display in case the verification fails.
[AssertionMethod]
- public static void MarkupMatches(this INodeList actual, string expected, string? userMessage = null)
+ public static void MarkupMatches(this INodeList actual, [StringSyntax("Html")]string expected, string? userMessage = null)
{
if (actual is null)
throw new ArgumentNullException(nameof(actual));
@@ -351,11 +351,11 @@ public static void MarkupMatches(this INodeList actual, RenderFragment expected,
/// the markup fragment, using the type.
///
/// Thrown when the markup does not match the markup.
- /// A enumerable of IElements to verifiy.
+ /// A enumerable of IElements to verify.
/// The expected markup fragment.
/// A custom user message to display in case the verification fails.
[AssertionMethod]
- public static void MarkupMatches(this IEnumerable actual, string expected, string? userMessage = null)
+ public static void MarkupMatches(this IEnumerable actual, [StringSyntax("Html")]string expected, string? userMessage = null)
{
if (actual is null)
throw new ArgumentNullException(nameof(actual));
@@ -370,7 +370,7 @@ public static void MarkupMatches(this IEnumerable actual, string expec
/// the fragments, using the type.
///
/// Thrown when the element does not match the fragments.
- /// An IElement to verifiy.
+ /// An IElement to verify.
/// The expected markup fragments.
/// A custom user message to display in case the verification fails.
[AssertionMethod]
@@ -412,7 +412,7 @@ public static void MarkupMatches(this IElement actual, IEnumerable exp
/// the fragment, using the type.
///
/// Thrown when the elements does not match the fragment.
- /// A list of elements to verifiy.
+ /// A list of elements to verify.
/// The expected markup fragment.
/// A custom user message to display in case the verification fails.
[AssertionMethod]
@@ -473,9 +473,7 @@ private static INodeList ToNodeList(this IEnumerable elements, BunitHt
using var parser = new BunitHtmlParser();
return nodesStr.ToNodeList(parser);
}
- else
- {
- return nodesStr.ToNodeList(htmlParser);
- }
+
+ return nodesStr.ToNodeList(htmlParser);
}
}
diff --git a/src/bunit.web/Extensions/StubComponentFactoryCollectionExtensions.cs b/src/bunit.web/Extensions/StubComponentFactoryCollectionExtensions.cs
index 01da2102a..011c82464 100644
--- a/src/bunit.web/Extensions/StubComponentFactoryCollectionExtensions.cs
+++ b/src/bunit.web/Extensions/StubComponentFactoryCollectionExtensions.cs
@@ -39,7 +39,7 @@ static Predicate CreatePredicate(Type componentTypeToStub)
/// The bUnit to configure.
/// Markup that will be used as render output instead of the stubbed out component.
/// A .
- public static ComponentFactoryCollection AddStub(this ComponentFactoryCollection factories, string replacementMarkup) where TComponent : IComponent
+ public static ComponentFactoryCollection AddStub(this ComponentFactoryCollection factories, [StringSyntax("Html")]string replacementMarkup) where TComponent : IComponent
=> AddStub(factories, b => b.AddMarkupContent(0, replacementMarkup));
///
diff --git a/src/bunit.web/Rendering/BunitHtmlParser.cs b/src/bunit.web/Rendering/BunitHtmlParser.cs
index 07a7f42c1..c6edf2971 100644
--- a/src/bunit.web/Rendering/BunitHtmlParser.cs
+++ b/src/bunit.web/Rendering/BunitHtmlParser.cs
@@ -57,7 +57,7 @@ private BunitHtmlParser(IConfiguration angleSharpConfiguration)
///
/// The markup to parse.
/// The .
- public INodeList Parse(string markup)
+ public INodeList Parse([StringSyntax("Html")]string markup)
{
if (markup is null)
throw new ArgumentNullException(nameof(markup));
@@ -187,4 +187,4 @@ public IEnumerator GetEnumerator()
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
-}
\ No newline at end of file
+}
diff --git a/src/bunit.web/TestDoubles/NavigationManager/NavigationHistory.cs b/src/bunit.web/TestDoubles/NavigationManager/NavigationHistory.cs
index e6b86e73c..9422f7a58 100644
--- a/src/bunit.web/TestDoubles/NavigationManager/NavigationHistory.cs
+++ b/src/bunit.web/TestDoubles/NavigationManager/NavigationHistory.cs
@@ -1,4 +1,8 @@
+#if NET7_0_OR_GREATER
+using System.Text.Json;
using Microsoft.AspNetCore.Components.Routing;
+using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
+#endif
namespace Bunit.TestDoubles;
@@ -45,7 +49,7 @@ public sealed class NavigationHistory : IEquatable
///
///
[SuppressMessage("Design", "CA1054:URI-like parameters should not be strings", Justification = "Using string to align with NavigationManager")]
- public NavigationHistory(string uri, Bunit.TestDoubles.NavigationOptions options)
+ public NavigationHistory([StringSyntax(StringSyntaxAttribute.Uri)]string uri, Bunit.TestDoubles.NavigationOptions options)
{
Uri = uri;
Options = options;
@@ -58,7 +62,7 @@ public NavigationHistory(string uri, Bunit.TestDoubles.NavigationOptions options
///
///
[SuppressMessage("Design", "CA1054:URI-like parameters should not be strings", Justification = "Using string to align with NavigationManager")]
- public NavigationHistory(string uri, NavigationOptions options)
+ public NavigationHistory([StringSyntax(StringSyntaxAttribute.Uri)]string uri, NavigationOptions options)
{
Uri = uri;
Options = options;
@@ -74,13 +78,37 @@ public NavigationHistory(string uri, NavigationOptions options)
///
///
[SuppressMessage("Design", "CA1054:URI-like parameters should not be strings", Justification = "Using string to align with NavigationManager")]
- public NavigationHistory(string uri, NavigationOptions options, NavigationState navigationState, Exception? exception = null)
+ public NavigationHistory(
+ [StringSyntax(StringSyntaxAttribute.Uri)]string uri,
+ NavigationOptions options,
+ NavigationState navigationState,
+ Exception? exception = null)
{
Uri = uri;
Options = options;
State = navigationState;
Exception = exception;
}
+
+ ///
+ /// Deserialize the content of .
+ /// into if it is not null.
+ ///
+ /// The type to deserialize the content of . to.
+ /// The used when deserializing. If not provided, is used.
+ /// The target type of the JSON value.
+ /// When . is null.
+ public T? StateFromJson(JsonSerializerOptions? options = null)
+ {
+ if (Options.HistoryEntryState is null)
+ {
+ throw new InvalidOperationException($"No {nameof(Options.HistoryEntryState)} has been set.");
+ }
+
+ return JsonSerializer.Deserialize(
+ Options.HistoryEntryState,
+ options ?? JsonSerializerOptions.Default);
+ }
#endif
///
@@ -88,13 +116,22 @@ public NavigationHistory(string uri, NavigationOptions options, NavigationState
public bool Equals(NavigationHistory? other)
=> other is not null && string.Equals(Uri, other.Uri, StringComparison.Ordinal) && Options.Equals(other.Options);
#endif
-#if NET6_0_OR_GREATER
+#if NET6_0
public bool Equals(NavigationHistory? other)
=> other is not null
&& string.Equals(Uri, other.Uri, StringComparison.Ordinal)
&& Options.ForceLoad == other.Options.ForceLoad
&& Options.ReplaceHistoryEntry == other.Options.ReplaceHistoryEntry;
#endif
+#if NET7_0_OR_GREATER
+ public bool Equals(NavigationHistory? other)
+ => other is not null
+ && string.Equals(Uri, other.Uri, StringComparison.Ordinal)
+ && Options.ForceLoad == other.Options.ForceLoad
+ && Options.ReplaceHistoryEntry == other.Options.ReplaceHistoryEntry
+ && State == other.State
+ && Exception == other.Exception;
+#endif
///
public override bool Equals(object? obj) => obj is NavigationHistory other && Equals(other);
diff --git a/tests/Directory.Build.props b/tests/Directory.Build.props
index 9ed6290d0..143b11772 100644
--- a/tests/Directory.Build.props
+++ b/tests/Directory.Build.props
@@ -16,11 +16,11 @@
-
+
-
+
diff --git a/tests/bunit.web.tests/TestDoubles/NavigationManager/FakeNavigationManagerTest.cs b/tests/bunit.web.tests/TestDoubles/NavigationManager/FakeNavigationManagerTest.cs
index 3709497c0..68549436d 100644
--- a/tests/bunit.web.tests/TestDoubles/NavigationManager/FakeNavigationManagerTest.cs
+++ b/tests/bunit.web.tests/TestDoubles/NavigationManager/FakeNavigationManagerTest.cs
@@ -1,3 +1,6 @@
+using System.Text.Json;
+using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
+
namespace Bunit.TestDoubles;
using static Microsoft.AspNetCore.Components.CompilerServices.RuntimeHelpers;
@@ -219,6 +222,47 @@ public void Test012()
entry.State.ShouldBe(NavigationState.Faulted);
}
+ [Fact(DisplayName = "StateFromJson deserialize InteractiveRequestOptions")]
+ public void Test013()
+ {
+ var fakeNavigationManager = CreateFakeNavigationManager();
+ var requestOptions = new InteractiveRequestOptions
+ {
+ ReturnUrl = "return", Interaction = InteractionType.SignIn,
+ };
+ requestOptions.TryAddAdditionalParameter("library", "bunit");
+
+ fakeNavigationManager.NavigateToLogin("/some-url", requestOptions);
+
+ var options = fakeNavigationManager.History.Last().StateFromJson();
+ options.ShouldNotBeNull();
+ options.Interaction.ShouldBe(InteractionType.SignIn);
+ options.ReturnUrl.ShouldBe("return");
+ options.TryGetAdditionalParameter("library", out string libraryName).ShouldBeTrue();
+ libraryName.ShouldBe("bunit");
+ }
+
+ [Fact(DisplayName = "Given no content in state then StateFromJson throws")]
+ public void Test014()
+ {
+ var fakeNavigationManager = CreateFakeNavigationManager();
+ fakeNavigationManager.NavigateTo("/some-url");
+
+ Should.Throw(
+ () => fakeNavigationManager.History.Last().StateFromJson());
+ }
+
+ [Fact(DisplayName = "StateFromJson with invalid json throws")]
+ public void Test015()
+ {
+ var fakeNavigationManager = CreateFakeNavigationManager();
+
+ fakeNavigationManager.NavigateTo("/login", new NavigationOptions { HistoryEntryState = "" });
+
+ Should.Throw(
+ () => fakeNavigationManager.History.Last().StateFromJson());
+ }
+
private class InterceptNavigateToCounterComponent : ComponentBase
{
protected override void BuildRenderTree(RenderTreeBuilder builder)
@@ -251,7 +295,6 @@ private void InterceptNavigation(LocationChangingContext context)
public class GotoExternalResourceComponent : ComponentBase
{
-#pragma warning disable 1998
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
builder.OpenElement(0, "button");
diff --git a/tests/run-tests.ps1 b/tests/run-tests.ps1
index 51e7f05a4..3b8fe0688 100644
--- a/tests/run-tests.ps1
+++ b/tests/run-tests.ps1
@@ -10,14 +10,10 @@ for ($num = 1 ; $num -le $maxRuns ; $num++)
if($filter)
{
- dotnet test .\bunit.core.tests\bunit.core.tests.csproj -c $mode --no-restore --no-build --blame-hang --blame-hang-timeout 100s --nologo --filter $filter --logger:"console;verbosity=normal"
- dotnet test .\bunit.web.tests\bunit.web.tests.csproj -c $mode --no-restore --no-build --blame-hang --blame-hang-timeout 100s --nologo --filter $filter --logger:"console;verbosity=normal"
- dotnet test .\bunit.web.testcomponents.tests\bunit.web.testcomponents.teststests.csproj -c $mode --no-restore --no-build --blame-hang --blame-hang-timeout 100s --nologo --filter $filter --logger:"console;verbosity=normal"
+ dotnet test ..\bunit.sln -c $mode --no-restore --no-build --blame --nologo --filter $filter
}
else
{
- dotnet test .\bunit.core.tests\bunit.core.tests.csproj -c $mode --no-restore --no-build --blame-hang --blame-hang-timeout 100s --nologo
- dotnet test .\bunit.web.tests\bunit.web.tests.csproj -c $mode --no-restore --no-build --blame-hang --blame-hang-timeout 100s --nologo
- dotnet test .\bunit.web.testcomponents.tests\bunit.web.testcomponents.tests.csproj -c $mode --no-restore --no-build --blame-hang --blame-hang-timeout 100s --nologo
+ dotnet test ..\bunit.sln -c $mode --no-restore --no-build --blame --nologo
}
}
diff --git a/version.json b/version.json
index 35c5358b2..cce110611 100644
--- a/version.json
+++ b/version.json
@@ -1,6 +1,6 @@
{
"$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
- "version": "1.10",
+ "version": "1.11",
"assemblyVersion": {
"precision": "revision"
},