mirror of
https://github.com/Matysh/houseplan-card
synced 2026-09-30 19:58:50 +00:00
test: не считать README входами харнесса (#672)
Issue: #672 User-Visible: no
This commit is contained in:
committed by
claude[bot]
parent
8b775247a7
commit
71c8a87e67
@@ -143,9 +143,11 @@ const PY_FROM = /^\s*from\s+([\w.]+)\s+import/gm;
|
||||
const PY_IMPORT = /^\s*import\s+([\w.]+)/gm;
|
||||
const PY_PATH_JOIN = /((?:"[\w.-]+"\s*\/\s*)+"[\w.-]+")/g;
|
||||
const REL_EXEC_LITERAL = /['"]((?:\.\.?\/)*[\w.-]+(?:\/[\w.-]+)*\.(?:mjs|py))['"]/g;
|
||||
const REL_DOC_LITERAL = /['"]((?:\.\.?\/)+[\w.-]+(?:\/[\w.@-]+)*\.md)['"]/gi;
|
||||
|
||||
const toPosix = (p) => p.replaceAll('\\', '/');
|
||||
const BINARY = /\.(png|jpe?g|gif|webp|svg|ico|woff2?|ttf|pdf|zip)$/i;
|
||||
const DIRECTORY_DOCUMENTATION = /\.md$/i;
|
||||
|
||||
/** `test-build/foo.js` — скомпилированный `src/foo.ts` (tsconfig.test.json). */
|
||||
const mapTestBuild = (rel) => {
|
||||
@@ -200,6 +202,13 @@ export function referencesOf(file, rawText) {
|
||||
for (const re of [JS_IMPORT, JS_DYNAMIC, JS_REQUIRE]) {
|
||||
for (const m of text.matchAll(re)) resolveJsSpecifier(file, m[1]).forEach((p) => code.add(norm(p)));
|
||||
}
|
||||
// Документ внутри названного каталога не является runtime-входом сам по
|
||||
// себе. Но точный относительный путь к Markdown в исполняемом коде — это
|
||||
// явная зависимость (например, release-gate действительно читает README).
|
||||
for (const m of text.matchAll(REL_DOC_LITERAL)) {
|
||||
const rel = norm(posix.join(posix.dirname(file), m[1]));
|
||||
if (!rel.startsWith('..')) data.add(rel);
|
||||
}
|
||||
}
|
||||
if (file.endsWith('.py')) {
|
||||
// pytest подхватывает conftest.py каталога без импорта — это код теста
|
||||
@@ -279,12 +288,12 @@ export function closure(root, entries, { tracked = trackedFiles(root), stopAt =
|
||||
}
|
||||
for (const ref of data) {
|
||||
if (trackedSet.has(ref)) { note(ref, file); seen.add(ref); continue; }
|
||||
// каталог по строке — данные; бинарные файлы под ним код по строке не
|
||||
// читает, а overlay эталонов принадлежит только своей проверке (#573):
|
||||
// и то и другое входит в golden явным корнем
|
||||
// Каталог по строке — данные. Бинарные файлы и документация под ним код
|
||||
// по одной строке-каталогу не читает; точный Markdown-путь выше остаётся
|
||||
// честной зависимостью. Overlay эталонов принадлежит только golden (#573).
|
||||
if (isDir(ref)) {
|
||||
for (const f of tracked) {
|
||||
if (f.startsWith(`${ref}/`) && !BINARY.test(f) && !isBaselineOverlay(f)) { note(f, file); seen.add(f); }
|
||||
if (f.startsWith(`${ref}/`) && !BINARY.test(f) && !DIRECTORY_DOCUMENTATION.test(f) && !isBaselineOverlay(f)) { note(f, file); seen.add(f); }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -301,7 +310,7 @@ const BUILD_INPUTS = ['src/**', 'package.json', 'package-lock.json', 'rollup.con
|
||||
'scripts/bundle-sync.mjs', 'scripts/bundle-tree.mjs'];
|
||||
/** Протокол браузерного харнеса: страница, сервер, гард исключений, compat-хелперы. */
|
||||
const BROWSER_PROTOCOL = ['demo/serve.mjs', 'demo/srv/demo.html', 'demo/bundle-freshness.mjs',
|
||||
'demo/editor-runtime-compat.mjs', 'demo/iso-runtime-compat.mjs', 'demo/guard/**', 'demo/helpers/hp-test.mjs'];
|
||||
'demo/editor-runtime-compat.mjs', 'demo/iso-runtime-compat.mjs', 'demo/guard/*.mjs', 'demo/helpers/hp-test.mjs'];
|
||||
const WORKFLOW = ['.github/workflows/validate.yml'];
|
||||
/** Протокол реюза: кто считает ключ, тот и вход (§5.1 protocol). */
|
||||
const REUSE_PROTOCOL = ['scripts/gate-reuse.mjs', 'scripts/check-inputs.mjs', 'scripts/ci-proof.mjs'];
|
||||
@@ -351,7 +360,7 @@ export const CHECKS = {
|
||||
},
|
||||
golden: {
|
||||
entries: ['demo/golden/run.mjs'],
|
||||
roots: [...BUILD_INPUTS, 'demo/golden/**', ...BROWSER_PROTOCOL, ...REUSE_PROTOCOL, ...WORKFLOW],
|
||||
roots: [...BUILD_INPUTS, ...BASELINE_OVERLAY, ...BROWSER_PROTOCOL, ...REUSE_PROTOCOL, ...WORKFLOW],
|
||||
reuse: true,
|
||||
},
|
||||
performance_smoke: {
|
||||
|
||||
@@ -5218,6 +5218,47 @@ const MUTANT_DEFINITIONS = [
|
||||
replace: 'export const GUARDED_DATA_ROOTS = []; // mutant: asset data is not audited',
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'harness-directory-docs-leak-into-inputs',
|
||||
guard: 'node --test --test-name-pattern="#672" test/check-inputs.test.mjs test/gate-reuse.test.mjs',
|
||||
because: '#672: строка-каталог обозначает runtime-корпус, а не документацию рядом с ним; '
|
||||
+ 'без фильтра README снова выбирает тяжёлые jobs и меняет их reuse keys',
|
||||
patches: [{
|
||||
file: 'scripts/check-inputs.mjs',
|
||||
find: ' if (f.startsWith(`${ref}/`) && !BINARY.test(f) && !DIRECTORY_DOCUMENTATION.test(f) && !isBaselineOverlay(f)) { note(f, file); seen.add(f); }',
|
||||
replace: ' if (f.startsWith(`${ref}/`) && !BINARY.test(f) && !isBaselineOverlay(f)) { note(f, file); seen.add(f); }',
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'explicit-markdown-read-dropped-from-inputs',
|
||||
guard: 'node --test --test-name-pattern="#672: документация каталога" test/check-inputs.test.mjs',
|
||||
because: '#672: фильтр каталогов не должен скрывать Markdown, который код читает по точному пути',
|
||||
patches: [{
|
||||
file: 'scripts/check-inputs.mjs',
|
||||
find: ' for (const m of text.matchAll(REL_DOC_LITERAL)) {',
|
||||
replace: " for (const m of ''.matchAll(REL_DOC_LITERAL)) { // mutant: explicit docs disappear",
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'browser-protocol-recaptures-guard-readme',
|
||||
guard: 'node --test --test-name-pattern="#672: README каталогов" test/check-inputs.test.mjs',
|
||||
because: '#672: browser protocol must name executable guards, not every document in demo/guard',
|
||||
patches: [{
|
||||
file: 'scripts/check-inputs.mjs',
|
||||
find: " 'demo/editor-runtime-compat.mjs', 'demo/iso-runtime-compat.mjs', 'demo/guard/*.mjs', 'demo/helpers/hp-test.mjs'];",
|
||||
replace: " 'demo/editor-runtime-compat.mjs', 'demo/iso-runtime-compat.mjs', 'demo/guard/**', 'demo/helpers/hp-test.mjs'];",
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'golden-root-recaptures-golden-readme',
|
||||
guard: 'node --test --test-name-pattern="#672: README каталогов" test/check-inputs.test.mjs',
|
||||
because: '#672: golden needs the accepted baseline overlay, not a broad root that also owns README',
|
||||
patches: [{
|
||||
file: 'scripts/check-inputs.mjs',
|
||||
find: ' roots: [...BUILD_INPUTS, ...BASELINE_OVERLAY, ...BROWSER_PROTOCOL, ...REUSE_PROTOCOL, ...WORKFLOW],',
|
||||
replace: " roots: [...BUILD_INPUTS, 'demo/golden/**', ...BROWSER_PROTOCOL, ...REUSE_PROTOCOL, ...WORKFLOW],",
|
||||
}],
|
||||
},
|
||||
{
|
||||
id: 'guard-inputs-ignore-wrapper-defaults',
|
||||
guard: 'node --test --test-name-pattern="#492 §8.2" test/mutation-gate.test.mjs',
|
||||
@@ -12140,8 +12181,8 @@ const MUTANT_DEFINITIONS = [
|
||||
+ 'а ключи, которые proof предъявляет как «те же входы», меняются от PNG',
|
||||
patches: [{
|
||||
file: 'scripts/check-inputs.mjs',
|
||||
find: " if (f.startsWith(`${ref}/`) && !BINARY.test(f) && !isBaselineOverlay(f)) { note(f, file); seen.add(f); }",
|
||||
replace: " if (f.startsWith(`${ref}/`) && !BINARY.test(f)) { note(f, file); seen.add(f); }",
|
||||
find: " if (f.startsWith(`${ref}/`) && !BINARY.test(f) && !DIRECTORY_DOCUMENTATION.test(f) && !isBaselineOverlay(f)) { note(f, file); seen.add(f); }",
|
||||
replace: " if (f.startsWith(`${ref}/`) && !BINARY.test(f) && !DIRECTORY_DOCUMENTATION.test(f)) { note(f, file); seen.add(f); }",
|
||||
}],
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user