Skip to content

Commit 9d3f1aa

Browse files
committed
Clean up interface dependencies
1 parent ff81b1f commit 9d3f1aa

20 files changed

Lines changed: 304 additions & 307 deletions

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
All notable changes to **bUnit** will be documented in this file. The project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
33

44
## [Unreleased]
5+
### Changed
6+
- Better error description from `MarkupMatches` when two sets of markup are different.
57

68
### Removed
79
- The generic collection assertion methods `ShouldAllBe<T>(this IEnumerable<T> collection, params Action<T, int>[] elementInspectors)` and `ShouldAllBe<T>(this IEnumerable<T> collection, params Action<T>[] elementInspectors)` have been removed from the library.

src/bunit.web.tests/ComponentTestFixtureTest.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using Xunit;
33
using Shouldly;
44
using Bunit.SampleComponents;
@@ -35,8 +35,8 @@ public void Test001()
3535
instance.NamedCascadingValue.ShouldBe(1337);
3636
Should.Throw<Exception>(async () => await instance.NonGenericCallback.InvokeAsync(null)).Message.ShouldBe("NonGenericCallback");
3737
Should.Throw<Exception>(async () => await instance.GenericCallback.InvokeAsync(EventArgs.Empty)).Message.ShouldBe("GenericCallback");
38-
new RenderedFragment(this, instance.ChildContent!).Markup.ShouldBe(nameof(ChildContent));
39-
new RenderedFragment(this, instance.OtherContent!).Markup.ShouldBe(nameof(AllTypesOfParams<string>.OtherContent));
38+
new RenderedFragment(Services, instance.ChildContent!).Markup.ShouldBe(nameof(ChildContent));
39+
new RenderedFragment(Services, instance.OtherContent!).Markup.ShouldBe(nameof(AllTypesOfParams<string>.OtherContent));
4040
Should.Throw<Exception>(() => instance.ItemTemplate!("")(null)).Message.ShouldBe("ItemTemplate");
4141
}
4242

@@ -74,8 +74,8 @@ public void Test002()
7474
instance.RegularParam.ShouldBe("some value");
7575
Should.Throw<Exception>(async () => await instance.NonGenericCallback.InvokeAsync(null)).Message.ShouldBe("NonGenericCallback");
7676
Should.Throw<Exception>(async () => await instance.GenericCallback.InvokeAsync(EventArgs.Empty)).Message.ShouldBe("GenericCallback");
77-
new RenderedFragment(this, instance.ChildContent!).Markup.ShouldBe(nameof(ChildContent));
78-
new RenderedFragment(this, instance.OtherContent!).Markup.ShouldBe(nameof(AllTypesOfParams<string>.OtherContent));
77+
new RenderedFragment(Services, instance.ChildContent!).Markup.ShouldBe(nameof(ChildContent));
78+
new RenderedFragment(Services, instance.OtherContent!).Markup.ShouldBe(nameof(AllTypesOfParams<string>.OtherContent));
7979
Should.Throw<Exception>(() => instance.ItemTemplate!("")(null)).Message.ShouldBe("ItemTemplate");
8080
}
8181

