Skip to content

Commit 1c607c0

Browse files
committedJul 25, 2020
Changed approval tests to shouldly should match approved to avoid weird errors
Fixed problem with changing context tests - split out html helpers and tag helpers
1 parent 939abbd commit 1c607c0

15 files changed

+145
-58
lines changed
 

‎ChameleonForms.AcceptanceTests/ChameleonForms.AcceptanceTests.csproj

-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
<ItemGroup>
1212
<PackageReference Include="AngleSharp" Version="0.14.0" />
1313
<PackageReference Include="AngleSharp.Io" Version="0.14.0" />
14-
<PackageReference Include="ApprovalTests" Version="3.0.18" />
1514
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.3" />
1615
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
1716
<PackageReference Include="Shouldly" Version="3.0.2" />

‎ChameleonForms.AcceptanceTests/IntegrationTests/ChangingContextTests.cs

+36
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,41 @@ public async Task Post_child_view_model_and_bind_to_parent_on_postback()
5656
IsSame.ViewModelAs(enteredViewModel, page.ReadParentModel());
5757
page.HasValidationErrors().ShouldBeFalse();
5858
}
59+
60+
[Fact]
61+
public async Task Post_different_view_model_and_bind_on_postback_taghelpers()
62+
{
63+
var enteredViewModel = ObjectMother.ChangingContextViewModels.DifferentViewModel;
64+
65+
var page = await _client.GetPageAsync<ChangingContextPage>("/ExampleForms/ChangingContextTH");
66+
page = await page.PostDifferentModelAsync(enteredViewModel); ;
67+
68+
IsSame.ViewModelAs(enteredViewModel, page.ReadDifferentModel());
69+
page.HasValidationErrors().ShouldBeFalse();
70+
}
71+
72+
[Fact]
73+
public async Task Post_child_view_model_and_bind_on_postback_taghelpers()
74+
{
75+
var enteredViewModel = ObjectMother.ChangingContextViewModels.ChildViewModel;
76+
77+
var page = await _client.GetPageAsync<ChangingContextPage>("/ExampleForms/ChangingContextTH");
78+
page = await page.PostChildModelAsync(enteredViewModel);
79+
80+
IsSame.ViewModelAs(enteredViewModel, page.ReadChildModel());
81+
page.HasValidationErrors().ShouldBeFalse();
82+
}
83+
84+
[Fact]
85+
public async Task Post_child_view_model_and_bind_to_parent_on_postback_taghelpers()
86+
{
87+
var enteredViewModel = ObjectMother.ChangingContextViewModels.ParentViewModel;
88+
89+
var page = await _client.GetPageAsync<ChangingContextPage>("/ExampleForms/ChangingContextTH");
90+
page = await page.PostParentModelAsync(enteredViewModel);
91+
92+
IsSame.ViewModelAs(enteredViewModel, page.ReadParentModel());
93+
page.HasValidationErrors().ShouldBeFalse();
94+
}
5995
}
6096
}

‎ChameleonForms.AcceptanceTests/IntegrationTests/PartialForTests.Should_render_correctly_when_used_via_form_or_section_and_when_used_for_top_level_property_or_sub_property.approved.html

+2-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ <h1>Partials</h1>
1010

