Run on every browser
Run a project across Chromium, Edge, Firefox, WebKit and mobile emulation.
Which browsers SDODS supports, how the project YAML declares them, how -b and --project-matrix
select them, how Edge differs from the engines Playwright downloads, and how to exclude a scenario
from one engine without hiding the exclusion in code.
Supported browsers
| Name | Engine | Device profile | Playwright installs it as |
|---|---|---|---|
chromium | Chromium | Desktop Chrome | a build, into the browser cache |
edge | Chromium | Desktop Edge | the msedge channel, system-wide |
firefox | Gecko | Desktop Firefox | a build, into the browser cache |
webkit | WebKit | Desktop Safari | a build, into the browser cache |
mobile-chrome | Chromium | Pixel 7 | a build, into the browser cache |
mobile-safari | WebKit | iPhone 15 | a build, into the browser cache |
Every one of these is provisioned by Playwright — sdods browsers install -b <name> is all you
need for any of them. Edge differs only in where the binary lands: Playwright ships no Edge
build (its download manifest lists chromium, firefox and webkit only), so playwright install msedge runs Microsoft's own installer and Edge ends up in the normal application location rather
than under ~/.cache/ms-playwright. That is why sdods browsers list finds it by path, and why
its row shows a channel.
Edge is the real browser, not a user agent
edge runs Microsoft Edge through Playwright's msedge channel. This is worth stating plainly
because the near-miss is invisible: Playwright's Desktop Edge device profile only sets an Edge
user-agent string, so a setup that stops there launches bundled Chromium that reports itself as
Edge. Tests pass, screenshots look right, and nothing is testing Edge. SDODS sets the channel, so
-b edge starts Edge itself — a different binary at a different version from the bundled Chromium,
which is the whole reason for running it.
Two consequences follow from the channel landing system-wide:
sdods browsers install -b edgeruns Microsoft's own installer instead of fetching a build into the Playwright cache — on Linux and
Windows it needs privileges, and sdods browsers list finds it by its installed path rather than in
the cache. And sdods run -b edge on a machine without Edge stops before running anything:
✖ NOT_SUPPORTED: edge is not installed.
hint: Run `sdods browsers install -b edge`. edge is a system browser: Playwright runs the
vendor installer rather than downloading a build.A freshly installed Edge sets up its profile on first launch. A headless run started before that
finishes fails with browserType.launch: Target page, context or browser has been closed. Open
Edge once, or run sdods browsers warmup -b edge, and the run is deterministic afterwards. CI
jobs that provision a browser and use it in the same job should include that step.
Other branded channels are still set with channel: in the project YAML. For edge, a same-family
channel refines it — channel: msedge-beta moves the edge target to the beta build — while a
chrome channel is ignored rather than applied, so a project that runs both Chromium and Edge can
never end up with Google Chrome reported under Edge's name.
Declare and select
browsers: [chromium, edge, firefox, webkit]bun run sdods run -p demo-shop -l ui -b chromium
bun run sdods run -p demo-shop -l ui -b firefox -b webkit
bun run sdods run -p demo-shop -l ui -b edge
bun run sdods run -p demo-shop -l ui --list # prints the generated run target namesA browser must be listed in the project's browsers: before -b will accept it; sdods run
rejects anything else with the list of what is enabled.
Each browser becomes a run target named demo-shop--ui--<browser>. Generation happens once per layer; browsers share the generated spec files.
The whole matrix
bun run sdods run -p demo-shop --project-matrix -t @smokeExclude a scenario from one engine
@ui @regression @skip:webkit
Scenario: Uses a Chromium-only DevTools featureEvery name in the table above is a valid @skip: value, edge included.
@skip:<browser> is validated by sdods lint and applied by a hook. Do not branch inside steps on the browser name; the exclusion stays visible in the feature and in reports.
Continuous integration
Pull requests run @smoke on Chromium; merges to main run @regression; a nightly job runs the full matrix including mobile emulation. See Sharding and CI.
The generic matrix comes from ci.browsers when a project sets it, and from browsers: otherwise.
That is how a project declares Edge for local and on-demand runs without putting a system browser
into every matrix job:
browsers: [chromium, edge, firefox, webkit]
ci:
browsers: [chromium, firefox, webkit]