Skip to content

Commit 35c4e33

Browse files
csharpfritzCopilot
andcommitted
test: add Playwright integration tests for Request.Form demo
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 0b8d18c commit 35c4e33

2 files changed

Lines changed: 169 additions & 0 deletions

File tree

samples/AfterBlazorServerSide.Tests/ControlSampleTests.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,14 @@ public async Task AjaxControl_Loads_WithoutErrors(string path)
247247
await VerifyPageLoadsWithoutErrors(path);
248248
}
249249

250+
// Migration Shim Sample Pages
251+
[Theory]
252+
[InlineData("/migration/request-form")]
253+
public async Task MigrationPage_Loads_WithoutErrors(string path)
254+
{
255+
await VerifyPageLoadsWithoutErrors(path);
256+
}
257+
250258
// Ajax Control Toolkit Controls
251259
[Theory]
252260
[InlineData("/ControlSamples/Accordion")]
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
using Microsoft.Playwright;
2+
3+
namespace AfterBlazorServerSide.Tests.Migration;
4+
5+
/// <summary>
6+
/// Integration tests for the Request.Form shim sample page at /migration/request-form.
7+
/// Verifies page load, demo section rendering, and graceful degradation in interactive mode.
8+
/// </summary>
9+
[Collection(nameof(PlaywrightCollection))]
10+
public class RequestFormTests
11+
{
12+
private readonly PlaywrightFixture _fixture;
13+
14+
public RequestFormTests(PlaywrightFixture fixture)
15+
{
16+
_fixture = fixture;
17+
}
18+
19+
/// <summary>
20+
/// Smoke test — verifies the page loads without errors and displays the expected heading.
21+
/// </summary>
22+
[Fact]
23+
public async Task RequestForm_PageLoads_Successfully()
24+
{
25+
var page = await _fixture.NewPageAsync();
26+
var consoleErrors = new List<string>();
27+
28+
page.Console += (_, msg) =>
29+
{
30+
if (msg.Type == "error")
31+
{
32+
if (System.Text.RegularExpressions.Regex.IsMatch(msg.Text, @"^\[\d{4}-\d{2}-\d{2}T"))
33+
return;
34+
if (msg.Text.StartsWith("Failed to load resource"))
35+
return;
36+
consoleErrors.Add(msg.Text);
37+
}
38+
};
39+
40+
try
41+
{
42+
var response = await page.GotoAsync($"{_fixture.BaseUrl}/migration/request-form", new PageGotoOptions
43+
{
44+
WaitUntil = WaitUntilState.NetworkIdle,
45+
Timeout = 30000
46+
});
47+
48+
Assert.NotNull(response);
49+
Assert.True(response.Ok, $"Page failed to load with status: {response.Status}");
50+
51+
// Verify the page heading renders
52+
var heading = page.Locator("h2").Filter(new() { HasTextString = "Request.Form Migration" });
53+
await Assertions.Expect(heading).ToBeVisibleAsync();
54+
55+
// Verify page title
56+
await Assertions.Expect(page).ToHaveTitleAsync(new System.Text.RegularExpressions.Regex("Request\\.Form"));
57+
58+
Assert.Empty(consoleErrors);
59+
}
60+
finally
61+
{
62+
await page.CloseAsync();
63+
}
64+
}
65+
66+
/// <summary>
67+
/// Render test — verifies all four data-audit-control demo cards are present.
68+
/// </summary>
69+
[Fact]
70+
public async Task RequestForm_DemoSections_Render()
71+
{
72+
var page = await _fixture.NewPageAsync();
73+
74+
try
75+
{
76+
await page.GotoAsync($"{_fixture.BaseUrl}/migration/request-form", new PageGotoOptions
77+
{
78+
WaitUntil = WaitUntilState.NetworkIdle,
79+
Timeout = 30000
80+
});
81+
82+
// Wait for Blazor interactive circuit
83+
await page.WaitForFunctionAsync("typeof window.__doPostBack === 'function'",
84+
null, new PageWaitForFunctionOptions { Timeout = 10000 });
85+
86+
// Verify all four demo cards render
87+
var basicDemo = page.Locator("[data-audit-control='form-basic-demo']");
88+
await Assertions.Expect(basicDemo).ToBeVisibleAsync();
89+
90+
var getValuesDemo = page.Locator("[data-audit-control='form-getvalues-demo']");
91+
await Assertions.Expect(getValuesDemo).ToBeVisibleAsync();
92+
93+
var metadataDemo = page.Locator("[data-audit-control='form-metadata-demo']");
94+
await Assertions.Expect(metadataDemo).ToBeVisibleAsync();
95+
96+
var migrationGuidance = page.Locator("[data-audit-control='form-migration-guidance']");
97+
await Assertions.Expect(migrationGuidance).ToBeVisibleAsync();
98+
99+
// Verify card titles
100+
await Assertions.Expect(basicDemo.Locator(".card-title")).ToContainTextAsync("Basic Field Access");
101+
await Assertions.Expect(getValuesDemo.Locator(".card-title")).ToContainTextAsync("GetValues");
102+
await Assertions.Expect(metadataDemo.Locator(".card-title")).ToContainTextAsync("Form Metadata");
103+
await Assertions.Expect(migrationGuidance.Locator(".card-title")).ToContainTextAsync("Migration Path Summary");
104+
}
105+
finally
106+
{
107+
await page.CloseAsync();
108+
}
109+
}
110+
111+
/// <summary>
112+
/// Interactive mode test — verifies Request.Form returns empty/null values gracefully
113+
/// when running in Blazor Server interactive mode (no HTTP POST available).
114+
/// </summary>
115+
[Fact]
116+
public async Task RequestForm_InteractiveMode_ShowsGracefulDegradation()
117+
{
118+
var page = await _fixture.NewPageAsync();
119+
120+
try
121+
{
122+
await page.GotoAsync($"{_fixture.BaseUrl}/migration/request-form", new PageGotoOptions
123+
{
124+
WaitUntil = WaitUntilState.NetworkIdle,
125+
Timeout = 30000
126+
});
127+
128+
// Wait for Blazor interactive circuit
129+
await page.WaitForFunctionAsync("typeof window.__doPostBack === 'function'",
130+
null, new PageWaitForFunctionOptions { Timeout = 10000 });
131+
132+
// Basic field access card — should show null indicators
133+
var basicDemo = page.Locator("[data-audit-control='form-basic-demo']");
134+
await Assertions.Expect(basicDemo).ToContainTextAsync("(null");
135+
136+
// GetValues card — should show null indicator
137+
var getValuesDemo = page.Locator("[data-audit-control='form-getvalues-demo']");
138+
await Assertions.Expect(getValuesDemo).ToContainTextAsync("(null");
139+
140+
// Metadata card — Count should be 0, AllKeys should be empty, ContainsKey should be False
141+
var metadataDemo = page.Locator("[data-audit-control='form-metadata-demo']");
142+
var metadataTable = metadataDemo.Locator("table");
143+
144+
// Request.Form.Count should show 0
145+
var countRow = metadataTable.Locator("tr").Filter(new() { HasTextString = "Request.Form.Count" });
146+
await Assertions.Expect(countRow.Locator("strong")).ToContainTextAsync("0");
147+
148+
// Request.Form.AllKeys should show "(empty — no form fields)"
149+
var allKeysRow = metadataTable.Locator("tr").Filter(new() { HasTextString = "Request.Form.AllKeys" });
150+
await Assertions.Expect(allKeysRow).ToContainTextAsync("(empty");
151+
152+
// Request.Form.ContainsKey("username") should show False
153+
var containsKeyRow = metadataTable.Locator("tr").Filter(new() { HasTextString = "ContainsKey" });
154+
await Assertions.Expect(containsKeyRow.Locator("strong")).ToContainTextAsync("False");
155+
}
156+
finally
157+
{
158+
await page.CloseAsync();
159+
}
160+
}
161+
}

0 commit comments

Comments
 (0)