Skip to content

Commit

Permalink
Merge branch 'dev' of https://github.com/egil/bUnit into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
egil committed Mar 9, 2021
2 parents 57e8e1c + 469fbf4 commit 41773b3
Show file tree
Hide file tree
Showing 22 changed files with 155 additions and 115 deletions.
1 change: 1 addition & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,7 @@ dotnet_diagnostic.CA2201.severity = suggestion # CA2201: Do not raise reserved e
# StyleCop
# https://github.com/DotNetAnalyzers/StyleCopAnalyzers
dotnet_diagnostic.SA1000.severity = none # BUGGY with C#9 code
dotnet_diagnostic.SA1005.severity = none # SA1005: Single line comments should begin with single space
dotnet_diagnostic.SA1011.severity = none # BUGGY with C#9 code

dotnet_diagnostic.SA1027.severity = none # SA1027: Use Tabs Correctly
Expand Down
19 changes: 15 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,12 @@ jobs:

dotnet-test:
if: github.event_name != 'schedule'
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
framework: [netcoreapp3.1, net5.0]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout repository
uses: actions/checkout@v2
Expand All @@ -63,12 +68,18 @@ jobs:
with:
dotnet-version: '5.0.x'

- name: Running unit tests
- name: Running unit tests (linux, osx)
if: matrix.os != 'windows-latest'
run: dotnet test -c Debug --framework ${{ matrix.framework }} /p:UseSourceLink=true /p:CollectCoverage=true /p:CoverletOutput=./coverage/ /p:CoverletOutputFormat=opencover /p:ExcludeByAttribute=\"Obsolete,GeneratedCodeAttribute,CompilerGeneratedAttribute\"

- name: Running unit tests (windows only)
if: matrix.os == 'windows-latest'
run: |
dotnet build -c Debug /nowarn:CS1591 /p:UseSourceLink=true
dotnet test -c Debug --no-build /nowarn:CS1591 /p:CollectCoverage=true /p:CoverletOutput=./coverage/ /p:CoverletOutputFormat=opencover /p:ExcludeByAttribute=\"Obsolete,GeneratedCodeAttribute,CompilerGeneratedAttribute\" /p:UseSourceLink=true
dotnet clean -c Debug && dotnet nuget locals all --clear
dotnet test -c Debug --framework ${{ matrix.framework }}
- name: Upload coverage to Codecov
if: matrix.os == 'ubuntu-latest'
uses: codecov/codecov-action@v1

