Skip to content

Commit 4370a85

Browse files
committed
Tweaks to assert helpers and API
1 parent 02fc237 commit 4370a85

32 files changed

+665
-235
lines changed

.editorconfig

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
[*.cs]
22

33
# CA1822: Mark members as static
4-
dotnet_diagnostic.CA1822.severity = suggestion
5-
6-
# CS8603: Possible null reference return.
7-
dotnet_diagnostic.CS8603.severity = none
4+
dotnet_diagnostic.CA1822.severity = suggestion

sample/src/Components/TodoList.razor

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,7 @@
1515
@ItemsTemplate(item);
1616
}
1717
</ol>
18-
19-
@code{
18+
@code {
2019
private ElementReference _inputRef;
2120
private string NewTaskValue { get; set; } = string.Empty;
2221

sample/tests/.editorconfig

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[*.cs]
2+
3+
# CA1822: Mark members as static
4+
dotnet_diagnostic.CA1822.severity = suggestion
5+
6+
# CA1303: Do not pass literals as localized parameters
7+
dotnet_diagnostic.CA1303.severity = none

sample/tests/CodeOnlyTests/CounterTest.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99

1010
namespace Egil.RazorComponents.Testing.Library.SampleApp.CodeOnlyTests
1111
{
12-
public class CounterTest : ComponentFixtureBase
12+
public class CounterTest : ComponentTestBase
1313
{
1414
[Fact]
1515
public void InitialHtmlIsCorrect()
1616
{
17-
var cut = TestHost.AddComponent<Counter>();
17+
var cut = RenderComponent<Counter>();
1818
var expectedHtml = @"<h1>Counter</h1>
1919
<p>Current count: 0</p>
2020
<button class=""btn btn-primary"">Click me</button>";
@@ -28,7 +28,7 @@ public void InitialHtmlIsCorrect()
2828
[InlineData(3, "Current count: 3")]
2929
public void AfterBtnClickCounterIsIncremented(int numberOfClicks, string expectedCountMsg)
3030
{
31-
var cut = TestHost.AddComponent<Counter>();
31+
var cut = RenderComponent<Counter>();
3232

3333
cut.Find("button").Click(numberOfClicks);
3434

@@ -40,7 +40,7 @@ public void AfterBtnClickCounterIsIncremented(int numberOfClicks, string expecte
4040
public void CounterStagesTest()
4141
{
4242
// Initial rendering
43-
var cut = TestHost.AddComponent<Counter>();
43+
var cut = RenderComponent<Counter>();
4444
var expectedHtml = @"<h1>Counter</h1>
4545
<p>Current count: 0</p>
4646
<button class=""btn btn-primary"">Click me</button>";

sample/tests/CodeOnlyTests/FetchDataTest.cs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
namespace Egil.RazorComponents.Testing.Library.SampleApp.CodeOnlyTests
1313
{
14-
public class FetchDataTest : ComponentFixtureBase
14+
public class FetchDataTest : ComponentTestBase
1515
{
1616
class MockForecastService : IWeatherForecastService
1717
{
@@ -23,8 +23,8 @@ class MockForecastService : IWeatherForecastService
2323
[Fact]
2424
public void InitialLoadingHtmlRendersCorrectly()
2525
{
26-
TestHost.AddService<IWeatherForecastService, MockForecastService>();
27-
var cut = TestHost.AddComponent<FetchData>();
26+
Services.AddService<IWeatherForecastService, MockForecastService>();
27+
var cut = RenderComponent<FetchData>();
2828
var initialExpectedHtml = @"<h1>Weather forecast</h1>
2929
<p>This component demonstrates fetching data from a service.</p>
3030
<p><em>Loading...</em></p>";
@@ -37,16 +37,16 @@ public void AfterDataLoadsItIsDisplayedInAForecastTable()
3737
{
3838
// setup mock
3939
var mockForecastService = new MockForecastService();
40-
TestHost.AddService<IWeatherForecastService>(mockForecastService);
40+
Services.AddService<IWeatherForecastService>(mockForecastService);
4141

4242
// arrange
4343
var forecasts = new[] { new WeatherForecast { Date = DateTime.Now, Summary = "Testy", TemperatureC = 42 } };
44-
var cut = TestHost.AddComponent<FetchData>();
44+
var cut = RenderComponent<FetchData>();
4545
var initialHtml = cut.GetMarkup();
46-
var expectedDataTable = TestHost.AddComponent<ForecastDataTable>((nameof(ForecastDataTable.Forecasts), forecasts));
46+
var expectedDataTable = RenderComponent<ForecastDataTable>((nameof(ForecastDataTable.Forecasts), forecasts));
4747

4848
// act
49-
TestHost.WaitForNextRender(() => mockForecastService.Task.SetResult(forecasts));
49+
WaitForNextRender(() => mockForecastService.Task.SetResult(forecasts));
5050

5151
// assert
5252
cut.CompareTo(initialHtml)
@@ -61,15 +61,15 @@ public void AfterDataLoadsItIsDisplayedInAForecastTableChangeTracking()
6161
{
6262
// setup mock
6363
var mockForecastService = new MockForecastService();
64-
TestHost.AddService<IWeatherForecastService>(mockForecastService);
64+
Services.AddService<IWeatherForecastService>(mockForecastService);
6565

6666
// arrange
6767
var forecasts = new[] { new WeatherForecast { Date = DateTime.Now, Summary = "Testy", TemperatureC = 42 } };
68-
var cut = TestHost.AddComponent<FetchData>();
69-
var expectedDataTable = TestHost.AddComponent<ForecastDataTable>((nameof(ForecastDataTable.Forecasts), forecasts));
68+
var cut = RenderComponent<FetchData>();
69+
var expectedDataTable = RenderComponent<ForecastDataTable>((nameof(ForecastDataTable.Forecasts), forecasts));
7070

7171
// act
72-
TestHost.WaitForNextRender(() => mockForecastService.Task.SetResult(forecasts));
72+
WaitForNextRender(() => mockForecastService.Task.SetResult(forecasts));
7373

7474
// assert
7575
cut.GetChangesSinceFirstRender().ShouldHaveChanges(

sample/tests/CodeOnlyTests/TodoItemTest.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,20 @@
1111

1212
namespace Egil.RazorComponents.Testing.Library.SampleApp.CodeOnlyTests
1313
{
14-
public class TodoItemTest : ComponentFixtureBase
14+
public class TodoItemTest : ComponentTestBase
1515
{
1616
[Fact(DisplayName = "When no Todo is passed to item an exception is thrown")]
1717
public void Test001()
1818
{
19-
Should.Throw<ArgumentException>(() => TestHost.AddComponent<TodoItem>());
20-
Should.Throw<InvalidOperationException>(() => TestHost.AddComponent<TodoItem>((nameof(TodoItem.Todo), null)));
19+
Should.Throw<ArgumentException>(() => RenderComponent<TodoItem>());
20+
Should.Throw<InvalidOperationException>(() => RenderComponent<TodoItem>((nameof(TodoItem.Todo), null)));
2121
}
2222

2323
[Fact(DisplayName = "The control renders the expected output")]
2424
public void Test002()
2525
{
2626
var todo = new Todo { Id = 42, Text = "Hello world" };
27-
var cut = TestHost.AddComponent<TodoItem>((nameof(TodoItem.Todo), todo));
27+
var cut = RenderComponent<TodoItem>((nameof(TodoItem.Todo), todo));
2828

2929
cut.ShouldBe($@"<li class=""list-group-item list-group-item-action"">
3030
<span>{todo.Text}</span>
@@ -38,7 +38,7 @@ public void Test003()
3838
var todo = new Todo { Id = 42, Text = "Hello world" };
3939
var completedId = 0;
4040
var onCompleteHandler = EventCallback.Factory.Create(this, (int id) => completedId = id);
41-
var cut = TestHost.AddComponent<TodoItem>(
41+
var cut = RenderComponent<TodoItem>(
4242
(nameof(TodoItem.Todo), todo),
4343
(nameof(TodoItem.OnCompleted), onCompleteHandler)
4444
);
Lines changed: 81 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
using Egil.RazorComponents.Testing.Library.SampleApp.Components;
1+
using AngleSharp.Dom;
2+
using Egil.RazorComponents.Testing.Library.SampleApp.Components;
23
using Egil.RazorComponents.Testing.Library.SampleApp.Data;
4+
using Egil.RazorComponents.Testing.Mocking.JSInterop;
35
using Microsoft.AspNetCore.Components;
46
using Microsoft.JSInterop;
7+
using Shouldly;
58
using System;
69
using System.Collections.Generic;
710
using System.Linq;
@@ -11,7 +14,7 @@
1114

1215
namespace Egil.RazorComponents.Testing.Library.SampleApp.CodeOnlyTests
1316
{
14-
public class TodoListTest : ComponentFixtureBase
17+
public class TodoListTest : ComponentTestBase
1518
{
1619
private string GetExpectedHtml(string label = "Task description", string itemsHtml = "") =>
1720
$@"<form>
@@ -28,43 +31,108 @@ private string GetExpectedHtml(string label = "Task description", string itemsHt
2831
[Fact(DisplayName = "Task list renders as empty with default html when no items is provided")]
2932
public void Test001()
3033
{
31-
TestHost.AddMockJsRuntime();
32-
var cut = TestHost.AddComponent<TodoList>();
34+
// arrange
35+
Services.AddMockJsRuntime();
36+
37+
// act
38+
var cut = RenderComponent<TodoList>();
3339

40+
// assert
3441
cut.ShouldBe(GetExpectedHtml());
3542
}
3643

3744
[Fact(DisplayName = "Task list with custom label renders correctly")]
3845
public void Test002()
3946
{
40-
TestHost.AddMockJsRuntime();
47+
// arrange
48+
Services.AddMockJsRuntime();
4149
var label = "hello world";
42-
var cut = TestHost.AddComponent<TodoList>((nameof(TodoList.Label), label));
4350

51+
// act
52+
var cut = RenderComponent<TodoList>((nameof(TodoList.Label), label));
53+
54+
// assert
4455
cut.ShouldBe(GetExpectedHtml(label: label));
4556
}
4657

4758
[Fact(DisplayName = "Task list renders Items using ItemTemplate")]
4859
public void Test003()
4960
{
5061
// arrange
51-
TestHost.AddMockJsRuntime();
62+
Services.AddMockJsRuntime();
63+
RenderFragment<Todo> itemTemplate = todo => builder => builder.AddMarkupContent(0, $"<li>{todo.Id}</li>");
5264
var items = new[] { new Todo { Id = 42 }, new Todo { Id = 1337 } };
5365

5466
// act
55-
var cut = TestHost.AddComponent<TodoList>(
67+
var cut = RenderComponent<TodoList>(
5668
(nameof(TodoList.Items), items),
57-
(nameof(TodoList.ItemsTemplate), GetItemTemplate())
69+
(nameof(TodoList.ItemsTemplate), itemTemplate)
5870
);
5971

6072
// assert
6173
var expectedHtml = GetExpectedHtml(itemsHtml: $"<li>{items[0].Id}</li><li>{items[1].Id}</li>");
6274
cut.ShouldBe(expectedHtml);
75+
}
76+
77+
[Fact(DisplayName = "After first render, the new task input field has focus")]
78+
public void Test004()
79+
{
80+
// arrange
81+
var jsRtMock = Services.AddMockJsRuntime();
82+
83+
// act
84+
var cut = RenderComponent<TodoList>();
85+
86+
// assert that there is a call to document.body.focus.call with a single argument,
87+
// a reference to the input element.
88+
jsRtMock.VerifyInvoke("document.body.focus.call")
89+
.Arguments.Single().ShouldBeElementReferenceTo(cut.Find("input"));
90+
}
91+
92+
[Fact(DisplayName = "The new task input field does not receive focus explicitly after second and later renders")]
93+
public void Test0041()
94+
{
95+
// arrange
96+
var jsRtMock = Services.AddMockJsRuntime();
97+
98+
// act
99+
var cut = RenderComponent<TodoList>(); // first render
100+
cut.Render(); // second render
101+
102+
// assert
103+
jsRtMock.VerifyInvoke("document.body.focus.call", calledTimes: 1);
104+
}
105+
106+
107+
[Fact(DisplayName = "When a text entered in the add task input field and the form is submitted, " +
108+
"the OnAddingTodo is raised with a new Todo containing the entered text")]
109+
public void Test005()
110+
{
111+
var jsRtMock = Services.AddMockJsRuntime();
112+
var taskValue = "HELLO WORLD TASK";
113+
var createdTask = default(Todo);
114+
var cut = RenderComponent<TodoList>(
115+
(nameof(TodoList.OnAddingTodo), EventCallback.Factory.Create<Todo>(this, task => createdTask = task))
116+
);
117+
118+
cut.Find("input").Change(taskValue);
119+
cut.Find("form").Submit();
120+
121+
createdTask.ShouldNotBeNull().Text.ShouldBe(taskValue);
122+
}
123+
124+
[Fact(DisplayName = "When add task form is submitted with no text OnAddingTodo is not called")]
125+
public void Test006()
126+
{
127+
var jsRtMock = Services.AddMockJsRuntime();
128+
var createdTask = default(Todo);
129+
var cut = RenderComponent<TodoList>(
130+
(nameof(TodoList.OnAddingTodo), EventCallback.Factory.Create<Todo>(this, task => createdTask = task))
131+
);
132+
133+
cut.Find("form").Submit();
63134

64-
RenderFragment<Todo> GetItemTemplate()
65-
{
66-
return todo => builder => builder.AddMarkupContent(0, $"<li>{todo.Id}</li>");
67-
}
135+
createdTask.ShouldBeNull();
68136
}
69137
}
70138
}

src/AssertHelpers/DiffExtensions.cs

Lines changed: 0 additions & 64 deletions
This file was deleted.

0 commit comments

Comments
 (0)