CI / test (pull_request) Failing after 16s
Without this, Chrome blocks chrome.runtime.getURL('interceptors.js')
in Manifest V3, causing HLS detection to silently fail.
Added regression test to prevent future removal.
103 lines
3.7 KiB
JavaScript
103 lines
3.7 KiB
JavaScript
/**
|
|
* config_validation.test.mjs — Validate build configuration integrity.
|
|
*
|
|
* Prevents regressions like the phantom entry module issue that kfj001
|
|
* hit: vite.config.ts referenced probeFn.js and scrapeFn.js but those
|
|
* files were never created.
|
|
*/
|
|
import { describe, it } from './runner.mjs';
|
|
import { readFileSync, existsSync } from 'fs';
|
|
import { resolve, dirname } from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const root = resolve(__dirname, '..');
|
|
|
|
describe('Config: build integrity', () => {
|
|
it('vite.config.ts entry modules must exist as source files', () => {
|
|
const viteConfig = readFileSync(resolve(root, 'vite.config.ts'), 'utf8');
|
|
|
|
const matches = viteConfig.matchAll(/resolve\(__dirname,\s*'([^']+)'\)/g);
|
|
const inputEntries = [...matches]
|
|
.map(m => m[1])
|
|
.filter(p => p.startsWith('src/'));
|
|
|
|
const missing = inputEntries.filter(p => !existsSync(resolve(root, p)));
|
|
|
|
if (missing.length > 0) {
|
|
throw new Error(
|
|
`vite.config.ts references ${missing.length} missing file(s): ${missing.join(', ')}`
|
|
);
|
|
}
|
|
if (inputEntries.length === 0) {
|
|
throw new Error('No entry points found in vite.config.ts');
|
|
}
|
|
});
|
|
|
|
it('content.js must NOT use inline script injection (textContent)', () => {
|
|
const contentJs = readFileSync(resolve(root, 'src/content/content.js'), 'utf8');
|
|
|
|
// Strip comments before checking for textContent usage
|
|
const codeOnly = contentJs
|
|
.replace(/\/\*[\s\S]*?\*\//g, '') // block comments
|
|
.replace(/\/\/.*$/gm, ''); // line comments
|
|
|
|
if (codeOnly.includes('textContent')) {
|
|
throw new Error(
|
|
'content.js uses inline script injection (textContent). ' +
|
|
'Sites like Pornhub block inline scripts via CSP. Use script.src instead.'
|
|
);
|
|
}
|
|
if (!codeOnly.includes('script.src') || !codeOnly.includes('chrome.runtime.getURL')) {
|
|
throw new Error(
|
|
'content.js does not use CSP-safe script.src = chrome.runtime.getURL(...)'
|
|
);
|
|
}
|
|
});
|
|
|
|
it('interceptors.js must be a standalone file', () => {
|
|
const path = resolve(root, 'src/inject/interceptors.js');
|
|
if (!existsSync(path)) {
|
|
throw new Error('src/inject/interceptors.js does not exist');
|
|
}
|
|
const content = readFileSync(path, 'utf8');
|
|
if (!content.includes('(function ()') || !content.includes('})();')) {
|
|
throw new Error('interceptors.js should be a self-contained IIFE');
|
|
}
|
|
});
|
|
|
|
it('manifest.json content_scripts must reference content.js', () => {
|
|
const manifest = JSON.parse(
|
|
readFileSync(resolve(root, 'manifest.json'), 'utf8')
|
|
);
|
|
const cs = manifest.content_scripts;
|
|
if (!cs || !Array.isArray(cs)) {
|
|
throw new Error('manifest.json has no content_scripts');
|
|
}
|
|
const hasContentScript = cs.some(s => s.js && s.js.includes('content.js'));
|
|
if (!hasContentScript) {
|
|
throw new Error('No content_scripts entry references content.js');
|
|
}
|
|
});
|
|
|
|
it('manifest.json must declare interceptors.js in web_accessible_resources', () => {
|
|
const manifest = JSON.parse(
|
|
readFileSync(resolve(root, 'manifest.json'), 'utf8')
|
|
);
|
|
const war = manifest.web_accessible_resources;
|
|
if (!war || !Array.isArray(war)) {
|
|
throw new Error(
|
|
'manifest.json has no web_accessible_resources. ' +
|
|
'interceptors.js needs this for chrome.runtime.getURL() to work.'
|
|
);
|
|
}
|
|
const allResources = war.flatMap(entry => entry.resources || []);
|
|
if (!allResources.includes('interceptors.js')) {
|
|
throw new Error(
|
|
'manifest.json web_accessible_resources must include interceptors.js. ' +
|
|
'Without it, the browser blocks chrome.runtime.getURL("interceptors.js").'
|
|
);
|
|
}
|
|
});
|
|
});
|