1111
@using (var f = Html.BeginChameleonForm())
1212
{
13-
@Html.Partial("_ParentPartial")
13+
@await Html.PartialAsync("_ParentPartial")
1414
@(await Html.PartialAsync("_BaseParentPartial"))
1515
@(await f.PartialForAsync(m => m.Child, "_ChildPartial"))
1616
@(await f.PartialForAsync(m => m.BaseChild, "_BaseChildPartial"))
@@ -209,4 +209,5 @@ <h1>Partials</h1>
209209
</fieldset>
210210
<div class="form_navigation">
211211
<button type="submit">Submit</button> </div>
212+
<input name="__RequestVerificationToken" type="hidden" value="...">
212213
</form>

‎ChameleonForms.AcceptanceTests/IntegrationTests/PartialForTests.Should_render_correctly_when_used_via_form_or_section_and_when_used_for_top_level_property_or_sub_property_via_tag_helpers.approved.html

+1
Original file line numberDiff line numberDiff line change
@@ -226,4 +226,5 @@ <h1>Partials - Tag Helpers</h1>
226226
<button type="submit">Submit</button>
227227
</div>
228228

229+
<input name="__RequestVerificationToken" type="hidden" value="...">
229230
</form>

‎ChameleonForms.AcceptanceTests/IntegrationTests/PartialForTests.cs

+7-5
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,16 @@
22
using System.Net.Http;
33
using System.Text.RegularExpressions;
44
using System.Threading.Tasks;
5-
using ApprovalTests.Html;
6-
using ApprovalTests.Reporters;
75
using ChameleonForms.AcceptanceTests.Helpers;
86
using Microsoft.AspNetCore.Mvc.Testing;
7+
using Shouldly;
98
using Xunit;
109

1110
namespace ChameleonForms.AcceptanceTests.IntegrationTests
1211
{
1312
/// <summary>
1413
/// Loading partial views is very difficult to test by unit testing.
1514
/// </summary>
16-
[UseReporter(typeof(DiffReporter))]
1715
public class PartialForTests : IClassFixture<WebApplicationFactory<Example.Startup>>
1816
{
1917
private readonly HttpClient _client;
@@ -33,14 +31,18 @@ public PartialForTests(WebApplicationFactory<Example.Startup> factory)
3331
public async Task Should_render_correctly_when_used_via_form_or_section_and_when_used_for_top_level_property_or_sub_property()
3432
{
3533
var renderedSource = await GetRenderedSourceAsync("/ExampleForms/Partials");
36-
HtmlApprovals.VerifyHtml($"Partials.cshtml\r\n\r\n{GetViewContents("Partials")}\r\n=====\r\n\r\n_ParentPartial.cshtml\r\n\r\n{GetViewContents("_ParentPartial")}\r\n=====\r\n\r\n_ChildPartial.cshtml\r\n\r\n{GetViewContents("_ChildPartial")}\r\n=====\r\n\r\n_BaseParentPartial.cshtml\r\n\r\n{GetViewContents("_BaseParentPartial")}\r\n=====\r\n\r\n_BaseChildPartial.cshtml\r\n\r\n{GetViewContents("_BaseChildPartial")}\r\n=====\r\n\r\nRendered Source\r\n\r\n{renderedSource}");
34+
var received = $"Partials.cshtml\r\n\r\n{GetViewContents("Partials")}\r\n=====\r\n\r\n_ParentPartial.cshtml\r\n\r\n{GetViewContents("_ParentPartial")}\r\n=====\r\n\r\n_ChildPartial.cshtml\r\n\r\n{GetViewContents("_ChildPartial")}\r\n=====\r\n\r\n_BaseParentPartial.cshtml\r\n\r\n{GetViewContents("_BaseParentPartial")}\r\n=====\r\n\r\n_BaseChildPartial.cshtml\r\n\r\n{GetViewContents("_BaseChildPartial")}\r\n=====\r\n\r\nRendered Source\r\n\r\n{renderedSource}";
35+
received = received.SanitiseRequestVerificationToken();
36+
received.ShouldMatchApproved(b => b.WithFileExtension(".html"));
3737
}
3838

3939
[Fact]
4040
public async Task Should_render_correctly_when_used_via_form_or_section_and_when_used_for_top_level_property_or_sub_property_via_tag_helpers()
4141
{
4242
var renderedSource = await GetRenderedSourceAsync("/ExampleForms/PartialsTH");
43-
HtmlApprovals.VerifyHtml($"PartialsTH.cshtml\r\n\r\n{GetViewContents("PartialsTH")}\r\n=====\r\n\r\n_ParentPartialTH.cshtml\r\n\r\n{GetViewContents("_ParentPartialTH")}\r\n=====\r\n\r\n_ChildPartialTH.cshtml\r\n\r\n{GetViewContents("_ChildPartialTH")}\r\n=====\r\n\r\n_BaseParentPartialTH.cshtml\r\n\r\n{GetViewContents("_BaseParentPartialTH")}\r\n=====\r\n\r\n_BaseChildPartialTH.cshtml\r\n\r\n{GetViewContents("_BaseChildPartialTH")}\r\n=====\r\n\r\nRendered Source\r\n\r\n{renderedSource}");
43+
var received = $"PartialsTH.cshtml\r\n\r\n{GetViewContents("PartialsTH")}\r\n=====\r\n\r\n_ParentPartialTH.cshtml\r\n\r\n{GetViewContents("_ParentPartialTH")}\r\n=====\r\n\r\n_ChildPartialTH.cshtml\r\n\r\n{GetViewContents("_ChildPartialTH")}\r\n=====\r\n\r\n_BaseParentPartialTH.cshtml\r\n\r\n{GetViewContents("_BaseParentPartialTH")}\r\n=====\r\n\r\n_BaseChildPartialTH.cshtml\r\n\r\n{GetViewContents("_BaseChildPartialTH")}\r\n=====\r\n\r\nRendered Source\r\n\r\n{renderedSource}";
44+
received = received.SanitiseRequestVerificationToken();
45+
received.ShouldMatchApproved(b => b.WithFileExtension(".html"));
4446
}
4547

4648
private async Task<string> GetRenderedSourceAsync(string url)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System.Text.RegularExpressions;
2+
3+
namespace ChameleonForms.AcceptanceTests.IntegrationTests
4+
{
5+
public static class StringExtensions
6+
{
7+
private static readonly Regex RequestVerificationToken = new Regex("<input name=\"__RequestVerificationToken\" type=\"hidden\" value=\".+?\">", RegexOptions.IgnoreCase);
8+
9+
public static string SanitiseRequestVerificationToken(this string html)
10+
{
11+
return RequestVerificationToken.Replace(html, "<input name=\"__RequestVerificationToken\" type=\"hidden\" value=\"...\">");
12+
}
13+
}
14+
}

‎ChameleonForms.AcceptanceTests/IntegrationTests/TagHelperTests.Should_render_correctly.approved.html

+3-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ <h1>ChameleonForms TagHelpers example</h1>
2727

2828
<form-section heading="Additional details">
2929
<field for="Bio" />
30-
<field for="Homepage" placeholder="http://" />
30+
<field for="Homepage" placeholder="https://" />
3131
</form-section>
3232

3333
<form-message type="Action" heading="Confirm the Terms & Conditions">
@@ -119,7 +119,7 @@ <h3>Signup for an account</h3>
119119

120120
<dt><label for="Homepage">Homepage</label></dt>
121121
<dd>
122-
<input id="Homepage" name="Homepage" placeholder="http://" type="url" value=""> <span class="field-validation-valid" data-valmsg-for="Homepage" data-valmsg-replace="true"></span>
122+
<input id="Homepage" name="Homepage" placeholder="https://" type="url" value=""> <span class="field-validation-valid" data-valmsg-for="Homepage" data-valmsg-replace="true"></span>
123123
</dd>
124124

125125
</dl>
@@ -144,4 +144,5 @@ <h3>Confirm the Terms &amp; Conditions</h3>
144144
<button class="btn-primary" type="submit">Signup</button>
145145
</div>
146146

147+
<input name="__RequestVerificationToken" type="hidden" value="...">
147148
</form>

‎ChameleonForms.AcceptanceTests/IntegrationTests/TagHelperTests.cs

+4-4
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,13 @@
22
using System.Net.Http;
33
using System.Text.RegularExpressions;
44
using System.Threading.Tasks;
5-
using ApprovalTests.Html;
6-
using ApprovalTests.Reporters;
75
using ChameleonForms.AcceptanceTests.Helpers;
86
using Microsoft.AspNetCore.Mvc.Testing;
7+
using Shouldly;
98
using Xunit;
109

1110
namespace ChameleonForms.AcceptanceTests.IntegrationTests
1211
{
13-
[UseReporter(typeof(DiffReporter))]
1412
public class TagHelperTests : IClassFixture<WebApplicationFactory<Example.Startup>>
1513
{
1614
private readonly HttpClient _client;
@@ -30,7 +28,9 @@ public TagHelperTests(WebApplicationFactory<Example.Startup> factory)
3028
public async Task Should_render_correctly()
3129
{
3230
var renderedSource = await GetRenderedSourceAsync("/Comparison/ChameleonFormsTH");
33-
HtmlApprovals.VerifyHtml($"ChameleonFormsTH.cshtml\r\n\r\n{GetViewContents("Comparison/ChameleonFormsTH")}\r\n=====\r\n\r\nRendered Source\r\n\r\n{renderedSource}");
31+
var received = $"ChameleonFormsTH.cshtml\r\n\r\n{GetViewContents("Comparison/ChameleonFormsTH")}\r\n=====\r\n\r\nRendered Source\r\n\r\n{renderedSource}";
32+
received = received.SanitiseRequestVerificationToken();
33+
received.ShouldMatchApproved(b => b.WithFileExtension(".html"));
3434
}
3535

3636
private async Task<string> GetRenderedSourceAsync(string url)

‎ChameleonForms.Example/Controllers/ExampleFormsController.cs

+11-6
Original file line numberDiff line numberDiff line change
@@ -116,34 +116,39 @@ public ActionResult ChangingContext()
116116
return View(new ParentViewModel{Child = new ChildViewModel { ChildField = "Initial value from controller"}});
117117
}
118118

119+
public ActionResult ChangingContextTH()
120+
{
121+
return View(new ParentViewModel { Child = new ChildViewModel { ChildField = "Initial value from controller" } });
122+
}
123+
119124
[HttpPost]
120-
public ActionResult PostDifferentModel(BasicViewModel vm)
125+
public ActionResult PostDifferentModel(BasicViewModel vm, bool tagHelpers)
121126
{
122127
ViewBag.Action = "PostDifferentModel";
123128
ViewBag.ModelType = vm.GetType().Name;
124129
ViewBag.BoundModelData = JsonSerializer.Serialize(vm, new JsonSerializerOptions{WriteIndented = true});
125130
ViewBag.BoundModel = vm;
126-
return View("ChangingContext");
131+
return View(tagHelpers ? "ChangingContextTH" : "ChangingContext");
127132
}
128133

129134
[HttpPost]
130-
public ActionResult PostChildViewModel(ChildViewModel vm)
135+
public ActionResult PostChildViewModel(ChildViewModel vm, bool tagHelpers)
131136
{
132137
ViewBag.Action = "PostChildViewModel";
133138
ViewBag.ModelType = vm.GetType().Name;
134139
ViewBag.BoundModelData = JsonSerializer.Serialize(vm, new JsonSerializerOptions { WriteIndented = true });
135140
ViewBag.BoundModel = vm;
136-
return View("ChangingContext");
141+
return View(tagHelpers ? "ChangingContextTH" : "ChangingContext");
137142
}
138143

139144
[HttpPost]
140-
public ActionResult PostParentViewModel(ParentViewModel vm)
145+
public ActionResult PostParentViewModel(ParentViewModel vm, bool tagHelpers)
141146
{
142147
ViewBag.Action = "PostParentViewModel";
143148
ViewBag.ModelType = vm.GetType().Name;
144149
ViewBag.BoundModelData = JsonSerializer.Serialize(vm, new JsonSerializerOptions { WriteIndented = true });
145150
ViewBag.BoundModel = vm;
146-
return View("ChangingContext");
151+
return View(tagHelpers ? "ChangingContextTH" : "ChangingContext");
147152
}
148153
}
149154

‎ChameleonForms.Example/Views/ExampleForms/ChangingContext.cshtml

+6-31
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@
55
var differentViewModel = new BasicViewModel { RequiredString = "Initial value" };
66
}
77

8-
<h1>Changing the context of HTML helper</h1>
8+
<h1>Changing the context of HTML helper - HTML Helpers</h1>
9+
10+
<p><a asp-action="ChangingContextTH">Tag Helpers</a>.</p>
911

1012
<p>There are three separate forms tied to three different post actions. Turn off JavaScript, clear all the text fields and hit each of the three submit buttons and also play with putting in values and submitting the values to see how they are bound back.</p>
1113

@@ -23,13 +25,7 @@
2325
</ul>
2426
}
2527

26-
<h2>Completely different model - Tag Helpers</h2>
27-
28-
<p><code>&lt;partial name="_FormAgainstDifferentModel" model="differentViewModel" /&gt;</code></p>
29-
30-
<partial name="_FormAgainstDifferentModel" model="differentViewModel" />
31-
32-
<h2>Completely different model - HTML Helpers</h2>
28+
<h2>Completely different model</h2>
3329

3430
<p><code>@@using (var f = Html.BeginChameleonFormFor(new BasicViewModel { RequiredString = "Initial value" }, Url.Action("PostDifferentModel")))</code></p>
3531

@@ -46,13 +42,7 @@
4642
}
4743
}
4844

