mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-06-10 16:14:54 +03:00
test(web-test): M4.D2 — openFile EPF + security confirm
Новый 13-misc.test.mjs (3 шага, 11s) — покрытие openFile() для внешних обработок с автоматической обработкой security confirmation. - setup: автономный билд EPF (идемпотентный) через epf-init → form-add → form-compile (с текстовой декорацией) → epf-build. child_process.spawnSync для вызова PowerShell скриптов. - openFile: проверки state.form, activeTab='Тест открытия', state.texts[] содержит декорацию с ожидаемым value, opened.attempt>=1, security confirm modal не пробивается. - cleanup: closeForm + soft-проверка activeTab (между тестами в desktop могут оставаться формы от других тестов — не настаиваем на formCount=0). Артефакты в test-tmp/13-openfile/ (.gitignore). Полный регресс 17/17 зелёный (8m 8s). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
export const name = 'misc: openFile EPF + security confirm';
|
||||
export const tags = ['openfile'];
|
||||
export const timeout = 120000;
|
||||
|
||||
export default async function({ openFile, closeForm, getFormState, assert, step, log }) {
|
||||
const fs = await import('fs');
|
||||
const path = await import('path');
|
||||
const cp = await import('child_process');
|
||||
|
||||
const dir = 'test-tmp/13-openfile';
|
||||
const srcDir = path.join(dir, 'src');
|
||||
const srcXml = path.join(srcDir, 'ТестОткрытия.xml');
|
||||
const buildDir = path.join(dir, 'build');
|
||||
const epfPath = path.join(buildDir, 'ТестОткрытия.epf');
|
||||
|
||||
await step('setup: собрать тестовый EPF через epf-init + form-add + form-compile + epf-build (идемпотентно)', async () => {
|
||||
if (fs.existsSync(epfPath)) {
|
||||
log(`EPF уже собран: ${epfPath}, размер=${fs.statSync(epfPath).size}`);
|
||||
return;
|
||||
}
|
||||
const run = (script, args) => {
|
||||
const r = cp.spawnSync('powershell.exe', ['-NoProfile', '-File', script, ...args], { encoding: 'utf-8' });
|
||||
return { code: r.status, stdout: r.stdout, stderr: r.stderr };
|
||||
};
|
||||
|
||||
// 1. epf-init — XML scaffold
|
||||
if (!fs.existsSync(srcXml)) {
|
||||
const init = run('.claude/skills/epf-init/scripts/init.ps1',
|
||||
['-Name', 'ТестОткрытия', '-Synonym', 'Тест открытия из файла', '-SrcDir', srcDir]);
|
||||
assert.equal(init.code, 0, `epf-init exit=0 (stderr: ${init.stderr?.slice(0, 200)})`);
|
||||
}
|
||||
// 2. form-add — пустая форма
|
||||
const formDir = path.join(srcDir, 'ТестОткрытия/Forms/Форма');
|
||||
if (!fs.existsSync(path.join(formDir, 'Ext/Form.xml'))) {
|
||||
const fa = run('.claude/skills/form-add/scripts/form-add.ps1',
|
||||
['-ObjectPath', srcXml, '-FormName', 'Форма']);
|
||||
assert.equal(fa.code, 0, 'form-add успешен');
|
||||
}
|
||||
// 3. form-compile — добавить текстовую декорацию
|
||||
const formJsonPath = path.join(dir, 'form.json');
|
||||
fs.writeFileSync(formJsonPath, JSON.stringify({
|
||||
title: 'Тест открытия',
|
||||
elements: [
|
||||
{ label: 'Заголовок', title: 'Это тестовая обработка для проверки openFile' }
|
||||
]
|
||||
}, null, 2), 'utf-8');
|
||||
const fc = run('.claude/skills/form-compile/scripts/form-compile.ps1',
|
||||
['-JsonPath', formJsonPath, '-OutputPath', path.join(formDir, 'Ext/Form.xml')]);
|
||||
assert.equal(fc.code, 0, `form-compile успешен (stderr: ${fc.stderr?.slice(0, 200)})`);
|
||||
|
||||
// 4. epf-build — собрать EPF
|
||||
const build = run('.claude/skills/epf-build/scripts/epf-build.ps1',
|
||||
['-SourceFile', srcXml, '-OutputFile', epfPath,
|
||||
'-V8Path', 'C:\\Program Files\\1cv8\\8.3.24.1691\\bin']);
|
||||
log(`epf-build exit=${build.code}`);
|
||||
assert.equal(build.code, 0, `epf-build успешен (stderr: ${build.stderr?.slice(0, 200)})`);
|
||||
assert.ok(fs.existsSync(epfPath), 'EPF создан на диске');
|
||||
log(`EPF: ${epfPath} size=${fs.statSync(epfPath).size}`);
|
||||
});
|
||||
|
||||
await step('openFile: открывает EPF с формой и текстовой декорацией (security confirm — авто)', async () => {
|
||||
const beforeForm = (await getFormState()).form;
|
||||
const r = await openFile(epfPath);
|
||||
log(`opened: form=${r.form} activeTab=${r.activeTab} texts=${JSON.stringify(r.texts)}`);
|
||||
assert.ok(r.form != null, 'state.form задан после openFile');
|
||||
assert.notEqual(r.form, beforeForm, 'открыта новая форма');
|
||||
assert.equal(r.activeTab, 'Тест открытия', 'заголовок формы из form-compile');
|
||||
// Security confirmation modal обрабатывается внутри openFile — наружу не пробивается
|
||||
assert.ok(!r.errors?.modal, 'нет оставшейся modal ошибки (security confirm обработан)');
|
||||
// Декорация видна в state.texts[]
|
||||
assert.ok(Array.isArray(r.texts) && r.texts.length >= 1, 'state.texts содержит декорации');
|
||||
const decor = r.texts.find(t => t.name === 'Заголовок');
|
||||
assert.ok(decor, 'декорация «Заголовок» присутствует в texts[]');
|
||||
assert.equal(decor.value, 'Это тестовая обработка для проверки openFile', 'текст декорации');
|
||||
// attempt=1 → security confirm не понадобился ИЛИ обработан с первой попытки
|
||||
assert.ok(r.opened?.attempt >= 1, 'opened.attempt задан');
|
||||
});
|
||||
|
||||
await step('cleanup: закрываем форму обработки', async () => {
|
||||
await closeForm();
|
||||
const s = await getFormState();
|
||||
log(`after cleanup: form=${s.form} formCount=${s.formCount} activeTab=${s.activeTab}`);
|
||||
// Проверяем что наша EPF-форма точно закрылась. Между тестами в desktop
|
||||
// могут оставаться формы от других тестов — это не наш регресс.
|
||||
assert.notEqual(s.activeTab, 'Тест открытия', 'форма обработки ТестОткрытия закрыта');
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user