src/bunit.web.tests/Rendering/RenderedFragmentTest.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using Bunit.Extensions;
1+
using Bunit.Extensions;
22
using Bunit.SampleComponents;
33
using Microsoft.AspNetCore.Components;
44
using Microsoft.Extensions.Logging;
@@ -138,7 +138,7 @@ public void Test103()
138138
[Fact(DisplayName = "Render events for non-rendered sub components are not emitted")]
139139
public void Test010()
140140
{
141-
var renderSub = new ConcurrentRenderEventSubscriber(Renderer.RenderEvents);
141+
var renderSub = new ConcurrentRenderEventSubscriber(RenderEvents);
142142
var wrapper = RenderComponent<TwoComponentWrapper>(
143143
RenderFragment<Simple1>(nameof(TwoComponentWrapper.First)),
144144
RenderFragment<Simple1>(nameof(TwoComponentWrapper.Second))

src/bunit.web.tests/TestComponentBase.cs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,6 @@ public abstract class TestComponentBase : ComponentTestFixture, IRazorTestContex
2525
public override TestServiceProvider Services
2626
=> _testContextAdapter.HasActiveContext ? _testContextAdapter.Services : base.Services;
2727

28-
/// <inheritdoc/>
29-
public override TestRenderer Renderer
30-
=> _testContextAdapter.HasActiveContext ? _testContextAdapter.Renderer : base.Renderer;
31-
3228
/// <inheritdoc/>
3329
public TestComponentBase()
3430
{
@@ -70,12 +66,6 @@ public IRenderedFragment GetFragment(string? id = null)
7066
public IRenderedComponent<TComponent> GetFragment<TComponent>(string? id = null) where TComponent : class, IComponent
7167
=> _testContextAdapter.GetFragment<TComponent>(id);
7268

73-
/// <inheritdoc/>
74-
public override INodeList CreateNodes(string markup)
75-
=> _testContextAdapter.HasActiveContext
76-
? _testContextAdapter.CreateNodes(markup)
77-
: base.CreateNodes(markup);
78-
7969
/// <inheritdoc/>
8070
public override IRenderedComponent<TComponent> RenderComponent<TComponent>(params ComponentParameter[] parameters)
8171
=> _testContextAdapter.HasActiveContext

src/bunit.web.tests/TestRendererTest.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Linq;
33
using Bunit.BlazorE2E.BasicTestApp;
44
using Bunit.Extensions;
@@ -15,7 +15,7 @@ public class TestRendererTest : ComponentTestFixture
1515
[Fact(DisplayName = "Renderer pushes render events to subscribers when renders occur")]
1616
public void Test001()
1717
{
18-
var res = new ConcurrentRenderEventSubscriber(Renderer.RenderEvents);
18+
var res = new ConcurrentRenderEventSubscriber(RenderEvents);
1919
var sut = RenderComponent<TwoChildren>();
2020

2121
res.RenderCount.ShouldBe(1);

src/bunit.web.tests/XunitTestComponentBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ public abstract class XunitTestComponentBase<TTestComponent> : IComponent, IRazo
1919

2020
public TestServiceProvider Services => throw new NotImplementedException();
2121

22-
public TestRenderer Renderer => throw new NotImplementedException();
22+
public IObservable<RenderEvent> RenderEvents => throw new NotImplementedException();
2323

2424
public static IEnumerable<RazorTest[]> RazorTestsSource()
2525
{

src/bunit.web/Asserting/CompareToDiffingExtensions.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using System.Linq;
44
using AngleSharp.Diffing.Core;
55
using AngleSharp.Dom;
66
using Bunit.Diffing;
7+
using Microsoft.Extensions.DependencyInjection;
78

89
namespace Bunit
910
{
@@ -24,7 +25,8 @@ public static IReadOnlyList<IDiff> CompareTo(this IRenderedFragment actual, stri
2425
if (actual is null) throw new ArgumentNullException(nameof(actual));
2526
if (expected is null) throw new ArgumentNullException(nameof(expected));
2627

27-
var expectedNodes = actual.TestContext.CreateNodes(expected);
28+
var htmlParser = actual.Services.GetRequiredService<TestHtmlParser>();
29+
var expectedNodes = htmlParser.Parse(expected);
2830

2931
return actual.Nodes.CompareTo(expectedNodes);
3032
}

src/bunit.web/Asserting/HtmlEqualException.cs

Lines changed: 50 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,49 +4,62 @@
44
using System.Linq;
55
using AngleSharp;
66
using AngleSharp.Diffing.Core;
7+
using AngleSharp.Dom;
78
using Bunit;
89
using Bunit.Asserting;
910

1011
namespace Bunit
1112
{
12-
/// <summary>
13-
/// Represents an differences between pieces of markup.
14-
/// </summary>
15-
[SuppressMessage("Design", "CA1032:Implement standard exception constructors", Justification = "<Pending>")]
16-
public class HtmlEqualException : ActualExpectedAssertException
17-
{
18-
/// <summary>
19-
/// Creates an instance of the <see cref="HtmlEqualException"/> type.
20-
/// </summary>
21-
public HtmlEqualException(IEnumerable<IDiff> diffs, IMarkupFormattable expected, IMarkupFormattable actual, string? userMessage)
22-
: base(PrintHtml(actual), PrintHtml(expected), "Actual HTML", "Expected HTML", CreateUserMessage(diffs, userMessage))
23-
{
24-
}
13+
/// <summary>
14+
/// Represents an differences between pieces of markup.
15+
/// </summary>
16+
[SuppressMessage("Design", "CA1032:Implement standard exception constructors", Justification = "<Pending>")]
17+
public class HtmlEqualException : ActualExpectedAssertException
18+
{
19+
/// <summary>
20+
/// Creates an instance of the <see cref="HtmlEqualException"/> type.
21+
/// </summary>
22+
public HtmlEqualException(IEnumerable<IDiff> diffs, IMarkupFormattable expected, IMarkupFormattable actual, string? userMessage)
23+
: base(actual.PrintHtml(), expected.PrintHtml(), "Actual HTML", "Expected HTML", CreateUserMessage(diffs, userMessage))
24+
{
25+
}
2526

26-
private static string CreateUserMessage(IEnumerable<IDiff> diffs, string? userMessage)
27-
{
28-
return $"HTML comparison failed. {userMessage}{Environment.NewLine}{Environment.NewLine}The following errors were found:{Environment.NewLine}{PrintDiffs(diffs)}";
29-
}
27+
private static string CreateUserMessage(IEnumerable<IDiff> diffs, string? userMessage)
28+
{
29+
return $"HTML comparison failed. {userMessage}{Environment.NewLine}{Environment.NewLine}The following errors were found:{Environment.NewLine}{PrintDiffs(diffs)}";
30+
}
3031

31-
[SuppressMessage("Globalization", "CA1308:Normalize strings to uppercase", Justification = "<Pending>")]
32-
private static string PrintDiffs(IEnumerable<IDiff> diffs)
33-
{
34-
return string.Join(Environment.NewLine, diffs.Select((x, i) =>
35-
{
36-
var diffText = x switch
37-
{
38-
NodeDiff diff => $"The expected {diff.Control.Node.NodeType.ToString().ToLowerInvariant()} at {diff.Control.Path} and the actual {diff.Test.Node.NodeType.ToString().ToLowerInvariant()} at {diff.Test.Path} are different.",
39-
AttrDiff diff => $"The value of the expected attribute {diff.Control.Path} and actual attribute {diff.Test.Path} are different.",
40-
MissingNodeDiff diff => $"The {diff.Control.Node.NodeType.ToString().ToLowerInvariant()} at {diff.Control.Path} is missing.",
41-
MissingAttrDiff diff => $"The attribute at {diff.Control.Path} is missing.",
42-
UnexpectedNodeDiff diff => $"The {diff.Test.Node.NodeType.ToString().ToLowerInvariant()} at {diff.Test.Path} was not expected.",
43-
UnexpectedAttrDiff diff => $"The attribute at {diff.Test.Path} was not expected.",
44-
_ => throw new InvalidOperationException($"Unknown diff type detected: {x.GetType()}")
45-
};
46-
return $" {i + 1}: {diffText}";
47-
})) + Environment.NewLine;
48-
}
32+
[SuppressMessage("Globalization", "CA1308:Normalize strings to uppercase", Justification = "<Pending>")]
33+
private static string PrintDiffs(IEnumerable<IDiff> diffs)
34+
{
35+
return string.Join(Environment.NewLine, diffs.Select((x, i) =>
36+
{
37+
var diffText = x switch
38+
{
39+
NodeDiff diff when diff.Target == DiffTarget.Text && diff.Control.Path.Equals(diff.Test.Path)
40+
=> $"The text in {diff.Control.Path} is different.",
41+
NodeDiff diff when diff.Target == DiffTarget.Text
42+
=> $"The expected {diff.Control.NodeName()} at {diff.Control.Path} and the actual {diff.Test.NodeName()} at {diff.Test.Path} is different.",
43+
NodeDiff diff when diff.Control.Path.Equals(diff.Test.Path)
44+
=> $"The {diff.Control.NodeName()}s at {diff.Control.Path} are different.",
45+
NodeDiff diff => $"The expected {diff.Control.NodeName()} at {diff.Control.Path} and the actual {diff.Test.NodeName()} at {diff.Test.Path} are different.",
46+
AttrDiff diff when diff.Control.Path.Equals(diff.Test.Path)
47+
=> $"The values of the attributes at {diff.Control.Path} are different.",
48+
AttrDiff diff => $"The value of the attribute {diff.Control.Path} and actual attribute {diff.Test.Path} are different.",
49+
MissingNodeDiff diff => $"The {diff.Control.NodeName()} at {diff.Control.Path} is missing.",
50+
MissingAttrDiff diff => $"The attribute at {diff.Control.Path} is missing.",
51+
UnexpectedNodeDiff diff => $"The {diff.Test.NodeName()} at {diff.Test.Path} was not expected.",
52+
UnexpectedAttrDiff diff => $"The attribute at {diff.Test.Path} was not expected.",
53+
_ => throw new InvalidOperationException($"Unknown diff type detected: {x.GetType()}")
54+
};
55+
return $" {i + 1}: {diffText}";
56+
})) + Environment.NewLine;
57+
}
58+
}
4959

50-
private static string PrintHtml(IMarkupFormattable nodes) => nodes.ToDiffMarkup() + Environment.NewLine;
51-
}
60+
internal static class ComparisonFormatHelpers
61+
{
62+
public static string NodeName(this ComparisonSource source) => source.Node.NodeType.ToString().ToLowerInvariant();
63+
public static string PrintHtml(this IMarkupFormattable nodes) => nodes.ToDiffMarkup() + Environment.NewLine;
64+
}
5265
}

src/bunit.web/Asserting/MarkupMatchesAssertExtensions.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
using System;
1+
using System;
22
using AngleSharp.Dom;
33
using Bunit.Diffing;
4+
using Microsoft.Extensions.DependencyInjection;
45
using Xunit.Sdk;
56

67
namespace Bunit
@@ -24,7 +25,8 @@ public static void MarkupMatches(this IRenderedFragment actual, string expected,
2425
if (actual is null) throw new ArgumentNullException(nameof(actual));
2526
if (expected is null) throw new ArgumentNullException(nameof(expected));
2627

27-
var expectedNodes = actual.TestContext.CreateNodes(expected);
28+
var htmlParser = actual.Services.GetRequiredService<TestHtmlParser>();
29+
var expectedNodes = htmlParser.Parse(expected);
2830

2931
actual.Nodes.MarkupMatches(expectedNodes, userMessage);
3032
}

src/bunit.web/Components/TestContextAdapter.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Collections.Generic;
33
using AngleSharp.Dom;
44
using Microsoft.AspNetCore.Components;
@@ -12,7 +12,7 @@ internal sealed class TestContextAdapter : IDisposable
1212

1313
public TestServiceProvider Services => _testContext?.Services ?? throw new InvalidOperationException("No active test context in the adapter");
1414

15-
public TestRenderer Renderer => _testContext?.Renderer ?? throw new InvalidOperationException("No active test context in the adapter");
15+
//public TestRenderer Renderer => _testContext?.Renderer ?? throw new InvalidOperationException("No active test context in the adapter");
1616

1717
public bool HasActiveContext => !(_testContext is null);
1818

@@ -58,8 +58,5 @@ public IRenderedComponent<TComponent> GetFragment<TComponent>(string? id) where
5858

5959
public IRenderedComponent<TComponent> RenderComponent<TComponent>(params ComponentParameter[] parameters) where TComponent : class, IComponent
6060
=> _testContext?.RenderComponent<TComponent>(parameters) ?? throw new InvalidOperationException("No active test context in the adapter");
61-
62-
public INodeList CreateNodes(string markup)
63-
=> _testContext?.CreateNodes(markup) ?? throw new InvalidOperationException("No active test context in the adapter");
6461
}
6562
}

0 commit comments

Comments
 (0)