Mock Server with Playwright
Mocked API + Playwright Cookbook
This cookbook demonstrates testing a Fusion Framework app end-to-end with a real browser,
against a real HTTP mock backend, using ffc mock-server and @playwright/test.
Overview
Most cookbooks show a framework feature in isolation. This one shows the integration between two
pieces of Fusion Framework tooling: @equinor/fusion-framework-cli-plugin-mock-server'sffc mock-server command (a standalone mock HTTP server, seepackages/cli-plugins/mock-server) and Playwright'swebServer option, which builds the application, starts both the mock server and the preview
server, and tears the servers down after the test run.
How it works
mocks/people.mock.tsoverrides an existing service-discovery entry
withserviceDiscovery: 'merge', inheriting the bundledpeopleschema while replacing itsgetPersonresponse.mocks/aurora-api.mock.tstemporarily adds the fictional
pre-productionaurora-apiservice withserviceDiscovery: 'new', its ownaurora-api.openapi.jsonschema, and deterministic component
values. It is absent from real service discovery during development, but must be registered
there before release.mocks/my-api.mock.tsdefinesmy-api, imports its OpenAPI schema,
and usesserviceDiscovery: falseto keep this custom service out of discovery.app.config.local.tsconfiguresmy-apidirectly athttp://my-api.localhost:4010for both normal and--mockdevelopment.ffc app serve --mock http://localhost:4010serves the production build, resolvesapp.config.local.ts, and points service discovery at the mock server. The
preview server automatically creates local proxy routes for the bundled services.src/routes/index.tsx,src/routes/people/index.tsx, andsrc/routes/aurora/index.tsxgive each service lifecycle
scenario its own page. The direct-only scenario is the root index; named pages live in their own
directories. Each page callsuseHttpClient()directly so its explanation and the framework
integration agents should reproduce live together in one retrieval-friendly file.playwright.config.tsstartsffc mock-serverand runsffc app build
followed byffc app serve --mockas PlaywrightwebServerentries, then runs the
specs underplaywright/against the built app.
Running it
pnpm --filter @equinor/fusion-framework-cookbook-app-react-mock-playwright testTo run the pieces individually while developing:
pnpm mock:server # ffc mock-server ./mocks --port 4010
pnpm mock:dev # ffc app dev --mock http://localhost:4010, in another terminal
ffc app build
ffc app serve --mock http://localhost:4010 # in another terminalOr start both processes together with pnpm dev:mock.
For normal development with real service discovery plus selected local services, manually startpnpm mock:server, then run pnpm dev in another terminal. Plain ffc app dev discovers*.mock.ts files under mockServer.path (default mocks) and merges visible defineService
entries into real discovery by key.
It does not start ffc mock-server; unreachable local service URIs remain unreachable.
Key concepts
ffc mock-serverserves any directory of<name>.mock.tsservice modules over HTTP,
independent of Vite or the dev server — see the plugin's own
README for the full command reference.ffc app dev --mockandffc app serve --mockuse the mock server's discovery endpoint and
generate proxy routes automatically, so the app needs no customdev-server.config.ts. These
modes ignore normal discovery and use only mock-server presets plus localdefineService
modules.app serverequires an existing build; Playwright runsffc app buildbefore starting
the preview server.defineServicecontrols mock-server behavior and whether a service is advertised. Plainffc app devpoints visible definitions at the manually started mock server;'merge'overrides an existing entry,'new'adds a pre-production service and rejects key
collisions,'replace'deliberately replaces a complete definition, andfalsekeeps a
genuinely custom endpoint likemy-apidirect-only becauseapp.config.local.tssupplies its URL.defineServicekeeps a service's schema,components, declarativeroutes, andmiddlewarein one module.serviceDiscovery: 'replace'defines a complete service;serviceDiscovery: 'merge'inherits an earlier service schema. A declarative route remains
overridable at runtime via/@fusion-mock/:service/:operationId
(seeplaywright/playwright-override.spec.ts), whilemiddlewarealways wins over the generated mock and runtime override.- Playwright's
webServerarray starts and stops each process for the whole test run — do
not startffc mock-serveryourself in the background; it is designed to run in the
foreground and shut down onSIGINT/SIGTERM.