A simulated DOM cannot tell you whether a flex row really gives its second column 200 pixels or whether WebKit 15,343 accepts your code. A browser runner keeps the fast unit-test workflow but executes each test file inside a real browser.

Karma: deprecated
Karma 11,960 (github.com/karma-runner/karma (https://github.com/karma-runner/karma 11,960 )) was created by the AngularJS 25,759 team and was long the standard way to run Jasmine 126 , Mocha 120,373 or QUnit 67,568 in browsers. It starts a server on port 9876, captures browsers that connect over WebSockets, loads your source and tests inside an iframe, and collects the results. Its README now states that Karma is deprecated and is not accepting new features or general bug fixes; the last release, 6.4.4, shipped in July 2024. It recommends Web Test Runner, jasmine-browser-runner, Jest 62,362 or Vitest 102,989 instead; new Angular 42,088 CLI projects use Vitest, and Angular publishes a Karma migration guide. Do not start new projects on Karma.
Web Test Runner
Web Test Runner (modern-web.dev (https://modern-web.dev/docs/test-runner/overview/)), from the Modern Web project, reached 1.0 in July 2026. It serves each test file as a native ES module through its dev server, runs files in parallel and in isolation, launches your local Chrome 1 by default, and can drive Firefox 555 and WebKit through Playwright 26,280 , Puppeteer 164,069 , Selenium 44,681 or WebdriverIO 417,092 launchers. Tests use Mocha's describe and it, which the runner provides as globals; bring Chai 206,458 for assertions.
import { expect } from "chai";
it("lays out a flex row with real CSS", () => {
document.body.innerHTML = `
<div style="display:flex; width:300px">
<div style="flex:1">Menu</div>
<div style="flex:2">Content</div>
</div>`;
const [menu, main] = document.querySelectorAll("div > div");
expect(menu.getBoundingClientRect().width).to.equal(100);
expect(main.getBoundingClientRect().width).to.equal(200);
});
it("runs in a real browser", () => {
expect(navigator.userAgent).to.match(/Chrome/);
expect(CSS.supports("container-type", "inline-size")).to.be.true;
});> npm install -D @web/test-runner chai > npx web-test-runner "browser/**/*.test.js" --node-resolve Chrome: |██████████████████████████████| 1/1 test files | 2 passed, 0 failed Finished running tests in 0.5s, all tests passed!
The same widths in jsdom 21,691 would be 0. --node-resolve rewrites bare imports such as "chai" into paths the browser can fetch, which is exactly what the import maps of The Front-End Toolchain do by hand. Add --watch to rerun changed files, or --manual --open to debug the tests in a visible browser with DevTools.