verify-template:
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -336,3 +336,5 @@ bunit.docs/log.txt
*coverage*.info
.sonarqube
tests/*/coverage

bunit.v3.ncrunchsolution.user
1 change: 1 addition & 0 deletions src/bunit.core/ComponentParameterCollectionBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using Bunit.Extensions;
using Microsoft.AspNetCore.Components;

namespace Bunit
Expand Down
1 change: 1 addition & 0 deletions src/bunit.core/ComponentParameterFactory.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Threading.Tasks;
using Bunit.Extensions;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;

Expand Down
2 changes: 1 addition & 1 deletion src/bunit.core/Extensions/BlazorExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Components;

namespace Bunit
namespace Bunit.Extensions
{
/// <summary>
/// Extensions for Blazor types.
Expand Down

This file was deleted.

43 changes: 43 additions & 0 deletions src/bunit.core/Extensions/RenderedFragmentInvokeAsyncExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System;
using System.Threading.Tasks;
using Bunit.Rendering;
using Microsoft.Extensions.DependencyInjection;

namespace Bunit
{
/// <summary>
/// InvokeAsync extensions methods on <see cref="IRenderedFragmentBase"/>.
/// </summary>
public static class RenderedFragmentInvokeAsyncExtensions
{
/// <summary>
/// Invokes the given <paramref name="workItem"/> in the context of the associated <see cref="ITestRenderer"/>.
/// </summary>
/// <param name="renderedFragment">The rendered fragment whose dispatcher to invoke with.</param>
/// <param name="workItem">The work item to execute on the renderer's thread.</param>
/// <returns>A <see cref="Task"/> that will be completed when the action has finished executing or is suspended by an asynchronous operation.</returns>
public static Task InvokeAsync(this IRenderedFragmentBase renderedFragment, Action workItem)
{
if (renderedFragment is null)
throw new ArgumentNullException(nameof(renderedFragment));

return renderedFragment.Services.GetRequiredService<ITestRenderer>()
.Dispatcher.InvokeAsync(workItem);
}

/// <summary>
/// Invokes the given <paramref name="workItem"/> in the context of the associated <see cref="ITestRenderer"/>.
/// </summary>
/// <param name="renderedFragment">The rendered component whose dispatcher to invoke with.</param>
/// <param name="workItem">The work item to execute on the renderer's thread.</param>
/// <returns>A <see cref="Task"/> that will be completed when the action has finished executing.</returns>
public static Task InvokeAsync(this IRenderedFragmentBase renderedFragment, Func<Task> workItem)
{
if (renderedFragment is null)
throw new ArgumentNullException(nameof(renderedFragment));

return renderedFragment.Services.GetRequiredService<ITestRenderer>()
.Dispatcher.InvokeAsync(workItem);
}
}
}
10 changes: 6 additions & 4 deletions src/bunit.core/Extensions/WaitForHelpers/WaitForHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ namespace Bunit.Extensions.WaitForHelpers
/// </summary>
public abstract class WaitForHelper : IDisposable
{
private readonly object lockObject = new();
private readonly Timer timer;
private readonly TaskCompletionSource<object?> completionSouce;
private readonly Func<bool> completeChecker;
Expand Down Expand Up @@ -52,6 +53,7 @@ protected WaitForHelper(IRenderedFragmentBase renderedFragment, Func<bool> compl
completionSouce = new TaskCompletionSource<object?>();
timer = new Timer(OnTimeout, this, Timeout.InfiniteTimeSpan, Timeout.InfiniteTimeSpan);

OnAfterRender(this, EventArgs.Empty);
this.renderedFragment.OnAfterRender += OnAfterRender;
OnAfterRender(this, EventArgs.Empty);
StartTimer(timeout);
Expand All @@ -62,7 +64,7 @@ private void StartTimer(TimeSpan? timeout)
if (isDisposed)
return;

lock (completionSouce)
lock (lockObject)
{
if (isDisposed)
return;
Expand All @@ -76,7 +78,7 @@ private void OnAfterRender(object? sender, EventArgs args)
if (isDisposed)
return;

lock (completionSouce)
lock (lockObject)
{
if (isDisposed)
return;
Expand Down Expand Up @@ -114,7 +116,7 @@ private void OnTimeout(object? state)
if (isDisposed)
return;

lock (completionSouce)
lock (lockObject)
{
if (isDisposed)
return;
Expand Down Expand Up @@ -150,7 +152,7 @@ protected virtual void Dispose(bool disposing)
if (isDisposed || !disposing)
return;

lock (completionSouce)
lock (lockObject)
{
if (isDisposed)
return;
Expand Down
17 changes: 14 additions & 3 deletions src/bunit.core/Rendering/TestRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public IRenderedComponentBase<TComponent> RenderComponent<TComponent>(ComponentP

/// <inheritdoc/>
public IRenderedComponentBase<TComponent> FindComponent<TComponent>(IRenderedFragmentBase parentComponent)
where TComponent : IComponent
where TComponent : IComponent
{
var foundComponents = FindComponents<TComponent>(parentComponent, 1);
return foundComponents.Count == 1
Expand All @@ -74,8 +74,8 @@ public IRenderedComponentBase<TComponent> FindComponent<TComponent>(IRenderedFra

/// <inheritdoc/>
public IReadOnlyList<IRenderedComponentBase<TComponent>> FindComponents<TComponent>(IRenderedFragmentBase parentComponent)
where TComponent : IComponent
=> FindComponents<TComponent>(parentComponent, int.MaxValue);
where TComponent : IComponent
=> FindComponents<TComponent>(parentComponent, int.MaxValue);

/// <inheritdoc/>
protected override void ProcessPendingRender()
Expand All @@ -87,6 +87,8 @@ protected override void ProcessPendingRender()
// render tree.
lock (renderTreeAccessLock)
{
logger.LogDebug(new EventId(6, nameof(ProcessPendingRender)), "Processing pending renders.");

base.ProcessPendingRender();
}
}
Expand All @@ -98,12 +100,15 @@ protected override void HandleException(Exception exception)
/// <inheritdoc/>
protected override Task UpdateDisplayAsync(in RenderBatch renderBatch)
{
logger.LogDebug(new EventId(10, nameof(UpdateDisplayAsync)), $"New render batch received.");

var renderEvent = new RenderEvent(renderBatch, new RenderTreeFrameDictionary());

// removes disposed components
for (var i = 0; i < renderBatch.DisposedComponentIDs.Count; i++)
{
var id = renderBatch.DisposedComponentIDs.Array[i];
logger.LogDebug(new EventId(10, nameof(UpdateDisplayAsync)), $"Component with ID = {id} has been disposed.");
if (renderedComponents.TryGetValue(id, out var rc))
{
renderedComponents.Remove(id);
Expand All @@ -114,6 +119,7 @@ protected override Task UpdateDisplayAsync(in RenderBatch renderBatch)
// notify each rendered component about the render
foreach (var (key, rc) in renderedComponents.ToArray())
{
logger.LogDebug(new EventId(11, nameof(UpdateDisplayAsync)), $"Component with ID = {rc.ComponentId} has been rendered.");
LoadRenderTreeFrames(rc.ComponentId, renderEvent.Frames);

rc.OnRender(renderEvent);
Expand All @@ -127,6 +133,8 @@ protected override Task UpdateDisplayAsync(in RenderBatch renderBatch)
}
}

logger.LogDebug(new EventId(10, nameof(UpdateDisplayAsync)), $"Finished updating components markup.");

return Task.CompletedTask;
}

Expand Down Expand Up @@ -162,9 +170,12 @@ private TResult Render<TResult>(RenderFragment renderFragment, Func<int, TResult

if (!renderTask.IsCompleted)
{
logger.LogDebug(new EventId(2, nameof(Render)), $"The initial render task for {renderedComponent.ComponentId} did not complete immediately.");
renderTask.GetAwaiter().GetResult();
}

logger.LogDebug(new EventId(5, nameof(Render)), $"The initial render of {renderedComponent.ComponentId} is completed.");

AssertNoUnhandledExceptions();

return renderedComponent!;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System;
using Xunit;
using Bunit;
using Bunit.TestDoubles;
using System;
using Xunit;

namespace Company.BlazorTests1
{
Expand All @@ -18,7 +18,7 @@ public void CounterStartsAtZero()
var cut = RenderComponent<Counter>();

// Assert that content of the paragraph shows counter at zero
cut.Find("p").MarkupMatches("<p>Current count: 0</p>");
cut.Find("p").MarkupMatches("<p>Current count: 0</p>");
}

[Fact]
Expand Down
2 changes: 1 addition & 1 deletion src/bunit.web/JSInterop/BunitJSInteropSetupExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using Bunit.JSInterop.InvocationHandlers;
using Microsoft.JSInterop;

namespace Bunit.JSInterop
namespace Bunit
{
/// <summary>
/// Helper methods for creating invocation handlers and adding the to a <see cref="BunitJSInterop"/>.
Expand Down
6 changes: 4 additions & 2 deletions src/bunit.xunit/Logging/XunitLogger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,12 @@ public XunitLogger(ITestOutputHelper output, string name, LogLevel minimumLogLev
}

/// <inheritdoc/>
public IDisposable BeginScope<TState>(TState state) => throw new NotImplementedException("Scoped logging is not supported by XunitLogger.");
public IDisposable BeginScope<TState>(TState state)
=> throw new NotImplementedException("Scoped logging is not supported by XunitLogger.");

/// <inheritdoc/>
public bool IsEnabled(LogLevel logLevel) => logLevel >= minimumLogLevel;
public bool IsEnabled(LogLevel logLevel)
=> logLevel >= minimumLogLevel;

/// <inheritdoc/>
public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter)
Expand Down
3 changes: 2 additions & 1 deletion src/bunit.xunit/Logging/XunitLoggerExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ public static class XunitLoggerExtensions
/// </summary>
public static IServiceCollection AddXunitLogger(this IServiceCollection services, LogLevel minimumLogLevel = LogLevel.Debug)
{
services.AddSingleton(srv => new XunitLoggerProvider(srv.GetRequiredService<ITestOutputHelper>(), minimumLogLevel));
services.AddSingleton<ILoggerProvider>(srv => new XunitLoggerProvider(srv.GetRequiredService<ITestOutputHelper>(), minimumLogLevel));
services.AddSingleton<ILoggerFactory, XunitLoggerFactory>();
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
return services;
}

Expand Down
2 changes: 1 addition & 1 deletion src/bunit.xunit/Logging/XunitLoggerFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class XunitLoggerFactory : LoggerFactory
/// <summary>
/// Initializes a new instance of the <see cref="XunitLoggerFactory"/> class.
/// </summary>
public XunitLoggerFactory(XunitLoggerProvider xunitLoggerProvider)
public XunitLoggerFactory(ILoggerProvider xunitLoggerProvider)
{
AddProvider(xunitLoggerProvider);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,6 @@ public void Test100()
// This click causes two renders, thus something is needed to await here.
cut.Find("#tock").Click();
cut.WaitForState(() => cut.Find("#state").TextContent == "Stopped");

cut.Find("#state").TextContent.ShouldBe("Stopped");
}

[Fact(DisplayName = "WaitForState can detect async changes to properties in the CUT")]
Expand Down
Loading

0 comments on commit 41773b3

Please sign in to comment.