Skip to content

Commit 0c13f66

Browse files
authored
Update README.md
1 parent 3c9dc27 commit 0c13f66

File tree

1 file changed

+212
-2
lines changed

1 file changed

+212
-2
lines changed

README.md

Lines changed: 212 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ This is still early days for the library and nothing is set in stone with regard
1212
If you have an idea, suggestion, or bug, please add an [issue](issues). Pull-requests are also very welcome.
1313

1414
## Getting started
15+
1. Create the necessary projects (Razor Class Library and xUnit class Library). See the [sample project](master/sample) for an example.
1516
1. Install the [Razor.Components.Testing.Library](https://www.nuget.org/packages/Razor.Components.Testing.Library) library from Nuget into your xUnit test project.
1617
2. Optionally, add an `_Imports.razor` to test project to avoid typing using and inherits statements in each test files.
1718
3. Write `.razor`-based tests.
@@ -29,6 +30,215 @@ If you have an idea, suggestion, or bug, please add an [issue](issues). Pull-req
2930
```
3031

3132
## Example
32-
The test examples below tests the Bootstrap [`Alert`](sample/ComponentLib/Alert.razor) sample component found in the sample folder:
33+
The test examples below tests the Bootstrap [`Alert.razor`](sample/ComponentLib/Alert.razor) sample component, using the [`AlertTests.razor`](sample/RazorComponentLibTests/AlertTests.razor), both found in the sample folder.
3334

34-
https://github.com/egil/razor-component-testing-library/blob/7b018f1bdd358d786df003a83ac6721be211385e/sample/ComponentLib/Alert.razor#L1
35+
### Component under test
36+
```cshtml
37+
@code {
38+
[Parameter]
39+
public RenderFragment? ChildContent { get; set; }
40+
41+
[Parameter]
42+
public string? Class { get; set; }
43+
44+
[Parameter]
45+
public string? Color { get; set; }
46+
47+
[Parameter]
48+
public bool Dismissable { get; set; } = false;
49+
50+
[Parameter]
51+
public string Role { get; set; } = "alert";
52+
53+
[Parameter]
54+
public bool Visible { get; set; } = true;
55+
56+
private string CssClass
57+
{
58+
get
59+
{
60+
var cssClass = "alert fade";
61+
62+
if(Visible)
63+
cssClass = $"{cssClass} show";
64+
65+
if (Color != null)
66+
cssClass = $"{cssClass} alert-{Color}";
67+
68+
if (Dismissable)
69+
cssClass = $"{cssClass} alert-dismissible";
70+
71+
if (Class != null)
72+
cssClass = $"{cssClass} {Class}";
73+
74+
return cssClass;
75+
}
76+
}
77+
}
78+
<div class=@CssClass role=@Role>
79+
@if (Visible)
80+
{
81+
@if (ChildContent != null)
82+
{
83+
@ChildContent
84+
}
85+
@if (Dismissable)
86+
{
87+
<button type="button" class="close" aria-label="Close">
88+
<span aria-hidden="true">&amp;times;</span>
89+
</button>
90+
}
91+
}
92+
</div>
93+
```
94+
95+
### Simple tests
96+
To perform a simple comparison test between the HTML generated by the `<Alert />` component, add a `<Fact />` component to your `.razor`-test-file, include the `<TestSetup>` component, that should contain the setup of the component under test, and an `<ExpectedHtml/>` component that contains the expected output.
97+
98+
E.g.:
99+
100+
```
101+
<Fact DisplayName="Alert renders as empty without child content">
102+
<TestSetup>
103+
<Alert />
104+
</TestSetup>
105+
<ExpectedHtml>
106+
<div class="alert fade show" role="alert"></div>
107+
</ExpectedHtml>
108+
</Fact>
109+
110+
<Fact DisplayName="Alert renders with child content if provided">
111+
<TestSetup>
112+
<Alert>FOO BAR BAZ</Alert>
113+
</TestSetup>
114+
<ExpectedHtml>
115+
<div class="alert fade show" role="alert">FOO BAR BAZ</div>
116+
</ExpectedHtml>
117+
</Fact>
118+
119+
<Fact DisplayName="Alert adds color when specified">
120+
<TestSetup>
121+
<Alert Color="primary" />
122+
</TestSetup>
123+
<ExpectedHtml>
124+
<div class="alert fade show alert-primary" role="alert"></div>
125+
</ExpectedHtml>
126+
</Fact>
127+
128+
<Fact DisplayName="Providing a role overrides default role value">
129+
<TestSetup>
130+
<Alert Role="banner" />
131+
</TestSetup>
132+
<ExpectedHtml>
133+
<div class="alert fade show" role="banner"></div>
134+
</ExpectedHtml>
135+
</Fact>
136+
137+
<Fact DisplayName="Setting Dismisasable to true renderes dismiss button below child content">
138+
<TestSetup>
139+
<Alert Dismissable>
140+
<strong>Holy guacamole!</strong> You should check in on some of those fields below.
141+
</Alert>
142+
</TestSetup>
143+
<ExpectedHtml>
144+
<div class="alert fade show alert-dismissible" role="alert">
145+
<strong>Holy guacamole!</strong> You should check in on some of those fields below.
146+
<button type="button" class="close" aria-label="Close">
147+
<span aria-hidden="true">&amp;times;</span>
148+
</button>
149+
</div>
150+
</ExpectedHtml>
151+
</Fact>
152+
```
153+
154+
**NOTE:** In the future, the 'DisplayName' attribute will be displayed by the test-runner.
155+
156+
### Custom tests
157+
If you want more control over the assertion, use a `<HtmlSnippet/>` component instead of a
158+
`<ExpectedHtml/>` component. Then the default unit test will not run, and you can add your
159+
own, where you can access the `RenderResults` property and do any comparison of the HTML (XML)
160+
you want.
161+
162+
```cshtml
163+
@code {
164+
[Fact]
165+
public void A_Custom_Test()
166+
{
167+
// assert
168+
var result = RenderResults.Single(x => x.Id == (nameof(A_Custom_Test)));
169+
result.RenderedHtml.ShouldBe(result.Snippets.First());
170+
}
171+
}
172+
<Fact Id=@nameof(A_Custom_Test)>
173+
<TestSetup>
174+
<Alert Role="banner" Color="secondary" class="my-custom-class" Dismissable>
175+
<strong>Holy guacamole!</strong> You should check in on some of those fields below.
176+
</Alert>
177+
</TestSetup>
178+
<HtmlSnippet>
179+
<div class="alert fade show alert-secondary alert-dismissible my-custom-class" role="banner">
180+
<strong>Holy guacamole!</strong> You should check in on some of those fields below.
181+
<button type="button" class="close" aria-label="Close">
182+
<span aria-hidden="true">&amp;times;</span>
183+
</button>
184+
</div>
185+
</HtmlSnippet>
186+
</Fact>
187+
```
188+
189+
If you want to assert directly on the rendered component or change its parameters
190+
and re-render, use the component reference syntax (`@ref`). The `Render` method allows
191+
you to trigger a re-render manually, on-demand.
192+
193+
```cshtml
194+
@code {
195+
Alert sut;
196+
bool isVisible = true;
197+
198+
[Fact(DisplayName = "When Visible is toggled to false, all child content is removed from alert")]
199+
public void DismissTest()
200+
{
201+
// initial assert
202+
var result = RenderResults.Single(x => x.Id == (nameof(DismissTest)));
203+
result.RenderedHtml.ShouldBe(result.Snippets[0]);
204+
sut.Visible.ShouldBeTrue();
205+
206+
// act
207+
isVisible = false;
208+
this.Render();
209+
210+
// dismiss assert
211+
var dismissResult = RenderResults.Single(x => x.Id == (nameof(DismissTest)));
212+
dismissResult.RenderedHtml.ShouldBe(result.Snippets[1]);
213+
sut.Visible.ShouldBeFalse();
214+
}
215+
}
216+
<Fact Id=@nameof(DismissTest)>
217+
<TestSetup>
218+
<Alert @ref="sut" Visible=@isVisible>
219+
<strong>Holy guacamole!</strong> You should check in on some of those fields below.
220+
</Alert>
221+
</TestSetup>
222+
<HtmlSnippet>
223+
<div class="alert fade show" role="alert">
224+
<strong>Holy guacamole!</strong> You should check in on some of those fields below.
225+
</div>
226+
</HtmlSnippet>
227+
<HtmlSnippet>
228+
<div class="alert fade" role="alert"></div>
229+
</HtmlSnippet>
230+
</Fact>
231+
```
232+
233+
### Injecting services
234+
If the component under test needs access to services, those can be injected by
235+
overriding the `AddServices` method. E.g.:
236+
237+
```cshtml
238+
@code {
239+
protected override void AddServices(IServiceCollection services)
240+
{
241+
services.AddScoped<IJSRuntime>(_ => Mock.Of<IJSRuntime>());
242+
}
243+
}
244+
```

0 commit comments

Comments
 (0)