关于 umbraco-playwright-testhelpers
@umbraco/playwright-testhelpers 为 Umbraco backoffice 的端到端测试提供 Playwright fixtures,以及 API 和界面辅助方法。适合编写测试的开发者,可用 API 设置测试数据并通过 UI 操作验证流程。
主要功能
- 01扩展 Playwright 测试并提供 fixtures
- 02按内容与实体类别提供 API 辅助方法
- 03提供 backoffice 导航和交互方法
- 04包含常量、别名及 JSON 工具
适用场景
- 01通过 API 创建和清理测试数据
- 02验证 backoffice 中的内容操作
- 03测试文件上传和界面导航
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ umbraco/ umbraco-cms-backoffice-skills --skill umbraco-playwright-testhelpers安装后在 Claude Code 中输入/umbraco-playwright-testhelpers确认已加载。
详细介绍
Umbraco Playwright 测试辅助工具
这是什么?
@umbraco/playwright-testhelpers 是 Umbraco 官方软件包,提供 Playwright fixture、API 辅助工具和 UI 辅助工具,用于针对 Umbraco 后台实例编写 E2E 测试。
代码库:https://github.com/umbraco/Umbraco.Playwright.Testhelpers
安装
npm install @umbraco/playwright-testhelpers --save-dev
相关技能
- umbraco-e2e-testing - 使用这些辅助工具的 E2E 测试模式
- umbraco-test-builders - JsonModels.Builders(由 testhelpers 在内部使用)
- umbraco-testing - 测试概览主技能
软件包导出项
该软件包导出以下主要项:
import {
test, // Extended Playwright test with fixtures
ApiHelpers, // Direct API helper class
UiHelpers, // Direct UI helper class
ConstantHelper, // Constants for sections, actions, buttons
AliasHelper, // Alias generation utilities
JsonHelper // JSON parsing utilities
} from '@umbraco/playwright-testhelpers';
测试 Fixture
test 导出项通过两个 fixture 扩展了 Playwright 的 test:
import { test } from '@umbraco/playwright-testhelpers';
test('my test', async ({ umbracoApi, umbracoUi }) => {
// umbracoApi - API helpers for fast test setup/teardown
// umbracoUi - UI helpers for backoffice interaction
});
Fixture 的工作方式
// testExtension.ts (internal)
const test = base.extend<{umbracoApi: ApiHelpers} & {umbracoUi: UiHelpers}>({
umbracoApi: async ({ page }, use) => {
const umbracoApi = new ApiHelpers(page);
await use(umbracoApi);
},
umbracoUi: async ({ page }, use) => {
const umbracoUi = new UiHelpers(page);
await use(umbracoUi);
}
});
API 辅助工具(umbracoApi)
ApiHelpers 类为每种实体类型提供子辅助工具:
| 属性 | 辅助类 | 用途 |
|---|---|---|
content | ContentApiHelper | 内容/文档操作 |
documentTypes | DocumentTypeApiHelper | 文档类型操作 |
dataTypes | DatatypeApiHelper | 数据类型操作 |
media | MediaApiHelper | 媒体操作 |
mediaTypes | MediaTypeApiHelper | 媒体类型操作 |
templates | TemplatesApiHelper | 模板操作 |
languages | LanguagesApiHelper | 语言操作 |
users | UserApiHelper | 用户操作 |
userGroups | UserGroupApiHelper | 用户组操作 |
members | MemberApiHelper | 成员操作 |
memberTypes | MemberTypeApiHelper | 成员类型操作 |
memberGroups | MemberGroupApiHelper | 成员组操作 |
macros | MacroApiHelper | 宏操作 |
scripts | ScriptApiHelper | 脚本操作 |
stylesheets | StylesheetApiHelper | 样式表操作 |
partialViews | PartialViewApiHelper | 局部视图操作 |
relationTypes | RelationTypeApiHelper | 关系类型操作 |
packages | PackageApiHelper | 软件包操作 |
domain | DomainApiHelper | 域操作 |
translation | TranslationApiHelper | 翻译操作 |
webhook | WebhookApiHelper | Webhook 操作 |
核心 API 方法
// Base HTTP methods (available on umbracoApi directly)
await umbracoApi.get(url, params?);
await umbracoApi.post(url, data?);
await umbracoApi.delete(url, data?);
// CSRF token (automatically handled)
await umbracoApi.getCsrfToken();
// Login
await umbracoApi.login(skipCheckTours?: boolean);
文档类型 API 辅助工具
// Ensure cleanup (idempotent - won't fail if not exists)
await umbracoApi.documentTypes.ensureNameNotExists('MyDocType');
// Create default document type
const docType = await umbracoApi.documentTypes.createDefaultDocumentType('MyDocType');
// Create element type (for blocks)
const elementType = await umbracoApi.documentTypes.createDefaultElementType('MyElement', 'myElement');
// Create document type with block grid
const element = await umbracoApi.documentTypes.createDefaultDocumentWithBlockGridEditor(element?, dataType?);
// Save document type (using builder)
const docType = new DocumentTypeBuilder()
.withName('MyDocType')
.withAlias('myDocType')
.build();
await umbracoApi.documentTypes.save(docType);
内容 API 辅助工具
// Reference: ContentApiHelper.ts patterns
// Note: Actual methods depend on version - check source
// Common patterns:
await umbracoApi.content.ensureNameNotExists('MyContent');
await umbracoApi.content.createDefaultContent(name, documentTypeId);
await umbracoApi.content.getByName('MyContent');
await umbracoApi.content.publish(contentId);
数据类型 API 辅助工具
// Get built-in data type
const dataType = await umbracoApi.dataTypes.getByName('Textstring');
// Create block grid data type
const blockGrid = await umbracoApi.dataTypes.createDefaultBlockGrid('MyBlockGrid', elementType);
// Ensure cleanup
await umbracoApi.dataTypes.ensureNameNotExists('MyDataType');
媒体 API 辅助工具
// Create media folder
await umbracoApi.media.createDefaultMediaFolder('MyFolder');
// Create image with file
await umbracoApi.media.createImageWithFile(
'MyImage',
{ src: '/path/to/image.jpg' },
'image.jpg',
'/local/path/to/image.jpg',
'image/jpeg'
);
// Cleanup
await umbracoApi.media.ensureNameNotExists('MyImage');
await umbracoApi.media.clearRecycleBin();
UI 辅助工具(umbracoUi)
导航
// Navigate to section
await umbracoUi.goToSection(ConstantHelper.sections.content);
await umbracoUi.goToSection(ConstantHelper.sections.settings);
await umbracoUi.goToSection(ConstantHelper.sections.media);
// Navigate to specific items
await umbracoUi.navigateToContent('MyContent');
await umbracoUi.navigateToMedia('MyMedia');
await umbracoUi.navigateToDocumentType('MyDocType');
await umbracoUi.navigateToDataType('MyDataType');
await umbracoUi.navigateToTemplate('MyTemplate');
树操作
// Get tree item by path
const item = await umbracoUi.getTreeItem('contentTypes', ['MyFolder', 'MyDocType']);
// Refresh trees
await umbracoUi.refreshContentTree();
await umbracoUi.refreshMediaTree();
// Wait for tree load
await umbracoUi.waitForTreeLoad('settings');
点击操作
// Click by data-element attribute
await umbracoUi.clickDataElementByElementName('tree-item-myItem');
// Click by text
await umbracoUi.clickButtonByText('Save');
// Click element
await umbracoUi.clickElement(locator);
// Click multiple elements
await umbracoUi.clickMultiple(locator);
编辑器操作
// Set header name (with alias generation wait)
await umbracoUi.setEditorHeaderName('My Document');
// Get editor header name
await umbracoUi.getEditorHeaderName('My Document');
// Add property group and editor
await umbracoUi.goToAddEditor('Content', 'Title');
定位器获取方法
// Get elements
const helpButton = await umbracoUi.getGlobalHelp();
const userButton = await umbracoUi.getGlobalUser();
const element = await umbracoUi.getDataElementByElementName('my-element');
const button = await umbracoUi.getButtonByText('Save');
const button = await umbracoUi.getButtonByLabelKey('buttons_save');
const contextAction = await umbracoUi.getContextMenuAction('action-create');
// Notifications
const success = await umbracoUi.getSuccessNotification();
const error = await umbracoUi.getErrorNotification();
断言
// Check notifications
await umbracoUi.isSuccessNotificationVisible();
await umbracoUi.isErrorNotificationVisible();
// Check data type exists
await umbracoUi.doesDataTypeExist('MyDataType');
文档类型 UI
// Create with template
await umbracoUi.createNewDocumentTypeWithTemplate();
// Update permissions
await umbracoUi.updateDocumentPermissionsToAllowCultureVariant();
内容 UI
// Create content
await umbracoUi.createContentWithDocumentType('MyDocType');
// Switch culture
await umbracoUi.switchCultureInContent('Danish');
文件上传
// Upload file
await umbracoUi.fileUploader('/path/to/file.jpg');
拖放
// Drag and drop elements
await umbracoUi.dragAndDrop(
fromLocator,
toLocator,
verticalOffset,
horizontalOffset,
steps?
);
ConstantHelper
import { ConstantHelper } from '@umbraco/playwright-testhelpers';
// Sections
ConstantHelper.sections.content // "content"
ConstantHelper.sections.media // "media"
ConstantHelper.sections.settings // "settings"
ConstantHelper.sections.users // "users"
ConstantHelper.sections.member // "member"
ConstantHelper.sections.packages // "packages"
ConstantHelper.sections.translation // "translation"
// Actions (data-element values)
ConstantHelper.actions.create // "action-create"
ConstantHelper.actions.delete // "action-delete"
ConstantHelper.actions.copy // "action-copy"
ConstantHelper.actions.move // "action-move"
ConstantHelper.actions.sort // "action-sort"
ConstantHelper.actions.save // "saveNew"
ConstantHelper.actions.publish // "publishNew"
ConstantHelper.actions.documentType // "action-documentType"
ConstantHelper.actions.dataType // "action-data-type"
ConstantHelper.actions.remove // "actions_remove"
// Buttons (label-key values)
ConstantHelper.buttons.save // "buttons_save"
ConstantHelper.buttons.saveAndPublish // "buttons_saveAndPublish"
ConstantHelper.buttons.delete // "general_delete"
ConstantHelper.buttons.ok // "general_ok"
ConstantHelper.buttons.close // "general_close"
ConstantHelper.buttons.insert // "general_insert"
ConstantHelper.buttons.download // "general_download"
ConstantHelper.buttons.submit // "general_submit"
ConstantHelper.buttons.rollback // "actions_rollback"
ConstantHelper.buttons.add // "general_add"
ConstantHelper.buttons.submitChanges // "buttons_submitChanges"
ConstantHelper.buttons.remove // "general_remove"
ConstantHelper.buttons.change // "general_change"
ConstantHelper.buttons.select // "buttons_select"
// Content Apps
ConstantHelper.contentApps.info // '[data-element="sub-view-umbInfo"]'
AliasHelper
完整的 AliasHelper 文档请参阅 umbraco-test-builders。
JsonHelper
import { JsonHelper } from '@umbraco/playwright-testhelpers';
// Parse response body
const response = await umbracoApi.get(url);
const body = await JsonHelper.getBody(response);
完整示例
完整的测试示例和模板请参阅 umbraco-e2e-testing。
源码参考
- 代码库:https://github.com/umbraco/Umbraco.Playwright.Testhelpers
- 本地路径:
/Users/philw/Projects/Umbraco.Playwright.Testhelpers/ - 主要文件:
lib/helpers/ApiHelpers.ts- API 辅助类lib/helpers/UiHelpers.ts- UI 辅助类lib/helpers/testExtension.ts- 测试 fixture 扩展lib/helpers/ConstantHelper.ts- 常量lib/helpers/AliasHelper.ts- 别名工具
评论
支持 Markdown