49-
<h2>Sub model (binding to itself) - Tag Helpers</h2>
50-
51-
<p><code>&lt;partial name="_FormAgainstChildProperty" for="Child" /&gt;</code></p>
52-
53-
<partial name="_FormAgainstChildProperty" for="Child" />
54-
55-
<h2>Sub model (binding to itself) - HTML Helpers</h2>
45+
<h2>Sub model (binding to itself)</h2>
5646

5747
<p><code>@@using (var f = Html.BeginChameleonFormFor(m => m.Child, Url.Action("PostChildViewModel")))</code></p>
5848

@@ -69,22 +59,7 @@
6959
}
7060
}
7161

72-
73-
<h2>Sub model (binding to parent) - Tag Helpers</h2>
74-
75-
<p><code>&lt;form-partial name="_FormPartialAgainstChildProperty" for="Child" /&gt;</code></p>
76-
77-
<chameleon-form action="@Url.Action("PostParentViewModel")">
78-
79-
<form-partial name="_FormPartialAgainstChildProperty" for="Child" />
80-
81-
<form-navigation>
82-
<submit-button label="Submit" add-class="parent-model" />
83-
</form-navigation>
84-
85-
</chameleon-form>
86-
87-
<h2>Sub model (binding to parent) - HTML Helpers</h2>
62+
<h2>Sub model (binding to parent)</h2>
8863

