test(ui): build the add-on bundles once for the whole run

Each worker built the Studio and Talk bundles into the same dist
directory, and the build empties that directory first. A worker that
started, or restarted after a failure, removed the files another worker
was serving, so a Studio spec saw "the style sheet of the add-on could
not be loaded". Build once in a global setup before the workers start.
A run without the setup still builds per worker.

Assisted-by: Claude Code:claude-sonnet-5-5 node
Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
Ettore Di Giacinto committed 2026-10-21 00:20:01 +00:00
1 parent c2e2877fbf
commit 958f584b36
3 files changed
+22 -1

No files matched your search

+6
View File
@@ -0,0 +1,6 @@
import { buildStudioAddons } from './studio-addon.js'
// Builds the Studio and Talk add-on bundles once, before the workers start.
export default async function globalSetup() {
await buildStudioAddons()
}
+15 -1
View File
@@ -13,8 +13,22 @@ const DIGEST = 'e'.repeat(64)
const TYPES = { js: 'text/javascript', css: 'text/css', png: 'image/png' }
const built = new Map()
// Builds the bundle once per worker, so a spec never runs against a stale one.
// The build empties and rewrites addons/<id>/ui/dist, and every worker serves
// its files, so two builds at once leave a running spec without its style sheet
// or module. The run builds once, before any worker starts (global-setup.js),
// and says so in this variable.
const BUILT = 'E2E_ADDON_BUNDLES_BUILT'
// Builds the bundles for the whole run. Called by the Playwright global setup.
export async function buildStudioAddons(ids = ['studio', 'talk']) {
for (const id of ids) await import(path.join(addons, id, 'ui/build.mjs')).then(m => m.build())
process.env[BUILT] = '1'
}
// The bundle of one add-on. A run that did not go through the global setup
// builds it here, once per worker, so a spec never runs against a stale one.
function build(id) {
if (process.env[BUILT]) return Promise.resolve(path.join(addons, id, 'ui/dist'))
if (!built.has(id)) built.set(id, import(path.join(addons, id, 'ui/build.mjs')).then(m => m.build()))
return built.get(id)
}
+1
View File
@@ -13,6 +13,7 @@ export default defineConfig({
'**/addons-upgrade.spec.js', '**/tables-acceptance.spec.js', '**/tables-artifacts.spec.js',
'**/tables-ui.spec.js',
],
globalSetup: './e2e/global-setup.js',
timeout: 30_000,
retries: process.env.CI ? 2 : 0,
// TEMPORARY: cap parallelism. Playwright's default (cores/2) oversubscribes