test(ui): build the Face and Fine-tuning bundles in the global setup

The navigation spec serves the built Fine-tuning bundle, but nothing
built it, so two specs failed on a fresh checkout when the dist folder
was missing. The spec also built the Face bundle in a hook that every
worker runs, and a build rewrites the folder the other workers serve.

The global setup now builds Studio, Talk, Face and Fine-tuning once,
before the workers start. The spec builds the two bundles itself only
when it runs without the global setup.

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:57:40 +00:00
1 parent 8629744087
commit cfdfe8f7e9
3 files changed
+14 -6

No files matched your search

@@ -3,7 +3,7 @@ import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
import { ADMIN, MEMBER, app, sessionFor, mockAddons } from './addons-fixtures.js'
import { installStudioAddons, packagedApp } from './studio-addon.js'
import { buildAddonBundles, installStudioAddons, packagedApp } from './studio-addon.js'
import { FACE_MODEL, clipFile, faces, match, mockIdentity, people, photoFile } from './identity-fixtures.js'
// Studio and Talk are packaged add-ons, not built-in tiles: the specs install
@@ -449,14 +449,16 @@ test.describe('Add-on navigation: the Voice recognition page', () => {
})
// The built Face module, served the same way. dist/ is not committed, so the
// spec builds it once per run with the builder of the add-on.
// global setup builds it once per run with the builder of the add-on.
const FT_DIST = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../../addons/fine-tuning/ui/dist')
const FACE_DIST = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../../../addons/face/ui/dist')
const FACE_BASE = `/api/addons/face/assets/${'e'.repeat(64)}`
test.beforeAll(async () => {
const { build } = await import('../../../../addons/face/ui/build.mjs')
await build()
// The global setup has built the bundles already. A build rewrites the
// dist folder that every worker serves, so a worker must not start one.
if (process.env.E2E_ADDON_BUNDLES_BUILT) return
await buildAddonBundles(['face', 'fine-tuning'])
})
const faceApp = () => app({
+1 -1
View File
@@ -1,6 +1,6 @@
import { buildStudioAddons } from './studio-addon.js'
// Builds the Studio and Talk add-on bundles once, before the workers start.
// Builds the add-on bundles the specs serve once, before the workers start.
export default async function globalSetup() {
await buildStudioAddons()
}
+7 -1
View File
@@ -20,8 +20,14 @@ const built = new Map()
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']) {
export async function buildAddonBundles(ids) {
for (const id of ids) await import(path.join(addons, id, 'ui/build.mjs')).then(m => m.build())
}
// The add-ons the specs serve from their build output: Studio and Talk through
// installStudioAddons, Face and Fine-tuning through their own routes.
export async function buildStudioAddons(ids = ['studio', 'talk', 'face', 'fine-tuning']) {
await buildAddonBundles(ids)
process.env[BUILT] = '1'
}