8964
<p><code>@@using (var f = Html.For(m => m.Child, bindFieldsToParent: true).BeginChameleonForm(Url.Action("PostParentViewModel")))</code></p>
9065

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
@model ParentViewModel
2+
3+
@{
4+
ViewBag.Title = "Changing context";
5+
var differentViewModel = new BasicViewModel { RequiredString = "Initial value" };
6+
}
7+
8+
<h1>Changing the context of the model - Tag Helpers</h1>
9+
10+
<p><a asp-action="ChangingContext">HTML Helpers</a>.</p>
11+
12+
<p>There are three separate forms tied to three different post actions. Turn off JavaScript, clear all the text fields and hit each of the three submit buttons and also play with putting in values and submitting the values to see how they are bound back.</p>
13+
14+
@if (Context.Request.Method.ToUpperInvariant() == "POST")
15+
{
16+
if (ViewBag.Action == "PostDifferentModel")
17+
{
18+
differentViewModel = ViewBag.BoundModel;
19+
}
20+
<h2>Binding data</h2>
21+
<ul>
22+
<li><strong>Action:</strong> @ViewBag.Action</li>
23+
<li><strong>Model type:</strong> @ViewBag.ModelType</li>
24+
<li><strong>Model data:</strong> <pre>@ViewBag.BoundModelData</pre></li>
25+
</ul>
26+
}
27+
28+
<h2>Completely different model</h2>
29+
30+
<p><code>&lt;partial name="_FormAgainstDifferentModel" model="differentViewModel" /&gt;</code></p>
31+
32+
<partial name="_FormAgainstDifferentModel" model="differentViewModel" />
33+
34+
<h2>Sub model (binding to itself)</h2>
35+
36+
<p><code>&lt;partial name="_FormAgainstChildProperty" model="Model?.Child" /&gt;</code></p>
37+
38+
<partial name="_FormAgainstChildProperty" model="Model?.Child" />
39+
40+
<h2>Sub model (binding to parent)</h2>
41+
42+
<p><code>&lt;form-partial name="_FormPartialAgainstChildProperty" for="Child" /&gt;</code></p>
43+
44+
<chameleon-form action="@Url.Action("PostParentViewModel")?tagHelpers=true">
45+
46+
<form-partial name="_FormPartialAgainstChildProperty" for="Child"/>
47+
48+
<form-navigation>
49+
<submit-button label="Submit" add-class="parent-model"/>
50+
</form-navigation>
51+
52+
</chameleon-form>

