import fs from 'node:fs/promises'; import path from 'node:path'; import { randomUUID } from 'node:crypto'; /** Adapter for the action palette emitted by QKForce. One instance per WDIO worker. */ export function createQkfActions(browser, root = process.cwd()) { let tail = Promise.resolve(); const enqueue = action => { const result = tail.then(action); tail = result; // Legacy saved snippets did not await calls. flush() surfaces failures at the step boundary. void result.catch(() => {}); return result; }; const element = selector => { if (typeof selector !== 'string' || !selector.trim()) throw new Error('QKForce action requires a selector string'); return browser.$(selector); }; const call = (selector, method, ...args) => enqueue(async () => (await element(selector))[method](...args)); return Object.freeze({ click: selector => call(selector, 'click'), doubleClick: selector => call(selector, 'doubleClick'), rightClick: selector => call(selector, 'click', { button: 'right' }), enterValue: (selector, value) => call(selector, 'setValue', value), addValue: (selector, value) => call(selector, 'addValue', value), clearValue: selector => call(selector, 'clearValue'), isVisible: selector => call(selector, 'isDisplayed'), exists: selector => call(selector, 'isExisting'), isEnabled: selector => call(selector, 'isEnabled'), isClickable: selector => call(selector, 'isClickable'), isSelected: selector => call(selector, 'isSelected'), waitForVisible: selector => call(selector, 'waitForDisplayed'), waitForExistence: selector => call(selector, 'waitForExist'), waitForClickable: selector => call(selector, 'waitForClickable'), waitForEnabled: selector => call(selector, 'waitForEnabled'), goto: url => enqueue(() => browser.url(url)), takeScreenshot: name => enqueue(async () => { const directory = path.resolve(root, 'qreport-results', 'screenshots'); await fs.mkdir(directory, { recursive: true }); const label = String(name ?? 'screenshot').replace(/[^a-zA-Z0-9_-]/g, '_').slice(0, 80); return browser.saveScreenshot(path.join(directory, `${label}-${randomUUID()}.png`)); }), async flush() { try { await tail; } finally { tail = Promise.resolve(); } } }); }