Run Umbraco backoffice with mocked APIs for visual extension testing
version
1.0.0
location
managed
allowed-tools
Read, Write, Edit, Glob, Grep, Bash
Umbraco Mocked Backoffice
Status: This skill is currently awaiting an update from Umbraco to allow external extensions to use the mocked backoffice. The patterns documented here work when running from within the Umbraco-CMS source repository.
Run the full Umbraco backoffice UI with all API calls mocked - no .NET backend required.
When to Use
Visually test extensions during development
Rapid iteration without backend deployment
Test extensions in realistic UI environment
Demonstrate extensions without infrastructure
CI/CD testing without backend setup
Related Skills
umbraco-example-generator - Set up extensions for mocked backoffice (start here)
umbraco-testing - Master skill for testing overview
umbraco-unit-testing - Test extension logic in isolation
umbraco-e2e-testing - Test against a real Umbraco instance
Two Mocking Approaches
Extensions with custom APIs can use two mocking approaches:
Both approaches require MSW to be enabled (VITE_UMBRACO_USE_MSW=on) for core Umbraco APIs.
Setup
Create Your Extension
Use the umbraco-example-generator skill to set up your extension:
Invoke: skill: umbraco-example-generator
This covers:
Cloning Umbraco-CMS repository
Extension structure and src/index.ts requirements
Running with VITE_EXAMPLE_PATH and npm run dev
Add Testing Dependencies
{"devDependencies":{"@playwright/test":"^1.56"},"scripts":{"test:mock-repo":"playwright test --config=tests/mock-repo/playwright.config.ts","test:msw":"playwright test --config=tests/msw/playwright.config.ts"}}
The entry point conditionally loads MSW handlers or mock manifests based on environment:
// Entry point for external extension loading// Run from Umbraco.Web.UI.Client with:// VITE_EXAMPLE_PATH=/path/to/extension/Client VITE_UMBRACO_USE_MSW=on npm run dev// VITE_EXAMPLE_PATH=/path/to/extension/Client VITE_USE_MOCK_REPO=on VITE_UMBRACO_USE_MSW=on npm run dev// Register MSW handlers when running in MSW mode (but not mock-repo mode)if (import.meta.env.VITE_UMBRACO_USE_MSW === 'on' && import.meta.env.VITE_USE_MOCK_REPO !== 'on') {
import('./msw/handlers.js').then(({ createHandlers }) => {
const { addMockHandlers } = (windowasany).MockServiceWorker;
addMockHandlers(...createHandlers());
});
}
// Export manifests - use mock repository if VITE_USE_MOCK_REPO is setexportconst manifests = import.meta.env.VITE_USE_MOCK_REPO === 'on'
? (awaitimport('../tests/mock-repo/mock/index.js')).manifests
: (awaitimport('./manifests.js')).manifests;
Running Tests
Self-contained external-example support (automatic)
Loading an extension from a path outside the Umbraco client requires the client to
support an absolute VITE_EXAMPLE_PATH (via Vite's /@fs/) plus a shared-package resolver
so @umbraco-cms/backoffice, lit and @umbraco-ui/uui resolve to the client's single
copy. Stock released v18 only supports relative (./examples/...) paths.
To stay self-contained, this repo's mocked configs wire a Playwright globalSetup/globalTeardown
(plugins/umbraco-testing-skills/harness/mocked-backoffice/) that injects that support into
the client at UMBRACO_CLIENT_PATH before the dev server starts and reverts it afterwards
(file-backup based; it detects clients that already have the support and no-ops). So no CMS
branch is required — only a built v18 client (npm ci in Umbraco.Web.UI.Client).
First run against a freshly-patched client may re-optimize deps and briefly restart the dev
server (a flaky first navigation); the configs set retries to absorb it. Warm runs are stable.
Environment Variables
Variable
Value
Purpose
VITE_EXAMPLE_PATH
/path/to/extension/Client
Path to extension directory
VITE_UMBRACO_USE_MSW
on
Enable MSW for core Umbraco APIs
VITE_USE_MOCK_REPO
on
Use mock repository instead of MSW handlers
UMBRACO_CLIENT_PATH
/path/to/Umbraco.Web.UI.Client
Path to Umbraco client (for Playwright)
Manual Dev Server
cd /path/to/Umbraco-CMS/src/Umbraco.Web.UI.Client
# MSW mode (uses your handlers for custom APIs)
VITE_EXAMPLE_PATH=/path/to/extension/Client VITE_UMBRACO_USE_MSW=on npm run dev
# Mock repository mode (uses mock repository for custom APIs)
VITE_EXAMPLE_PATH=/path/to/extension/Client VITE_USE_MOCK_REPO=on VITE_UMBRACO_USE_MSW=on npm run dev
Run Tests
cd /path/to/extension/Client
# Set path to Umbraco clientexport UMBRACO_CLIENT_PATH=/path/to/Umbraco-CMS/src/Umbraco.Web.UI.Client
# Run MSW tests
npm run test:msw
# Run mock repository tests
npm run test:mock-repo
Check that your extension exports a manifests array from src/index.ts
Check browser console for errors
Verify VITE_EXAMPLE_PATH points to the Client directory
Tests timeout waiting for elements
Ensure the dev server is running with your extension loaded
Check the browser console for extension loading errors
Use longer timeouts (15000ms+) for initial element appearance
MSW handlers not intercepting requests
Check console for [MSW] logs showing handler registration
Verify handler URL patterns match the actual API calls
Use browser DevTools Network tab to see actual request URLs
Working Example
See tree-example in umbraco-backoffice-skills/examples/tree-example/Client/:
Path
Description
src/index.ts
Entry point with conditional manifest loading
src/msw/handlers.ts
MSW handlers for custom API
tests/mock-repo/
Mock repository tests
tests/msw/
MSW tests
cd tree-example/Client
export UMBRACO_CLIENT_PATH=/path/to/Umbraco-CMS/src/Umbraco.Web.UI.Client
npm run test:msw # Run MSW tests
npm run test:mock-repo # Run mock repository tests