‎ChameleonForms.Example/Views/ExampleForms/_FormAgainstChildProperty.cshtml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
@model ChildViewModel
22

3-
<chameleon-form action="@Url.Action("PostChildViewModel")">
3+
<chameleon-form action="@Url.Action("PostChildViewModel")?tagHelpers=true">
44
<form-section>
55
<field for="ChildField" />
66
<field for="SomeEnum" />
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
@model BasicViewModel
22

3-
<chameleon-form action="@Url.Action("PostDifferentModel")">
3+
<chameleon-form action="@Url.Action("PostDifferentModel")?tagHelpers=true">
44
<form-section>
5-
<field for="RequiredString" />
6-
<field for="SomeCheckbox" />
5+
<field for="RequiredString"/>
6+
<field for="SomeCheckbox"/>
77
</form-section>
88
<form-navigation>
9-
<submit-button add-class="different-model" label="Submit" />
9+
<submit-button add-class="different-model" label="Submit"/>
1010
</form-navigation>
1111
</chameleon-form>

‎ChameleonForms.Example/Views/Home/Index.cshtml

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@
3333
<li>@Html.ActionLink("Null list", "NullList", "ExampleForms")</li>
3434
<li>@Html.ActionLink("Buttons", "Buttons", "ExampleForms")</li>
3535
<li>@Html.ActionLink("Partials", "Partials", "ExampleForms") | @Html.ActionLink("Partials - Tag Helpers", "PartialsTH", "ExampleForms")</li>
36-
<li>@Html.ActionLink("Changing HTML Helper context", "ChangingContext", "ExampleForms")</li>
36+
<li>@Html.ActionLink("Changing model context - HTML Helpers", "ChangingContext", "ExampleForms")</li>
37+
<li>@Html.ActionLink("Changing model context - Tag Helpers", "ChangingContextTH", "ExampleForms")</li>
3738
</ul>
3839

