mcpField
U
umbraco-playwright-testhelpers

umbraco-playwright-testhelpers

github.com/umbraco测试与质量27376 次安装6 周前更新
代码仓库

关于 umbraco-playwright-testhelpers

@umbraco/playwright-testhelpers 为 Umbraco backoffice 的端到端测试提供 Playwright fixtures,以及 API 和界面辅助方法。适合编写测试的开发者,可用 API 设置测试数据并通过 UI 操作验证流程。

主要功能

  1. 01扩展 Playwright 测试并提供 fixtures
  2. 02按内容与实体类别提供 API 辅助方法
  3. 03提供 backoffice 导航和交互方法
  4. 04包含常量、别名及 JSON 工具

适用场景

  1. 01通过 API 创建和清理测试数据
  2. 02验证 backoffice 中的内容操作
  3. 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 类为每种实体类型提供子辅助工具:

属性辅助类用途
contentContentApiHelper内容/文档操作
documentTypesDocumentTypeApiHelper文档类型操作
dataTypesDatatypeApiHelper数据类型操作
mediaMediaApiHelper媒体操作
mediaTypesMediaTypeApiHelper媒体类型操作
templatesTemplatesApiHelper模板操作
languagesLanguagesApiHelper语言操作
usersUserApiHelper用户操作
userGroupsUserGroupApiHelper用户组操作
membersMemberApiHelper成员操作
memberTypesMemberTypeApiHelper成员类型操作
memberGroupsMemberGroupApiHelper成员组操作
macrosMacroApiHelper宏操作
scriptsScriptApiHelper脚本操作
stylesheetsStylesheetApiHelper样式表操作
partialViewsPartialViewApiHelper局部视图操作
relationTypesRelationTypeApiHelper关系类型操作
packagesPackageApiHelper软件包操作
domainDomainApiHelper域操作
translationTranslationApiHelper翻译操作
webhookWebhookApiHelperWebhook 操作
核心 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