playwright
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChinesePlaywright Skill
Playwright 技能
E2E testing for Blazor WebAssembly using Playwright .NET with NUnit and .NET Aspire integration. Tests run against the full Aspire application stack with all services.
使用Playwright .NET结合NUnit和.NET Aspire集成,为Blazor WebAssembly进行端到端(E2E)测试。测试会针对包含所有服务的完整Aspire应用栈运行。
Quick Start
快速开始
Basic Page Test
基础页面测试
csharp
[Parallelizable(ParallelScope.Self)]
[TestFixture]
public class BlazorUITests : PageTest
{
private DistributedApplication? _app;
private string? _blazorUrl;
[OneTimeSetUp]
public async Task OneTimeSetUp()
{
var appHost = await DistributedApplicationTestingBuilder
.CreateAsync<Projects.Sorcha_AppHost>();
_app = await appHost.BuildAsync();
await _app.StartAsync();
_blazorUrl = _app.GetEndpoint("blazor-client").ToString();
}
[Test]
public async Task HomePage_LoadsSuccessfully()
{
await Page.GotoAsync(_blazorUrl!);
await Page.WaitForLoadStateAsync();
await Expect(Page).ToHaveTitleAsync(new Regex("Sorcha|Blueprint"));
}
}csharp
[Parallelizable(ParallelScope.Self)]
[TestFixture]
public class BlazorUITests : PageTest
{
private DistributedApplication? _app;
private string? _blazorUrl;
[OneTimeSetUp]
public async Task OneTimeSetUp()
{
var appHost = await DistributedApplicationTestingBuilder
.CreateAsync<Projects.Sorcha_AppHost>();
_app = await appHost.BuildAsync();
await _app.StartAsync();
_blazorUrl = _app.GetEndpoint("blazor-client").ToString();
}
[Test]
public async Task HomePage_LoadsSuccessfully()
{
await Page.GotoAsync(_blazorUrl!);
await Page.WaitForLoadStateAsync();
await Expect(Page).ToHaveTitleAsync(new Regex("Sorcha|Blueprint"));
}
}Locator Patterns
定位器模式
csharp
// Role-based (preferred)
await Page.GetByRole(AriaRole.Button, new() { Name = "Submit" }).ClickAsync();
// Text-based
Page.Locator("a:has-text('Designer')")
// MudBlazor components
Page.Locator(".mud-button")
Page.Locator(".mud-table")
// Test IDs (most stable)
Page.Locator("[data-testid='my-element']")csharp
// Role-based (preferred)
await Page.GetByRole(AriaRole.Button, new() { Name = "Submit" }).ClickAsync();
// Text-based
Page.Locator("a:has-text('Designer')")
// MudBlazor components
Page.Locator(".mud-button")
Page.Locator(".mud-table")
// Test IDs (most stable)
Page.Locator("[data-testid='my-element']")Key Concepts
核心概念
| Concept | Usage | Example |
|---|---|---|
| PageTest | Base class providing Page object | |
| Locator | Lazy element reference | |
| Expect | Assertion API | |
| Aspire Testing | Full stack integration | |
| Auto-wait | Built-in waiting | Actions wait for actionability |
| 概念 | 用法 | 示例 |
|---|---|---|
| PageTest | 提供Page对象的基类 | |
| Locator | 延迟加载的元素引用 | |
| Expect | 断言API | |
| Aspire Testing | 全栈集成 | |
| Auto-wait | 内置等待机制 | 操作会等待元素可交互 |
Common Patterns
常见模式
JavaScript Error Detection
JavaScript错误检测
csharp
[Test]
public async Task NoJavaScriptErrors()
{
var errors = new List<string>();
Page.Console += (_, msg) =>
{
if (msg.Type == "error") errors.Add(msg.Text);
};
await Page.GotoAsync(_blazorUrl!);
await Page.WaitForLoadStateAsync();
var criticalErrors = errors.Where(e =>
!e.Contains("WASM") && !e.Contains("Blazor")).ToList();
Assert.That(criticalErrors, Is.Empty);
}csharp
[Test]
public async Task NoJavaScriptErrors()
{
var errors = new List<string>();
Page.Console += (_, msg) =>
{
if (msg.Type == "error") errors.Add(msg.Text);
};
await Page.GotoAsync(_blazorUrl!);
await Page.WaitForLoadStateAsync();
var criticalErrors = errors.Where(e =>
!e.Contains("WASM") && !e.Contains("Blazor")).ToList();
Assert.That(criticalErrors, Is.Empty);
}Responsive Design Testing
响应式设计测试
csharp
[Test]
public async Task ResponsiveDesign_Works()
{
await Page.SetViewportSizeAsync(375, 667); // Mobile
await Page.GotoAsync(_blazorUrl!);
Assert.That(await Page.TextContentAsync("body"), Is.Not.Empty);
await Page.SetViewportSizeAsync(1920, 1080); // Desktop
await Page.ReloadAsync();
Assert.That(await Page.TextContentAsync("body"), Is.Not.Empty);
}csharp
[Test]
public async Task ResponsiveDesign_Works()
{
await Page.SetViewportSizeAsync(375, 667); // Mobile
await Page.GotoAsync(_blazorUrl!);
Assert.That(await Page.TextContentAsync("body"), Is.Not.Empty);
await Page.SetViewportSizeAsync(1920, 1080); // Desktop
await Page.ReloadAsync();
Assert.That(await Page.TextContentAsync("body"), Is.Not.Empty);
}See Also
另请参阅
- patterns - Locator strategies and assertions
- workflows - Test setup and CI integration
- patterns - 定位器策略与断言
- workflows - 测试设置与CI集成
Related Skills
相关技能
- See the xunit skill for unit testing patterns
- See the fluent-assertions skill for SignalR integration tests
- See the blazor skill for component architecture
- See the signalr skill for real-time notification testing
- See the docker skill for container-based test environments
- 查看xunit技能了解单元测试模式
- 查看fluent-assertions技能了解SignalR集成测试
- 查看blazor技能了解组件架构
- 查看signalr技能了解实时通知测试
- 查看docker技能了解基于容器的测试环境
Documentation Resources
文档资源
Fetch latest Playwright .NET documentation with Context7.
How to use Context7:
- Use to search for "playwright"
mcp__context7__resolve-library-id - Prefer website documentation () over source code
/websites/playwright_dev_dotnet - Query with using the resolved library ID
mcp__context7__query-docs
Library ID:
/websites/playwright_dev_dotnetRecommended Queries:
- "Locators selectors best practices"
- "NUnit test fixtures setup teardown"
- "Wait for element network idle auto-waiting"
- "Assertions expect API"
- "Trace viewer debugging"
使用Context7获取最新的Playwright .NET文档。
Context7使用方法:
- 使用搜索"playwright"
mcp__context7__resolve-library-id - 优先选择网站文档 ()而非源代码
/websites/playwright_dev_dotnet - 使用解析后的库ID,通过进行查询
mcp__context7__query-docs
库ID:
/websites/playwright_dev_dotnet推荐查询:
- "Locators selectors best practices"
- "NUnit test fixtures setup teardown"
- "Wait for element network idle auto-waiting"
- "Assertions expect API"
- "Trace viewer debugging"