3940
<h2>Random forms and UI tests</h2>

‎docs/different-form-models.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ Tag Helpers are explicitly tied to the model of the page so it's not possible to
190190
@model SomeViewModel
191191
192192
<h1>Creating new xyz against @Model.ReadonlyProperty</h1>
193-
<partial name="_SomeViewModelInputForm" for="InputModel" />
193+
<partial name="_SomeViewModelInputForm" model="Model?.InputModel" />
194194
```
195195

196196
*_SomeViewModelInputForm.cshtml*
@@ -272,4 +272,4 @@ This is still easily possible, but it's just a little more verbose since it's li
272272

273273
## Try working examples
274274

275-
See also the working examples in the [source code](https://github.com/MRCollective/ChameleonForms/blob/master/ChameleonForms.Example/Views/ExampleForms/ChangingContext.cshtml), which can be run so you can see how it works.
275+
See also the working examples in the [source](https://github.com/MRCollective/ChameleonForms/blob/master/ChameleonForms.Example/Views/ExampleForms/ChangingContextTH.cshtml) [code](https://github.com/MRCollective/ChameleonForms/blob/master/ChameleonForms.Example/Views/ExampleForms/ChangingContext.cshtml), which can be run so you can see how it works.

0 commit comments

Comments
 (0)
Please sign in to comment.