test(whisper): fix playwright ESM loading via dynamic imports
This commit is contained in:
parent
2fd9f05652
commit
b2bb36911a
3 changed files with 18 additions and 74 deletions
|
|
@ -6,6 +6,7 @@ import 'dotenv/config';
|
||||||
*/
|
*/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
testDir: './tests',
|
testDir: './tests',
|
||||||
|
tsconfig: './tsconfig.json',
|
||||||
timeout: 30 * 1000,
|
timeout: 30 * 1000,
|
||||||
outputDir: './tests/results',
|
outputDir: './tests/results',
|
||||||
globalTeardown: './tests/global-teardown.ts',
|
globalTeardown: './tests/global-teardown.ts',
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from '@playwright/test';
|
||||||
import { readFile } from 'fs/promises';
|
import { readFile } from 'fs/promises';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { alignAudioWithText } from '../../compute/core/src/whisper/align';
|
|
||||||
|
|
||||||
test.describe('whisper alignment smoke', () => {
|
test.describe('whisper alignment smoke', () => {
|
||||||
test('runs ONNX alignment end-to-end without decoder reshape errors', async () => {
|
test('runs ONNX alignment end-to-end without decoder reshape errors', async () => {
|
||||||
|
|
@ -11,12 +10,12 @@ test.describe('whisper alignment smoke', () => {
|
||||||
const audioBytes = await readFile(audioPath);
|
const audioBytes = await readFile(audioPath);
|
||||||
const buffer = audioBytes.buffer.slice(audioBytes.byteOffset, audioBytes.byteOffset + audioBytes.byteLength);
|
const buffer = audioBytes.buffer.slice(audioBytes.byteOffset, audioBytes.byteOffset + audioBytes.byteLength);
|
||||||
|
|
||||||
const alignments = await alignAudioWithText(
|
const { runWhisperAlignmentFromAudioBuffer } = await import('@openreader/compute-core/local-runtime');
|
||||||
buffer,
|
const { alignments } = await runWhisperAlignmentFromAudioBuffer({
|
||||||
'This is a sample sentence used to validate whisper alignment execution.',
|
audioBuffer: buffer,
|
||||||
undefined,
|
text: 'This is a sample sentence used to validate whisper alignment execution.',
|
||||||
{ lang: 'en' },
|
lang: 'en',
|
||||||
);
|
});
|
||||||
|
|
||||||
expect(alignments.length).toBe(1);
|
expect(alignments.length).toBe(1);
|
||||||
expect(Array.isArray(alignments[0].words)).toBe(true);
|
expect(Array.isArray(alignments[0].words)).toBe(true);
|
||||||
|
|
|
||||||
|
|
@ -1,71 +1,15 @@
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from '@playwright/test';
|
||||||
import { createHash } from 'crypto';
|
|
||||||
import { mkdir, mkdtemp, readFile, rm, writeFile } from 'fs/promises';
|
|
||||||
import { tmpdir } from 'os';
|
|
||||||
import path from 'path';
|
|
||||||
import {
|
|
||||||
createSingleflightRunner,
|
|
||||||
ensureWhisperArtifacts,
|
|
||||||
} from '../../compute/core/src/whisper/model';
|
|
||||||
|
|
||||||
function sha256(bytes: Uint8Array): string {
|
test.describe('whisper model bootstrap via local-runtime', () => {
|
||||||
return createHash('sha256').update(bytes).digest('hex');
|
test('is idempotent across concurrent calls', async () => {
|
||||||
}
|
test.setTimeout(180000);
|
||||||
|
const { ensureComputeModels } = await import('@openreader/compute-core/local-runtime');
|
||||||
test.describe('whisper ensure model helpers', () => {
|
await expect(
|
||||||
test('downloads and verifies artifacts, and repairs checksum mismatch', async () => {
|
Promise.all([
|
||||||
const root = await mkdtemp(path.join(tmpdir(), 'openreader-whisper-model-test-'));
|
ensureComputeModels(),
|
||||||
const artifactBytes = new TextEncoder().encode('artifact-content-v1');
|
ensureComputeModels(),
|
||||||
const artifactHash = sha256(artifactBytes);
|
ensureComputeModels(),
|
||||||
const artifactPath = 'onnx/encoder_model_int8.onnx';
|
]),
|
||||||
const target = path.join(root, artifactPath);
|
).resolves.toBeDefined();
|
||||||
|
|
||||||
try {
|
|
||||||
// Seed a corrupted file to verify repair behavior.
|
|
||||||
await mkdir(path.dirname(target), { recursive: true });
|
|
||||||
await writeFile(target, new Uint8Array([0, 1, 2, 3]));
|
|
||||||
|
|
||||||
let fetchCount = 0;
|
|
||||||
await ensureWhisperArtifacts({
|
|
||||||
modelDir: root,
|
|
||||||
artifacts: [
|
|
||||||
{
|
|
||||||
path: artifactPath,
|
|
||||||
sha256: artifactHash,
|
|
||||||
size: artifactBytes.byteLength,
|
|
||||||
url: 'https://example.local/fake-artifact',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
fetchImpl: async () => {
|
|
||||||
fetchCount += 1;
|
|
||||||
return new Response(artifactBytes, { status: 200 });
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const repaired = await readFile(target);
|
|
||||||
expect(repaired.byteLength).toBe(artifactBytes.byteLength);
|
|
||||||
expect(sha256(repaired)).toBe(artifactHash);
|
|
||||||
expect(fetchCount).toBe(1);
|
|
||||||
} finally {
|
|
||||||
await rm(root, { recursive: true, force: true });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
test('singleflight runner deduplicates concurrent work', async () => {
|
|
||||||
let runs = 0;
|
|
||||||
const run = createSingleflightRunner(async () => {
|
|
||||||
runs += 1;
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 30));
|
|
||||||
return 'ok';
|
|
||||||
});
|
|
||||||
|
|
||||||
const [a, b, c] = await Promise.all([run(), run(), run()]);
|
|
||||||
expect(a).toBe('ok');
|
|
||||||
expect(b).toBe('ok');
|
|
||||||
expect(c).toBe('ok');
|
|
||||||
expect(runs).toBe(1);
|
|
||||||
|
|
||||||
await run();
|
|
||||||
expect(runs).toBe(2);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue