- viewer.js: dynamic hls.js loading, HLS-aware panel creation, error handling - schema.json: hlsManifest and mediaType fields (optional, backward compatible) - types.ts: VideoEntry interface with MediaType type - isHls() null guard fix - tests: 39 tests (schema, viewer units, data flow, integration) - CI: GitHub/Gitea Actions workflow (npm test on push/PR) - deps: ajv, ajv-formats, jsdom for testing
This commit is contained in:
1 parent
baa72a4c33
commit
90c3425200
12 files changed
+2295
-27
No files matched your search
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
* Minimal test runner — describe/it with timing and summary.
|
||||
* No external dependencies. Import this from test files.
|
||||
*/
|
||||
|
||||
const suites = [];
|
||||
let currentSuite = null;
|
||||
let totalTests = 0;
|
||||
let totalPassed = 0;
|
||||
let totalFailed = 0;
|
||||
const failures = [];
|
||||
|
||||
export function describe(name, fn) {
|
||||
currentSuite = { name, tests: [], passed: 0, failed: 0, duration: 0 };
|
||||
suites.push(currentSuite);
|
||||
fn();
|
||||
currentSuite = null;
|
||||
}
|
||||
|
||||
export function it(name, fn) {
|
||||
if (!currentSuite) {
|
||||
throw new Error(`it() called outside describe(). Test: "${name}"`);
|
||||
}
|
||||
currentSuite.tests.push({ name, fn, async: typeof fn === 'function' });
|
||||
}
|
||||
|
||||
// Run all suites and print results
|
||||
export async function run() {
|
||||
let globalStart = Date.now();
|
||||
|
||||
for (const suite of suites) {
|
||||
const suiteStart = Date.now();
|
||||
process.stdout.write(`\n${suite.name}\n${'─'.repeat(suite.name.length + 2)}\n`);
|
||||
|
||||
for (const test of suite.tests) {
|
||||
totalTests++;
|
||||
const testStart = Date.now();
|
||||
try {
|
||||
const result = test.fn();
|
||||
if (result instanceof Promise) {
|
||||
await result;
|
||||
}
|
||||
const ms = Date.now() - testStart;
|
||||
totalPassed++;
|
||||
suite.passed++;
|
||||
process.stdout.write(` ✓ ${test.name} (${ms}ms)\n`);
|
||||
} catch (err) {
|
||||
const ms = Date.now() - testStart;
|
||||
totalFailed++;
|
||||
suite.failed++;
|
||||
failures.push({ suite: suite.name, test: test.name, error: err.message, stack: err.stack });
|
||||
process.stdout.write(` ✗ ${test.name} (${ms}ms)\n`);
|
||||
process.stdout.write(` → ${err.message}\n`);
|
||||
}
|
||||
}
|
||||
|
||||
suite.duration = Date.now() - suiteStart;
|
||||
}
|
||||
|
||||
const totalMs = Date.now() - globalStart;
|
||||
|
||||
process.stdout.write(`\n${'='.repeat(60)}\n`);
|
||||
process.stdout.write(`Results: ${totalPassed}/${totalTests} passed`);
|
||||
if (totalFailed > 0) {
|
||||
process.stdout.write(` | ${totalFailed} FAILED`);
|
||||
}
|
||||
process.stdout.write(` | ${totalMs}ms\n`);
|
||||
process.stdout.write(`${'='.repeat(60)}\n`);
|
||||
|
||||
if (failures.length > 0) {
|
||||
process.stdout.write(`\nFailures:\n`);
|
||||
for (const f of failures) {
|
||||
process.stdout.write(` [${f.suite}] ${f.test}\n`);
|
||||
process.stdout.write(` Error: ${f.error}\n`);
|
||||
process.stdout.write(` ${f.stack.split('\n')[1].trim()}\n`);
|
||||
}
|
||||
}
|
||||
|
||||
return { totalTests, totalPassed, totalFailed, totalMs, failures };
|
||||
}
|
||||
Reference in new issue
Block a user