ソース情報
- リポジトリ
- microsoft/webui
- ソースの最終更新活動
- 2026年8月23日 18:02
- 検出された SKILL.md の言語
- 英語
- スター
- 82
- フォーク
- 22
インストール方法
デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。
ソースファイルを確認
インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。
メニュー
デフォルトでは、最初にソースを確認する Prompt が選択されています。直接コマンドに切り替えるか、ローカルコピーをダウンロードすることもできます。
インストールを決める前に、SKILL.md と SkillsMP に表示されている付属ファイルをお読みください。
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
直接コマンドでは確認用 Prompt が省略されます。実行前にソースを確認してください。
npx skills add https://github.com/microsoft/webui --skill testingコマンドは1行のまま表示されます。コピー前に横へスクロールして全体を確認してください。
ローカルで確認しますか?SkillsMP が現在取得できるファイルをダウンロードできます。
SKILL.md を表示中
Bump WebUI to an input release version, run the full gate, and prepare a release PR with bucketed changes since the previous v-prefixed tag.
Authoritative WebUI framework reference for generating correct application code - template-first authoring rules, template syntax, styling, interactivity, routing, state JSON, and anti-patterns.
Speed and memory performance rules for Rust crates, the Node addon, webui-framework, and webui-router.
| name | testing |
| description | Test patterns, fixture structure, and when to use E2E vs unit tests. |
Use this skill when writing or modifying tests in this repository.
Unit tests live alongside code in #[cfg(test)] modules. Integration tests go in each crate's tests/ directory.
cargo test -p microsoft-webui-handler # one crate
cargo test --workspace # all crates
cargo xtask test # via xtask (part of quality gate)
Every code change ships with tests:
| Change type | Requirement |
|---|---|
| New public API | At least one unit test per function/method |
| Bug fix | Regression test that fails without the fix |
| Performance change | Benchmark comparison (before/after) |
| Refactor | Existing tests pass unchanged |
Never remove, weaken, or #[ignore] an existing test unless explicitly asked.
webui-test-utils)The webui-test-utils crate provides common Rust test helpers, builders, and fixtures. Check it before writing new helpers - avoid duplicating across crates.
[dev-dependencies]
webui-test-utils = { path = "../webui-test-utils" }
The packages/webui-framework package uses Playwright for E2E tests. Each fixture is a mini WebUI app compiled and rendered by the real pipeline.
See tests/fixtures/README.md for the full reference.
tests/fixtures/<name>/
src/
index.html Page template (uses the component)
<tag-name>/
<tag-name>.html Component template (real WebUI syntax)
<tag-name>.css Component CSS (optional)
state.json Initial render state (all bound properties)
element.ts Component class (NO template registration)
<name>.spec.ts Playwright tests
webui.config.json Build options override (optional)
The test server (fixture-render.ts) auto-discovers fixtures with src/index.html, calls @microsoft/webui build() + render() to produce SSR HTML with template IIFEs, hydration markers, and inventory. The result is served at /<name>/fixture.html.
fixtures/<name>/src/index.html — page template:<!DOCTYPE html>
<html lang="en">
<head><meta charset="utf-8"><title>My Fixture</title></head>
<body>
<test-widget label="Hello"></test-widget>
</body>
</html>
fixtures/<name>/src/test-widget/test-widget.html — component template:<span class="label">{{label}}</span>
<span class="count">{{count}}</span>
<button class="inc" @click="{increment()}">+</button>
fixtures/<name>/state.json — initial state:{ "label": "Hello", "count": 0 }
fixtures/<name>/element.ts — component class only:// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { WebUIElement, attr, observable } from '../../../src/index.js';
export class TestWidget extends WebUIElement {
@attr label = 'Hello';
@observable count = 0;
increment(): void {
this.count += 1;
}
}
TestWidget.define('test-widget');
fixtures/<name>/<name>.spec.ts — Playwright tests:// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.
import { expect, test } from '@playwright/test';
test.describe('widget fixture', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/<name>/fixture.html');
await page.waitForFunction(() => {
const el = document.querySelector('test-widget');
return el && (el as any).$ready === true;
});
});
test('renders SSR content', async ({ page }) => {
await expect(page.locator('test-widget .label')).toHaveText('Hello');
await expect(page.locator('test-widget .count')).toHaveText('0');
});
test('updates on click', async ({ page }) => {
await page.locator('test-widget .inc').click();
await (page.()).();
});
});
| Feature | Syntax |
|---|---|
| Text binding | {{propertyName}} |
| Event binding | @click="{handler()}" or @click="{handler(e)}" |
| Boolean attribute | ?disabled="{{isDisabled}}" |
| Dynamic attribute | href="{{url}}" |
| Mixed attribute | href="/items/{{id}}" |
| Complex property | :items="{{items}}" |
| Element ref | w-ref="{myElement}" |
| Conditional | <if condition="show">...</if> |
| Negation | <if condition="!hidden">...</if> |
| Comparison | <if condition="count > 0">...</if> |
| Compound | <if condition="active && !busy">...</if> |
| Loop | <for each="item in items">...</for> |
| Nested loop | <for each="group in groups">...<for each="item in group.items">...</for></for> |
| Shadow DOM | <template shadowrootmode="open">...</template> |
| Root event | <template shadowrootmode="open" @click="{handler(e)}"> |
| Slot | <slot></slot> |
Components only created via document.createElement() (not in any template) need a false <if> in the page template to make their template IIFEs available:
<body>
<my-host></my-host>
<if condition="showChild"><my-child></my-child></if>
</body>
With state.json: { "showChild": false }.
Create webui.config.json to override build options:
{ "css": "module" }
Ordinary unwrapped fixture components exercise the Shadow default. Set
"dom": "light" in webui.config.json to exercise global Light rendering; a
fixture component requiring Shadow inside that build must author a sole
top-level <template shadowrootmode="open">. A sole bare top-level
<template> explicitly exercises Light even in the default Shadow fixture.
See fixtures/dom-default/ and
fixtures/light-dom/ for both paths through the real pipeline. Reserve manual
registerCompiledTemplate fixtures for raw template-metadata scenarios.
cd packages/webui-framework
pnpm build # build the framework
pnpm test # unit + E2E tests
npx playwright test # E2E only
npx playwright test tests/fixtures/<name>/ # one fixture
@microsoft/webui-test-support)The packages/webui-test-support package provides:
registerCompiledTemplate(name, meta) — register a raw TemplateMeta object (for manual/light-DOM fixtures)renderTemplateScript(name, meta) — render a template as an inline <script> tagrenderFixtures({ fixturesRoot }) — build+render all pipeline fixturesbuildFixtureEntries({ ... }) — bundle element.ts files via esbuildstartFixtureServer({ ... }) — start the HTTP fixture server| Scenario | Tool |
|---|---|
| Rust crate logic (parsing, rendering, state, expressions) | #[test] unit tests |
| Rust crate integration (full pipeline) | tests/ integration tests |
| Rust performance | cargo bench with Criterion |
| Framework hydration, reactive updates, DOM behavior | Playwright E2E fixtures |
| Router navigation, lazy loading, chain diffing | Playwright E2E fixtures |
| Template metadata encoding/decoding | Node unit tests (pnpm test:unit) |