Files
TS-CUCUMBER-WDIO-QK/test/unit/qkforce-generated.test.mjs
isopropilick 29899223e4
Some checks failed
CI / validate (push) Has been cancelled
Enhance CI configuration and documentation; add new action palette adapter
2026-09-15 10:32:11 -06:00

72 lines
4.2 KiB
JavaScript

import assert from 'node:assert/strict';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import test from 'node:test';
import { loadGeneratedWorkspace, loadGeneratedSelectors } from '../support/qkforce-generated.mjs';
import { createQkfActions } from '../support/qkforce-actions.mjs';
function fixture(t, features=['test/qkforce/features/project.feature']) {
const root=fs.mkdtempSync(path.join(os.tmpdir(),'qkf-generated-'));
t.after(()=>fs.rmSync(root,{recursive:true,force:true}));
fs.mkdirSync(path.join(root,'test/qkforce/features'),{recursive:true});
fs.writeFileSync(path.join(root,'test/qkforce/features/project.feature'),'Feature: project');
fs.writeFileSync(path.join(root,'test/qkforce/steps.mjs'),'');
fs.writeFileSync(path.join(root,'test/qkforce/selectors.json'),'{}');
const manifest={schemaVersion:1,features,steps:'test/qkforce/steps.mjs',selectors:'test/qkforce/selectors.json'};
fs.writeFileSync(path.join(root,'test/qkforce/manifest.json'),JSON.stringify(manifest));
return root;
}
test('runs exactly generated cases and never template or stale feature globs', t=>{
const root=fixture(t);
fs.writeFileSync(path.join(root,'test/qkforce/features/stale.feature'),'Feature: stale');
assert.deepEqual(loadGeneratedWorkspace(root),{specs:['./test/qkforce/features/project.feature'],imports:['./test/qkforce/steps.mjs']});
assert.deepEqual(loadGeneratedSelectors(root),{});
});
test('an empty generated selection fails instead of running the template sample',t=>{
assert.throws(()=>loadGeneratedWorkspace(fixture(t,[])),/at least one/);
});
test('an API package without generated selection cannot fall back to samples',t=>{
const root=fixture(t);fs.unlinkSync(path.join(root,'test/qkforce/manifest.json'));
assert.equal(loadGeneratedWorkspace(root),null);
fs.writeFileSync(path.join(root,'qkforce-package-manifest.json'),'{}');
assert.throws(()=>loadGeneratedWorkspace(root),/regenerate/);
});
test('unsafe, missing, duplicate and symlinked feature inputs are rejected',t=>{
for(const features of [['test/qkforce/features/../../secret.feature'],['test/qkforce/features/missing.feature'],['test/qkforce/features/project.feature','test/qkforce/features/project.feature']]) {
assert.throws(()=>loadGeneratedWorkspace(fixture(t,features)));
}
const root=fixture(t);
const feature=path.join(root,'test/qkforce/features/project.feature');
fs.unlinkSync(feature);fs.symlinkSync(path.join(root,'test/qkforce/steps.mjs'),feature);
assert.throws(()=>loadGeneratedWorkspace(root),/symlinks/);
});
test('legacy unawaited actions execute sequentially and finish before flush returns',async()=>{
const events=[];
const browser={url:async url=>{await Promise.resolve();events.push(url);},$:async selector=>({click:async()=>events.push(selector)})};
const qkf=createQkfActions(browser);
qkf.goto('/login');qkf.click('#submit');
await qkf.flush();assert.deepEqual(events,['/login','#submit']);
});
test('queued action failures fail the step and reset for the next scenario',async()=>{
let fail=true;
const qkf=createQkfActions({url:async()=>{if(fail)throw new Error('navigation failed');}});
qkf.goto('/login');await assert.rejects(qkf.flush(),/navigation failed/);
fail=false;qkf.goto('/ok');await qkf.flush();
});
test('all palette element actions map to real WDIO methods',async()=>{
const calls=[];
const element=new Proxy({}, {get:(_,method)=>method === 'then' ? undefined : (...args)=>{calls.push([method,...args]);return true;}});
const qkf=createQkfActions({$:()=>element});
for(const method of ['click','doubleClick','rightClick','enterValue','addValue','clearValue','isVisible','exists','isEnabled','isClickable','isSelected','waitForVisible','waitForExistence','waitForClickable','waitForEnabled']) qkf[method]('#x','value');
await qkf.flush();
assert.equal(calls.length,15);assert.deepEqual(calls[2],['click',{button:'right'}]);assert.deepEqual(calls[3],['setValue','value']);
});
test('screenshots stay inside the results directory',async t=>{
const root=fixture(t);let saved;
const qkf=createQkfActions({saveScreenshot:async file=>{saved=file;}},root);
qkf.takeScreenshot('../../outside');await qkf.flush();
assert.equal(path.dirname(saved),path.join(root,'qreport-results/screenshots'));
});