Download source/scripts/check_huggingface_space.mjs from jackboyla/hendrix: direct link, hf CLI and curl.
- Browser
- Download file 9.31 kB
-
https://huggingface.co/spaces/jackboyla/hendrix/resolve/main/source/scripts/check_huggingface_space.mjs
- Command line
-
hf download hf://spaces/jackboyla/hendrix/source/scripts/check_huggingface_space.mjs
-
curl -L -o check_huggingface_space.mjs https://huggingface.co/spaces/jackboyla/hendrix/resolve/main/source/scripts/check_huggingface_space.mjs
9.31 kB
| // Check examples, real audio gains, live CPU inference, and responsive layouts. | |
| import assert from "node:assert/strict"; | |
| import { mkdir, writeFile } from "node:fs/promises"; | |
| import { dirname } from "node:path"; | |
| import { chromium } from "../demo/web/node_modules/playwright/index.mjs"; | |
| const base = process.env.HENDRIX_SPACE_URL || "https://jackboyla-hendrix.static.hf.space"; | |
| const resultPath = process.env.HENDRIX_SPACE_RESULT || "progress/evaluations/huggingface_space_redesign_check.json"; | |
| const screenshotPath = process.env.HENDRIX_SPACE_SCREENSHOT || "progress/evaluations/huggingface_space_redesign.png"; | |
| const browser = await chromium.launch({ headless: true, args: ["--disable-gpu"] }); | |
| const errors = [], failedResponses = [], audioUploads = [], results = []; | |
| async function check(page, embedded) { | |
| await page.addInitScript(() => { | |
| window.__blendTargets = []; | |
| const original = AudioParam.prototype.setTargetAtTime; | |
| AudioParam.prototype.setTargetAtTime = function (value, time, constant) { | |
| window.__blendTargets.push(value); | |
| return original.call(this, value, time, constant); | |
| }; | |
| }); | |
| const modelRequests = []; | |
| page.on("pageerror", error => errors.push(String(error))); | |
| page.on("request", request => { | |
| if (request.method() === "POST" && request.url().startsWith(base)) audioUploads.push(request.url()); | |
| if (request.url().includes("/transcribe")) audioUploads.push(request.url()); | |
| if (request.url().includes("/models/")) modelRequests.push(request.url()); | |
| }); | |
| page.on("response", response => { | |
| if (response.status() >= 400 && response.url().startsWith(base)) failedResponses.push({ url: response.url(), status: response.status() }); | |
| }); | |
| let app; | |
| if (embedded) { | |
| const repoId = process.env.HENDRIX_SPACE_REPO || "jackboyla/hendrix"; | |
| await page.goto(`https://huggingface.co/spaces/${repoId}`, { waitUntil: "domcontentloaded", timeout: 60_000 }); | |
| await page.waitForFunction(origin => [...document.querySelectorAll("iframe")].some(frame => frame.src.startsWith(origin)), base, { timeout: 60_000 }); | |
| app = page.frameLocator(`iframe[src^="${base}"]`).first(); | |
| } else { | |
| await page.goto(`${base}/local.html?backend=wasm`, { waitUntil: "domcontentloaded", timeout: 60_000 }); | |
| app = page.mainFrame(); | |
| } | |
| const download = app.getByRole("link", { name: "Download MIDI" }); | |
| await download.waitFor({ timeout: 60_000 }); | |
| assert.equal(await app.locator(".example-card").count(), 14); | |
| assert.doesNotMatch(await app.locator("body").textContent(), /D26|research checkpoint/); | |
| const isolation = await app.locator("html").evaluate(() => ({ isolated: crossOriginIsolated, secure: isSecureContext, sharedArrayBuffer: typeof SharedArrayBuffer !== "undefined" })); | |
| assert.equal(isolation.secure, true); | |
| if (!embedded) assert.equal(isolation.isolated, true); | |
| assert.deepEqual(modelRequests, [], "prepared examples must work without downloading the inference model"); | |
| // Verify every catalog asset, not just the featured example. | |
| const catalogResult = await app.locator("html").evaluate(async () => { | |
| const catalog = await (await fetch("/examples/catalog.json")).json(); | |
| const bad = []; | |
| for (const example of catalog.examples) { | |
| for (const url of [example.audio_url, example.notes_url]) { | |
| const response = await fetch(url); | |
| if (!response.ok) bad.push({ url, status: response.status }); | |
| } | |
| } | |
| return { count: catalog.examples.length, categories: [...new Set(catalog.examples.map(example => example.category))], bad }; | |
| }); | |
| assert.equal(catalogResult.count, 14); | |
| assert.deepEqual(catalogResult.bad, []); | |
| const blend = app.getByRole("slider", { name: "Original and MIDI blend" }); | |
| await blend.waitFor(); | |
| // MIDI endpoints stay disabled until the actual sampled-instrument synth is ready. | |
| await app.getByRole("button", { name: "MIDI", exact: true }).waitFor(); | |
| const synthStarted = Date.now(); | |
| while (await blend.isDisabled()) { | |
| if (Date.now() - synthStarted > 60_000) throw new Error("MIDI instrument sounds did not become ready"); | |
| await new Promise(resolve => setTimeout(resolve, 100)); | |
| } | |
| await app.getByRole("button", { name: "Play recording" }).click(); | |
| await app.getByRole("button", { name: "Pause playback" }).waitFor(); | |
| await blend.focus(); | |
| await page.keyboard.press("End"); | |
| await app.locator(".blend-readout").filter({ hasText: "100% MIDI" }).waitFor(); | |
| const midiGains = await app.locator("html").evaluate(() => window.__blendTargets.slice(-4)); | |
| assert.deepEqual(midiGains, [0, 1, 0, 0], "MIDI endpoint must mute original gain and open MIDI gain"); | |
| assert.equal(await app.getByRole("button", { name: "Pause playback" }).count(), 1); | |
| await page.keyboard.press("Home"); | |
| await app.locator(".blend-readout").filter({ hasText: "100% original" }).waitFor(); | |
| const originalGains = await app.locator("html").evaluate(() => window.__blendTargets.slice(-4)); | |
| assert.deepEqual(originalGains, [1, 0, 0, 0], "Original endpoint must open original gain and mute MIDI gain"); | |
| await page.keyboard.press("ArrowRight"); | |
| await app.locator(".blend-readout").filter({ hasText: "99% original" }).waitFor(); | |
| const mixedGains = await app.locator("html").evaluate(() => window.__blendTargets.slice(-4)); | |
| assert.deepEqual(mixedGains, [0.99, 0.01, 0, 0], "slider must drive both actual audio gains"); | |
| await app.getByRole("button", { name: "Pause playback" }).click(); | |
| const preparedMidi = await app.locator("html").evaluate(async (_html, url) => Array.from(new Uint8Array(await (await fetch(url)).arrayBuffer())), await download.getAttribute("href")); | |
| assert.equal(Buffer.from(preparedMidi).subarray(0, 4).toString(), "MThd"); | |
| // Browse and load a second source; then return to the featured mix. | |
| await app.getByRole("button", { name: "Guitar", exact: true }).click(); | |
| assert.equal(await app.locator(".example-card").count(), 4); | |
| await app.getByRole("button", { name: "Load Funk guitar", exact: true }).click(); | |
| await app.getByRole("heading", { name: "Funk guitar", exact: true }).waitFor(); | |
| await download.waitFor(); | |
| await app.getByRole("button", { name: "Pause playback" }).waitFor(); | |
| await app.getByRole("button", { name: "Pause playback" }).click(); | |
| await app.getByRole("button", { name: "All", exact: true }).click(); | |
| await app.getByRole("button", { name: "Load Full-band groove", exact: true }).click(); | |
| await app.getByRole("heading", { name: "Full-band groove", exact: true }).waitFor(); | |
| await app.getByRole("button", { name: "Pause playback" }).waitFor(); | |
| await app.getByRole("button", { name: "Pause playback" }).click(); | |
| assert.deepEqual(modelRequests, [], "all prepared listening checks must stay independent of inference download"); | |
| if (!embedded) { | |
| await mkdir(dirname(screenshotPath), { recursive: true }); | |
| await page.screenshot({ path: screenshotPath, fullPage: true }); | |
| await page.setViewportSize({ width: 390, height: 844 }); | |
| const layout = await app.locator("html").evaluate(() => ({ width: innerWidth, scrollWidth: document.documentElement.scrollWidth })); | |
| assert.ok(layout.scrollWidth <= layout.width, `mobile layout overflow: ${JSON.stringify(layout)}`); | |
| await page.screenshot({ path: screenshotPath.replace(/\.png$/, "_mobile.png"), fullPage: true }); | |
| await page.setViewportSize({ width: 1280, height: 1000 }); | |
| } | |
| // Check the live path too; use a short excerpt to keep this a bounded test. | |
| await app.locator(".limit-label select").selectOption("2.05"); | |
| const started = Date.now(); | |
| await app.getByRole("button", { name: "Transcribe audio" }).click(); | |
| await app.locator('.run-status:has-text("Audio never left this device"), .run-status.error').waitFor({ timeout: 180_000 }); | |
| const status = await app.locator(".run-status").textContent(); | |
| const diagnostic = await app.locator(".diagnostic-output").textContent().catch(() => ""); | |
| assert.match(status, /^[1-9]\d* notes from /, `${status}; ${diagnostic}`); | |
| assert.match(diagnostic, /backend=wasm cache=cpu/); | |
| const midi = await app.locator("html").evaluate(async (_html, url) => Array.from(new Uint8Array(await (await fetch(url)).arrayBuffer())), await download.getAttribute("href")); | |
| assert.equal(Buffer.from(midi).subarray(0, 4).toString(), "MThd"); | |
| const result = { embedded, ...isolation, catalog: catalogResult, midiGains, originalGains, mixedGains, | |
| preparedMidiBytes: preparedMidi.length, status, diagnostic, liveMidiBytes: midi.length, | |
| liveWallSeconds: (Date.now() - started) / 1000, modelRequests }; | |
| results.push(result); | |
| console.log(JSON.stringify(result)); | |
| } | |
| try { | |
| await check(await browser.newPage({ viewport: { width: 1280, height: 1000 } }), false); | |
| if (process.env.HENDRIX_SPACE_SKIP_EMBED !== "1") { | |
| await check(await browser.newPage({ viewport: { width: 1440, height: 1000 } }), true); | |
| } | |
| assert.deepEqual(errors, []); | |
| assert.deepEqual(failedResponses, []); | |
| assert.deepEqual(audioUploads, []); | |
| await mkdir(dirname(resultPath), { recursive: true }); | |
| await writeFile(resultPath, JSON.stringify({ base, results, errors, failedResponses, audioUploads }, null, 2) + "\n"); | |
| console.log(`Example, audio blend, MIDI, layout, and live transcription checks passed: ${resultPath}`); | |
| } finally { await browser.close(); } | |