gts-x / scripts /validate-test-pmws.ts
JAMES HAN
fix: QC matrix output changed from DOCX to XLSX (ExcelJS)
37d3ac2
Raw
History Blame Contribute Delete
4.27 kB
import { readFileSync } from "fs";
import { resolve } from "path";
const envContent = readFileSync(resolve(import.meta.dirname, "../.env"), "utf-8");
for (const line of envContent.split("\n")) {
const t = line.trim(); if (!t || t.startsWith("#")) continue;
const e = t.indexOf("="); if (e < 0) continue;
if (!process.env[t.slice(0, e)]) process.env[t.slice(0, e)] = t.slice(e + 1);
}
import { detectFormat } from "../src/lib/gts/formats";
import { richTextToPlain } from "../src/lib/gts/models/text";
import { runNetflixChecks } from "../src/lib/qc/netflix-checks";
import { runRuleChecks } from "../src/lib/qc/rule-checks";
import type { QCLine } from "../src/lib/qc/types";
const TEST_DIR = resolve(import.meta.dirname, "../test-pmws");
const manifest = JSON.parse(readFileSync(resolve(TEST_DIR, "manifest.json"), "utf-8")) as Array<{
lang: string;
file: string;
sensitiveTermCount: number;
glyphViolationCount: number;
expectedIssues: number;
[key: string]: any;
}>;
console.log(`=== QC VALIDATION: ${manifest.length} PMW files ===`);
console.log("");
let totalFiles = 0;
let passedFiles = 0;
let failedFiles = 0;
const failures: string[] = [];
for (const entry of manifest) {
totalFiles++;
const filePath = resolve(TEST_DIR, entry.file);
try {
// Parse PMW
const buf = readFileSync(filePath);
const handler = detectFormat(buf, entry.file);
if (!handler) {
console.log(`βœ— ${entry.lang.padEnd(8)} | PARSE FAILED: format not detected`);
failedFiles++;
failures.push(`${entry.lang}: format not detected`);
continue;
}
const doc = handler.read(buf, entry.file);
const track = doc.tracks[0];
const lines: QCLine[] = track.subtitles.map((sub, i) => ({
id: i + 1,
text: typeof sub.text === "string" ? sub.text : richTextToPlain(sub.text),
}));
// Run Netflix checks (glyph + sensitive terms)
const netflixIssues = runNetflixChecks(lines, entry.lang);
const glyphIssues = netflixIssues.filter((i) => i.category === "glyph");
const sensitiveIssues = netflixIssues.filter((i) => i.category === "sensitive");
// Also run rule checks
const ruleIssues = runRuleChecks(lines, entry.lang);
// Validate: did we detect at least as many as expected?
// Note: some terms may match multiple times in different contexts, so actual >= expected
const sensitiveOk = sensitiveIssues.length >= entry.sensitiveTermCount;
const glyphOk = glyphIssues.length >= entry.glyphViolationCount;
const status = sensitiveOk && glyphOk ? "βœ“" : "βœ—";
if (sensitiveOk && glyphOk) {
passedFiles++;
} else {
failedFiles++;
if (!sensitiveOk) failures.push(`${entry.lang}: sensitive ${sensitiveIssues.length}/${entry.sensitiveTermCount}`);
if (!glyphOk) failures.push(`${entry.lang}: glyph ${glyphIssues.length}/${entry.glyphViolationCount}`);
}
console.log(
`${status} ${entry.lang.padEnd(8)} | ` +
`sensitive: ${String(sensitiveIssues.length).padStart(4)}/${String(entry.sensitiveTermCount).padStart(4)} ` +
`${sensitiveOk ? "βœ“" : "βœ—"} | ` +
`glyph: ${String(glyphIssues.length).padStart(2)}/${String(entry.glyphViolationCount).padStart(2)} ` +
`${glyphOk ? "βœ“" : "βœ—"} | ` +
`rule: ${String(ruleIssues.length).padStart(3)} | ` +
`total: ${netflixIssues.length + ruleIssues.length}`
);
} catch (err) {
failedFiles++;
const msg = (err as Error).message.substring(0, 60);
console.log(`βœ— ${entry.lang.padEnd(8)} | ERROR: ${msg}`);
failures.push(`${entry.lang}: ${msg}`);
}
}
console.log("");
console.log("=== SUMMARY ===");
console.log(`Files: ${totalFiles}`);
console.log(`Passed: ${passedFiles}`);
console.log(`Failed: ${failedFiles}`);
console.log("");
if (failures.length > 0) {
console.log("FAILURES:");
for (const f of failures) console.log(` ${f}`);
} else {
console.log("ALL 32 LANGUAGES PASSED βœ“");
}
// Aggregate stats
const totalSensitive = manifest.reduce((s, e) => s + e.sensitiveTermCount, 0);
const totalGlyphs = manifest.reduce((s, e) => s + e.glyphViolationCount, 0);
console.log("");
console.log(`Injected: ${totalSensitive} sensitive terms + ${totalGlyphs} illegal glyphs across ${totalFiles} files`);