test: exercise gui smoke actions
This commit is contained in:
parent
cb6c06fdc5
commit
2284f893f8
|
|
@ -13,7 +13,7 @@ const OUT_DIR = process.env.GUI_SMOKE_OUT || path.join(os.tmpdir(), 'verstak-gui
|
||||||
const CHROMIUM = process.env.CHROMIUM_BIN || findChromium()
|
const CHROMIUM = process.env.CHROMIUM_BIN || findChromium()
|
||||||
const HOST = '127.0.0.1'
|
const HOST = '127.0.0.1'
|
||||||
|
|
||||||
const flowUnderTest = 'app loads -> first meaningful screen renders -> primary visible controls respond without runtime errors.'
|
const flowUnderTest = 'app loads -> first meaningful screen renders -> primary visible controls respond and mutate UI state without runtime errors.'
|
||||||
|
|
||||||
if (!CHROMIUM) {
|
if (!CHROMIUM) {
|
||||||
fail('Chromium executable not found. Set CHROMIUM_BIN or install chromium.')
|
fail('Chromium executable not found. Set CHROMIUM_BIN or install chromium.')
|
||||||
|
|
@ -138,6 +138,11 @@ async function runReadyScenario(cdp, url) {
|
||||||
|
|
||||||
await clickText(cdp, '.tab', 'Заметки')
|
await clickText(cdp, '.tab', 'Заметки')
|
||||||
await assertText(cdp, 'Smoke note', 'notes: existing note visible')
|
await assertText(cdp, 'Smoke note', 'notes: existing note visible')
|
||||||
|
await clickText(cdp, '.btn', '+ Добавить заметку')
|
||||||
|
await waitForSelector(cdp, '.create-form input[type="text"]')
|
||||||
|
await setInputValue(cdp, '.create-form input[type="text"]', 'GUI smoke note')
|
||||||
|
await clickText(cdp, '.create-form .btn', 'Создать')
|
||||||
|
await assertText(cdp, 'GUI smoke note', 'notes: created note appears')
|
||||||
|
|
||||||
await clickText(cdp, '.tab', 'Файлы')
|
await clickText(cdp, '.tab', 'Файлы')
|
||||||
await waitForSelector(cdp, '.file-row')
|
await waitForSelector(cdp, '.file-row')
|
||||||
|
|
@ -146,12 +151,21 @@ async function runReadyScenario(cdp, url) {
|
||||||
await waitForSelector(cdp, '.back-btn')
|
await waitForSelector(cdp, '.back-btn')
|
||||||
await assertEval(cdp, `document.querySelector('.back-btn')?.innerText.trim() === 'Назад'`, 'files: back button has one textual label')
|
await assertEval(cdp, `document.querySelector('.back-btn')?.innerText.trim() === 'Назад'`, 'files: back button has one textual label')
|
||||||
await screenshot(cdp, 'files-folder.png')
|
await screenshot(cdp, 'files-folder.png')
|
||||||
|
await click(cdp, '.back-btn')
|
||||||
|
await assertText(cdp, 'brief.md', 'files: back button returns to parent folder')
|
||||||
|
|
||||||
await clickText(cdp, '.tab', 'Действия')
|
await clickText(cdp, '.tab', 'Действия')
|
||||||
await assertText(cdp, 'Deploy smoke', 'actions: action card visible')
|
await assertText(cdp, 'Deploy smoke', 'actions: action card visible')
|
||||||
|
|
||||||
await clickText(cdp, '.tab', 'Журнал')
|
await clickText(cdp, '.tab', 'Журнал')
|
||||||
await assertText(cdp, 'Manual smoke entry', 'worklog: entry visible')
|
await assertText(cdp, 'Manual smoke entry', 'worklog: entry visible')
|
||||||
|
await clickText(cdp, '.worklog-toolbar .btn', 'Добавить запись')
|
||||||
|
await waitForSelector(cdp, '.modal-worklog')
|
||||||
|
await setInputValue(cdp, '.modal-worklog input[type="text"]', 'GUI smoke worklog')
|
||||||
|
await setInputValue(cdp, '.modal-worklog input[type="number"]', '15')
|
||||||
|
await clickText(cdp, '.modal-worklog .btn', 'Сохранить')
|
||||||
|
await waitForGone(cdp, '.modal-worklog')
|
||||||
|
await assertText(cdp, 'GUI smoke worklog', 'worklog: created entry appears')
|
||||||
|
|
||||||
await clickText(cdp, '.tab', 'Активность')
|
await clickText(cdp, '.tab', 'Активность')
|
||||||
await assertText(cdp, 'Smoke activity', 'activity: per-node activity visible')
|
await assertText(cdp, 'Smoke activity', 'activity: per-node activity visible')
|
||||||
|
|
@ -173,9 +187,12 @@ async function runReadyScenario(cdp, url) {
|
||||||
await click(cdp, '.nav-add-btn')
|
await click(cdp, '.nav-add-btn')
|
||||||
await waitForSelector(cdp, '.modal-create')
|
await waitForSelector(cdp, '.modal-create')
|
||||||
await assertText(cdp, 'Создать элемент', 'create node: modal opens')
|
await assertText(cdp, 'Создать элемент', 'create node: modal opens')
|
||||||
|
await clickText(cdp, '.template-card', 'Пустое дело')
|
||||||
|
await setInputValue(cdp, '.modal-create input[type="text"]', 'GUI Smoke Created')
|
||||||
await screenshot(cdp, 'create-node-modal.png')
|
await screenshot(cdp, 'create-node-modal.png')
|
||||||
await clickText(cdp, '.modal-actions .btn', 'Отмена')
|
await clickText(cdp, '.modal-actions .btn', 'Создать')
|
||||||
await waitForGone(cdp, '.modal-create')
|
await waitForGone(cdp, '.modal-create')
|
||||||
|
await assertText(cdp, 'GUI Smoke Created', 'create node: created node appears')
|
||||||
|
|
||||||
await setViewport(cdp, 390, 844)
|
await setViewport(cdp, 390, 844)
|
||||||
await navigate(cdp, url)
|
await navigate(cdp, url)
|
||||||
|
|
@ -263,6 +280,22 @@ async function clickText(cdp, selector, text) {
|
||||||
await sleep(200)
|
await sleep(200)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function setInputValue(cdp, selector, value) {
|
||||||
|
const ok = await evalValue(cdp, `
|
||||||
|
(() => {
|
||||||
|
const el = document.querySelector(${JSON.stringify(selector)});
|
||||||
|
if (!el) return false;
|
||||||
|
el.focus();
|
||||||
|
el.value = ${JSON.stringify(value)};
|
||||||
|
el.dispatchEvent(new Event('input', { bubbles: true }));
|
||||||
|
el.dispatchEvent(new Event('change', { bubbles: true }));
|
||||||
|
return true;
|
||||||
|
})()
|
||||||
|
`)
|
||||||
|
if (!ok) throw new Error(`Input target not found: ${selector}`)
|
||||||
|
await sleep(100)
|
||||||
|
}
|
||||||
|
|
||||||
async function clickFolderOpenButton(cdp, name) {
|
async function clickFolderOpenButton(cdp, name) {
|
||||||
const ok = await evalValue(cdp, `
|
const ok = await evalValue(cdp, `
|
||||||
(() => {
|
(() => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue