umbraco-test-builders by umbraco/umbraco-cms-backoffice-skills
npx skills add https://github.com/umbraco/umbraco-cms-backoffice-skills --skill umbraco-test-builders@umbraco/json-models-builders 包提供了用于创建 Umbraco 后台模型的流畅构建器类。这些构建器通过合理的默认值和可链式调用的配置方法,简化了测试数据的创建。
@umbraco/json-models-builders/Users/philw/Projects/Umbraco.JsonModels.Buildersnpm install @umbraco/json-models-builders
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
所有构建器都遵循以下模式:
const model = new SomeBuilder()
.withProperty(value) // 配置标量属性
.withOtherProperty(value) // 链式调用多个配置
.addChild() // 创建嵌套构建器
.withChildProperty(value)
.done() // 返回父构建器
.build(); // 生成最终对象
| 方法模式 | 目的 | 返回值 |
|---|---|---|
withXxx(value) | 设置属性 | this(用于链式调用) |
addXxx() | 添加嵌套构建器 | 子构建器 |
done() | 返回父级 | 父构建器 |
build() | 生成最终对象 | 模型 |
创建包含属性、组和选项卡的文档类型:
import { DocumentTypeBuilder } from '@umbraco/json-models-builders';
const documentType = new DocumentTypeBuilder()
.withName('Article')
.withAlias('article')
.withAllowAsRoot(true)
.withAllowCultureVariation(true)
.addGroup()
.withName('Content')
.addTextBoxProperty()
.withLabel('Title')
.withAlias('title')
.done()
.addRichTextProperty()
.withLabel('Body')
.withAlias('body')
.done()
.done()
.addGroup()
.withName('SEO')
.addTextBoxProperty()
.withLabel('Meta Title')
.withAlias('metaTitle')
.done()
.done()
.build();
关键方法 :
withName(name) - 文档类型名称withAlias(alias) - 文档类型别名withAllowAsRoot(bool) - 允许在内容根目录下withAllowCultureVariation(bool) - 启用变体AsElementType() - 标记为元素类型(用于块)addGroup() - 添加属性组addTab() - 添加选项卡withDefaultTemplate(template) - 设置默认模板创建内容项:
import { ContentBuilder } from '@umbraco/json-models-builders';
const content = new ContentBuilder()
.withContentTypeAlias('article')
.withAction('publishNew')
.withParent('-1') // 根目录
.addVariant()
.withName('My Article')
.withCulture('en-US')
.addProperty()
.withAlias('title')
.withValue('Hello World')
.done()
.addProperty()
.withAlias('body')
.withValue('<p>Article content</p>')
.done()
.done()
.build();
关键方法 :
withContentTypeAlias(alias) - 文档类型别名withTemplateAlias(alias) - 模板别名withAction(action) - 'publishNew', 'save' 等withParent(parentId) - 父节点 IDaddVariant() - 添加内容变体创建媒体项:
import { MediaBuilder } from '@umbraco/json-models-builders';
const media = new MediaBuilder()
.withName('My Image')
.withMediaTypeAlias('Image')
.addProperty()
.withAlias('umbracoFile')
.withValue({ src: '/media/image.jpg' })
.done()
.build();
创建数据类型:
import { DataTypeBuilder } from '@umbraco/json-models-builders';
const dataType = new DataTypeBuilder()
.withName('My Text Box')
.withSaveNewAction()
.build();
向文档类型添加属性:
documentTypeBuilder
.addGroup()
.withName('Content')
.addTextBoxProperty()
.withLabel('Title')
.withAlias('title')
.withDescription('Enter the page title')
.withMandatory(true)
.done()
.done()
.addRichTextProperty()
.withLabel('Body Text')
.withAlias('bodyText')
.done()
.addMediaPickerProperty()
.withLabel('Featured Image')
.withAlias('featuredImage')
.done()
.addContentPickerProperty()
.withLabel('Related Page')
.withAlias('relatedPage')
.done()
.addCustomProperty()
.withLabel('Custom Field')
.withAlias('customField')
.withDataTypeId('your-datatype-id')
.done()
import { BlockListDataTypeBuilder } from '@umbraco/json-models-builders';
const blockList = new BlockListDataTypeBuilder()
.withName('Content Blocks')
.addBlock()
.withContentElementTypeKey('hero-block-key')
.withLabel('Hero Block')
.done()
.addBlock()
.withContentElementTypeKey('text-block-key')
.withLabel('Text Block')
.done()
.withMin(1)
.withMax(10)
.withUseLiveEditing(true)
.build();
import { BlockGridDataTypeBuilder } from '@umbraco/json-models-builders';
const blockGrid = new BlockGridDataTypeBuilder()
.withName('Page Grid')
.withGridColumns(12)
.addBlock()
.withContentElementTypeKey('row-block-key')
.withLabel('Row')
.withColumnSpanOptions([6, 12])
.done()
.addBlock()
.withContentElementTypeKey('image-block-key')
.withLabel('Image')
.done()
.build();
import { ContentBuilder, BlockListValueBuilder } from '@umbraco/json-models-builders';
const content = new ContentBuilder()
.withContentTypeAlias('page')
.addVariant()
.withName('Home')
.addProperty()
.withAlias('blocks')
.addBlockListValue()
.addBlockListEntry()
.withContentTypeKey('hero-block-key')
.appendContentProperties('heading', 'Welcome')
.appendContentProperties('subheading', 'To our site')
.done()
.addBlockListEntry()
.withContentTypeKey('text-block-key')
.appendContentProperties('text', 'Some content here')
.done()
.done()
.done()
.done()
.build();
import { UserBuilder } from '@umbraco/json-models-builders';
const user = new UserBuilder()
.withName('Test User')
.withEmail('test@example.com')
.withUserGroups(['admin'])
.build();
import { UserGroupBuilder } from '@umbraco/json-models-builders';
const userGroup = new UserGroupBuilder()
.withName('Editors')
.withAlias('editors')
.withIcon('icon-users')
.appendSection('content')
.appendSection('media')
.addDefaultPermissions()
.withBrowseNode()
.withCreate()
.withUpdate()
.withPublish()
.done()
.withSaveNew()
.build();
userGroupBuilder
.addNodePermissions()
.forNode('content-node-id')
.withBrowseNode()
.withCreate()
.withUpdate()
.withDelete()
.withPublish()
.withUnpublish()
.done()
import { TemplateBuilder } from '@umbraco/json-models-builders';
const template = new TemplateBuilder()
.withName('Article Template')
.withAlias('articleTemplate')
.withContent(`@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
<h1>@Model.Name</h1>`)
.build();
import { StylesheetBuilder } from '@umbraco/json-models-builders';
const stylesheet = new StylesheetBuilder()
.withName('main.css')
.withContent('body { font-family: sans-serif; }')
.build();
import { ScriptBuilder } from '@umbraco/json-models-builders';
const script = new ScriptBuilder()
.withName('main.js')
.withContent('console.log("Hello");')
.build();
从名称生成安全的别名:
import { AliasHelper } from '@umbraco/json-models-builders';
// 转换为驼峰式别名
AliasHelper.toAlias('My Page Type');
// 返回: "myPageType"
// 创建带前缀/后缀的安全别名
AliasHelper.toSafeAlias('My Page Type');
// 返回: "aMyPageTypea"
// 首字母大写
AliasHelper.capitalize('hello');
// 返回: "Hello"
// 将句子转换为驼峰式
AliasHelper.toCamelCase('My Awesome Example');
// 返回: "myAwesomeExample"
// 将 UUID 转换为别名(移除短横线)
AliasHelper.uuidToAlias('123e4567-e89b-12d3-a456-426614174000');
// 返回: "123e4567e89b12d3a456426614174000"
import { DocumentTypeBuilder, AliasHelper } from '@umbraco/json-models-builders';
const name = 'Blog Post';
const alias = AliasHelper.toAlias(name);
const blogPost = new DocumentTypeBuilder()
.withName(name)
.withAlias(alias)
.withAllowAsRoot(true)
.withAllowCultureVariation(true)
.addGroup()
.withName('Content')
.addTextBoxProperty()
.withLabel('Title')
.withAlias('title')
.withMandatory(true)
.done()
.addTextBoxProperty()
.withLabel('Author')
.withAlias('author')
.done()
.addRichTextProperty()
.withLabel('Body')
.withAlias('body')
.done()
.done()
.addGroup()
.withName('Media')
.addMediaPickerProperty()
.withLabel('Featured Image')
.withAlias('featuredImage')
.done()
.done()
.build();
// 在测试中使用
await umbracoApi.documentType.save(blogPost);
const heroBlock = new DocumentTypeBuilder()
.withName('Hero Block')
.withAlias('heroBlock')
.AsElementType() // 对于块很重要!
.addGroup()
.withName('Content')
.addTextBoxProperty()
.withLabel('Heading')
.withAlias('heading')
.done()
.addTextBoxProperty()
.withLabel('Subheading')
.withAlias('subheading')
.done()
.addMediaPickerProperty()
.withLabel('Background Image')
.withAlias('backgroundImage')
.done()
.done()
.build();
const pageContent = new ContentBuilder()
.withContentTypeAlias('landingPage')
.withAction('publishNew')
.addVariant()
.withName('Landing Page')
.addProperty()
.withAlias('pageTitle')
.withValue('Welcome')
.done()
.addProperty()
.withAlias('contentBlocks')
.addBlockListValue()
.addBlockListEntry()
.withContentTypeKey(heroBlockKey)
.appendContentProperties('heading', 'Welcome to Our Site')
.appendContentProperties('subheading', 'Discover what we offer')
.done()
.addBlockListEntry()
.withContentTypeKey(textBlockKey)
.appendContentProperties('text', '<p>More content here...</p>')
.done()
.done()
.done()
.done()
.build();
每周安装量
71
仓库
GitHub 星标数
17
首次出现
2026年2月4日
安全审计
安装于
github-copilot53
opencode22
codex22
cursor21
amp20
kimi-cli20
The @umbraco/json-models-builders package provides fluent builder classes for creating Umbraco backoffice models. These builders simplify test data creation with sensible defaults and chainable configuration methods.
@umbraco/json-models-builders/Users/philw/Projects/Umbraco.JsonModels.Buildersnpm install @umbraco/json-models-builders
All builders follow this pattern:
const model = new SomeBuilder()
.withProperty(value) // Configure scalar properties
.withOtherProperty(value) // Chain multiple configurations
.addChild() // Create nested builder
.withChildProperty(value)
.done() // Return to parent builder
.build(); // Generate final object
| Method Pattern | Purpose | Returns |
|---|---|---|
withXxx(value) | Set a property | this (for chaining) |
addXxx() | Add nested builder | Child builder |
done() | Return to parent | Parent builder |
build() | Generate final object | The model |
Create document types with properties, groups, and tabs:
import { DocumentTypeBuilder } from '@umbraco/json-models-builders';
const documentType = new DocumentTypeBuilder()
.withName('Article')
.withAlias('article')
.withAllowAsRoot(true)
.withAllowCultureVariation(true)
.addGroup()
.withName('Content')
.addTextBoxProperty()
.withLabel('Title')
.withAlias('title')
.done()
.addRichTextProperty()
.withLabel('Body')
.withAlias('body')
.done()
.done()
.addGroup()
.withName('SEO')
.addTextBoxProperty()
.withLabel('Meta Title')
.withAlias('metaTitle')
.done()
.done()
.build();
Key Methods :
withName(name) - Document type namewithAlias(alias) - Document type aliaswithAllowAsRoot(bool) - Allow at content rootwithAllowCultureVariation(bool) - Enable variantsAsElementType() - Mark as element type (for blocks)addGroup() - Add property groupaddTab() - Add tabwithDefaultTemplate(template) - Set default templateCreate content items:
import { ContentBuilder } from '@umbraco/json-models-builders';
const content = new ContentBuilder()
.withContentTypeAlias('article')
.withAction('publishNew')
.withParent('-1') // Root
.addVariant()
.withName('My Article')
.withCulture('en-US')
.addProperty()
.withAlias('title')
.withValue('Hello World')
.done()
.addProperty()
.withAlias('body')
.withValue('<p>Article content</p>')
.done()
.done()
.build();
Key Methods :
withContentTypeAlias(alias) - Document type aliaswithTemplateAlias(alias) - Template aliaswithAction(action) - 'publishNew', 'save', etc.withParent(parentId) - Parent node IDaddVariant() - Add content variantCreate media items:
import { MediaBuilder } from '@umbraco/json-models-builders';
const media = new MediaBuilder()
.withName('My Image')
.withMediaTypeAlias('Image')
.addProperty()
.withAlias('umbracoFile')
.withValue({ src: '/media/image.jpg' })
.done()
.build();
Create data types:
import { DataTypeBuilder } from '@umbraco/json-models-builders';
const dataType = new DataTypeBuilder()
.withName('My Text Box')
.withSaveNewAction()
.build();
Add properties to document types:
documentTypeBuilder
.addGroup()
.withName('Content')
.addTextBoxProperty()
.withLabel('Title')
.withAlias('title')
.withDescription('Enter the page title')
.withMandatory(true)
.done()
.done()
.addRichTextProperty()
.withLabel('Body Text')
.withAlias('bodyText')
.done()
.addMediaPickerProperty()
.withLabel('Featured Image')
.withAlias('featuredImage')
.done()
.addContentPickerProperty()
.withLabel('Related Page')
.withAlias('relatedPage')
.done()
.addCustomProperty()
.withLabel('Custom Field')
.withAlias('customField')
.withDataTypeId('your-datatype-id')
.done()
import { BlockListDataTypeBuilder } from '@umbraco/json-models-builders';
const blockList = new BlockListDataTypeBuilder()
.withName('Content Blocks')
.addBlock()
.withContentElementTypeKey('hero-block-key')
.withLabel('Hero Block')
.done()
.addBlock()
.withContentElementTypeKey('text-block-key')
.withLabel('Text Block')
.done()
.withMin(1)
.withMax(10)
.withUseLiveEditing(true)
.build();
import { BlockGridDataTypeBuilder } from '@umbraco/json-models-builders';
const blockGrid = new BlockGridDataTypeBuilder()
.withName('Page Grid')
.withGridColumns(12)
.addBlock()
.withContentElementTypeKey('row-block-key')
.withLabel('Row')
.withColumnSpanOptions([6, 12])
.done()
.addBlock()
.withContentElementTypeKey('image-block-key')
.withLabel('Image')
.done()
.build();
import { ContentBuilder, BlockListValueBuilder } from '@umbraco/json-models-builders';
const content = new ContentBuilder()
.withContentTypeAlias('page')
.addVariant()
.withName('Home')
.addProperty()
.withAlias('blocks')
.addBlockListValue()
.addBlockListEntry()
.withContentTypeKey('hero-block-key')
.appendContentProperties('heading', 'Welcome')
.appendContentProperties('subheading', 'To our site')
.done()
.addBlockListEntry()
.withContentTypeKey('text-block-key')
.appendContentProperties('text', 'Some content here')
.done()
.done()
.done()
.done()
.build();
import { UserBuilder } from '@umbraco/json-models-builders';
const user = new UserBuilder()
.withName('Test User')
.withEmail('test@example.com')
.withUserGroups(['admin'])
.build();
import { UserGroupBuilder } from '@umbraco/json-models-builders';
const userGroup = new UserGroupBuilder()
.withName('Editors')
.withAlias('editors')
.withIcon('icon-users')
.appendSection('content')
.appendSection('media')
.addDefaultPermissions()
.withBrowseNode()
.withCreate()
.withUpdate()
.withPublish()
.done()
.withSaveNew()
.build();
userGroupBuilder
.addNodePermissions()
.forNode('content-node-id')
.withBrowseNode()
.withCreate()
.withUpdate()
.withDelete()
.withPublish()
.withUnpublish()
.done()
import { TemplateBuilder } from '@umbraco/json-models-builders';
const template = new TemplateBuilder()
.withName('Article Template')
.withAlias('articleTemplate')
.withContent(`@inherits Umbraco.Cms.Web.Common.Views.UmbracoViewPage
<h1>@Model.Name</h1>`)
.build();
import { StylesheetBuilder } from '@umbraco/json-models-builders';
const stylesheet = new StylesheetBuilder()
.withName('main.css')
.withContent('body { font-family: sans-serif; }')
.build();
import { ScriptBuilder } from '@umbraco/json-models-builders';
const script = new ScriptBuilder()
.withName('main.js')
.withContent('console.log("Hello");')
.build();
Generate safe aliases from names:
import { AliasHelper } from '@umbraco/json-models-builders';
// Convert to camelCase alias
AliasHelper.toAlias('My Page Type');
// Returns: "myPageType"
// Create safe alias with prefix/suffix
AliasHelper.toSafeAlias('My Page Type');
// Returns: "aMyPageTypea"
// Capitalize first character
AliasHelper.capitalize('hello');
// Returns: "Hello"
// Convert sentence to camelCase
AliasHelper.toCamelCase('My Awesome Example');
// Returns: "myAwesomeExample"
// Convert UUID to alias (removes dashes)
AliasHelper.uuidToAlias('123e4567-e89b-12d3-a456-426614174000');
// Returns: "123e4567e89b12d3a456426614174000"
import { DocumentTypeBuilder, AliasHelper } from '@umbraco/json-models-builders';
const name = 'Blog Post';
const alias = AliasHelper.toAlias(name);
const blogPost = new DocumentTypeBuilder()
.withName(name)
.withAlias(alias)
.withAllowAsRoot(true)
.withAllowCultureVariation(true)
.addGroup()
.withName('Content')
.addTextBoxProperty()
.withLabel('Title')
.withAlias('title')
.withMandatory(true)
.done()
.addTextBoxProperty()
.withLabel('Author')
.withAlias('author')
.done()
.addRichTextProperty()
.withLabel('Body')
.withAlias('body')
.done()
.done()
.addGroup()
.withName('Media')
.addMediaPickerProperty()
.withLabel('Featured Image')
.withAlias('featuredImage')
.done()
.done()
.build();
// Use in test
await umbracoApi.documentType.save(blogPost);
const heroBlock = new DocumentTypeBuilder()
.withName('Hero Block')
.withAlias('heroBlock')
.AsElementType() // Important for blocks!
.addGroup()
.withName('Content')
.addTextBoxProperty()
.withLabel('Heading')
.withAlias('heading')
.done()
.addTextBoxProperty()
.withLabel('Subheading')
.withAlias('subheading')
.done()
.addMediaPickerProperty()
.withLabel('Background Image')
.withAlias('backgroundImage')
.done()
.done()
.build();
const pageContent = new ContentBuilder()
.withContentTypeAlias('landingPage')
.withAction('publishNew')
.addVariant()
.withName('Landing Page')
.addProperty()
.withAlias('pageTitle')
.withValue('Welcome')
.done()
.addProperty()
.withAlias('contentBlocks')
.addBlockListValue()
.addBlockListEntry()
.withContentTypeKey(heroBlockKey)
.appendContentProperties('heading', 'Welcome to Our Site')
.appendContentProperties('subheading', 'Discover what we offer')
.done()
.addBlockListEntry()
.withContentTypeKey(textBlockKey)
.appendContentProperties('text', '<p>More content here...</p>')
.done()
.done()
.done()
.done()
.build();
Weekly Installs
71
Repository
GitHub Stars
17
First Seen
Feb 4, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
github-copilot53
opencode22
codex22
cursor21
amp20
kimi-cli20
Vue 3 调试指南:解决响应式、计算属性与监听器常见错误
11,900 周安装
Kotlin 2.0 开发指南:K2编译器、Ktor、Compose多平台与协程实战
70 周安装
SQL Server专家指南:T-SQL高级功能与Node.js集成实践
70 周安装
ADHD友好型设计专家:为ADHD大脑优化数字体验的UX设计原则与神经科学指南
70 周安装
.NET Core 专家 | 跨平台开发、.NET MAUI、云原生部署与 Native AOT 编译指南
71 周安装
Rails 7+ 专家 | Hotwire/Turbo 全栈开发 | 现代 Rails 模式与性能优化
71 周安装
链式验证(CoVe)系统:AI代码生成验证框架,消除幻觉错误,提升代码质量
71 周安装