skopix 2.0.61 → 2.0.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/commands/dashboard.js +21 -14
- package/package.json +1 -1
- package/web/app/index.html +18 -0
|
@@ -1836,6 +1836,11 @@ export async function dashboardCommand(options) {
|
|
|
1836
1836
|
sendJSON(res, 200, { stopped: true });
|
|
1837
1837
|
return;
|
|
1838
1838
|
}
|
|
1839
|
+
if (pathname.match(/^\/api\/step-tester\/[^/]+\/status$/) && method === 'GET') {
|
|
1840
|
+
const testerId = pathname.split('/')[3];
|
|
1841
|
+
sendJSON(res, 200, { active: stepTesterSessions.has(testerId) });
|
|
1842
|
+
return;
|
|
1843
|
+
}
|
|
1839
1844
|
|
|
1840
1845
|
// ─── STEP LIBRARY ──────────────────────────────────────────────────
|
|
1841
1846
|
if (pathname === '/api/step-library' && method === 'GET') {
|
|
@@ -3956,21 +3961,23 @@ async function startStepTester(testerId, url, selector, mode, steps) {
|
|
|
3956
3961
|
await ctx.exposeFunction('__skopixPreviewRun', async ({ index }) => {
|
|
3957
3962
|
const s = steps[index];
|
|
3958
3963
|
if (!s) return;
|
|
3959
|
-
await page.evaluate((i, status) => { if(window.__skopixUpdatePreview) window.__skopixUpdatePreview(i, null, status); }, index, `Running step ${index+1}/${steps.length}...`).catch(()=>{});
|
|
3964
|
+
await page.evaluate(({ i, status }) => { if(window.__skopixUpdatePreview) window.__skopixUpdatePreview(i, null, status); }, { i: index, status: `Running step ${index+1}/${steps.length}...` }).catch(()=>{});
|
|
3960
3965
|
const result = await executeStepTesterAction(page, { selector: s.stableSelector||s.selector, action: s.action, value: s.value||'', assertType: s.assertType });
|
|
3961
|
-
|
|
3962
|
-
|
|
3963
|
-
|
|
3966
|
+
const msg = result.passed ? (index+1 >= steps.length ? `✓ All ${steps.length} steps passed!` : `✓ Step ${index+1} passed`) : `✗ Step ${index+1} failed`;
|
|
3967
|
+
await page.evaluate(({ i, r, msg }) => {
|
|
3968
|
+
if(window.__skopixUpdatePreview) window.__skopixUpdatePreview(i, r, msg);
|
|
3969
|
+
}, { i: index, r: { passed: result.passed, error: result.error||null }, msg }).catch(()=>{});
|
|
3964
3970
|
});
|
|
3965
3971
|
|
|
3966
3972
|
await ctx.exposeFunction('__skopixPreviewRunAll', async ({ fromIndex }) => {
|
|
3967
3973
|
for (let i = fromIndex; i < steps.length; i++) {
|
|
3968
3974
|
const s = steps[i];
|
|
3969
|
-
await page.evaluate((i, total) => { if(window.__skopixUpdatePreview) window.__skopixUpdatePreview(i, null, `Running step ${i+1}/${total}...`); }, i, steps.length).catch(()=>{});
|
|
3975
|
+
await page.evaluate(({ i, total }) => { if(window.__skopixUpdatePreview) window.__skopixUpdatePreview(i, null, `Running step ${i+1}/${total}...`); }, { i, total: steps.length }).catch(()=>{});
|
|
3970
3976
|
const result = await executeStepTesterAction(page, { selector: s.stableSelector||s.selector, action: s.action, value: s.value||'', assertType: s.assertType });
|
|
3971
|
-
|
|
3972
|
-
|
|
3973
|
-
|
|
3977
|
+
const msg = result.passed ? (i+1 >= steps.length ? `✓ All ${steps.length} steps passed!` : `Running...`) : `✗ Step ${i+1} failed — fix and retry`;
|
|
3978
|
+
await page.evaluate(({ i, r, msg }) => {
|
|
3979
|
+
if(window.__skopixUpdatePreview) window.__skopixUpdatePreview(i, r, msg);
|
|
3980
|
+
}, { i, r: { passed: result.passed, error: result.error||null }, msg }).catch(()=>{});
|
|
3974
3981
|
if (!result.passed) break;
|
|
3975
3982
|
await new Promise(r => setTimeout(r, 400));
|
|
3976
3983
|
}
|
|
@@ -4093,17 +4100,17 @@ async function startStepTester(testerId, url, selector, mode, steps) {
|
|
|
4093
4100
|
// STEP TESTER MODE — register expose functions FIRST
|
|
4094
4101
|
await ctx.exposeFunction('__skopixTesterRun', async ({ sel, action, value }) => {
|
|
4095
4102
|
const result = await executeStepTesterAction(page, { selector: sel, action, value });
|
|
4096
|
-
await page.evaluate((passed
|
|
4103
|
+
await page.evaluate(({ passed }) => {
|
|
4097
4104
|
const el = document.getElementById('__skopix_result');
|
|
4098
4105
|
if (el) { el.textContent = passed ? '✓' : '✗'; el.style.color = passed ? '#34d399' : '#ef4444'; }
|
|
4099
|
-
},
|
|
4106
|
+
}, { passed: result.passed }).catch(async () => {
|
|
4100
4107
|
await new Promise(r => setTimeout(r, 500));
|
|
4101
|
-
await page.evaluate((passed) => {
|
|
4108
|
+
await page.evaluate(({ passed }) => {
|
|
4102
4109
|
const el = document.getElementById('__skopix_result');
|
|
4103
4110
|
if (el) { el.textContent = passed ? '✓' : '✗'; el.style.color = passed ? '#34d399' : '#ef4444'; }
|
|
4104
|
-
}, result.passed).catch(() => {});
|
|
4111
|
+
}, { passed: result.passed }).catch(() => {});
|
|
4105
4112
|
});
|
|
4106
|
-
await page.evaluate((passed, sel) => {
|
|
4113
|
+
await page.evaluate(({ passed, sel }) => {
|
|
4107
4114
|
try {
|
|
4108
4115
|
const target = document.querySelector(sel);
|
|
4109
4116
|
if (target) {
|
|
@@ -4112,7 +4119,7 @@ async function startStepTester(testerId, url, selector, mode, steps) {
|
|
|
4112
4119
|
setTimeout(() => { target.style.outline = orig; }, 1500);
|
|
4113
4120
|
}
|
|
4114
4121
|
} catch {}
|
|
4115
|
-
}, result.passed, sel).catch(() => {});
|
|
4122
|
+
}, { passed: result.passed, sel }).catch(() => {});
|
|
4116
4123
|
});
|
|
4117
4124
|
|
|
4118
4125
|
await ctx.exposeFunction('__skopixTesterStop', async () => {
|
package/package.json
CHANGED
package/web/app/index.html
CHANGED
|
@@ -6422,9 +6422,27 @@ async function startBuilderPreview() {
|
|
|
6422
6422
|
const data = await res.json();
|
|
6423
6423
|
if (!res.ok) throw new Error(data.error || 'Failed');
|
|
6424
6424
|
previewState.testerId = data.testerId;
|
|
6425
|
+
btn.disabled = false;
|
|
6425
6426
|
btn.textContent = '⏸ Previewing';
|
|
6426
6427
|
btn.onclick = stopBuilderPreview;
|
|
6427
6428
|
showToast('Browser open — use the toolbar in the browser to run steps');
|
|
6429
|
+
|
|
6430
|
+
// Poll until session ends (browser closed via Stop button in browser)
|
|
6431
|
+
const poll = setInterval(async () => {
|
|
6432
|
+
if (!previewState.testerId) { clearInterval(poll); return; }
|
|
6433
|
+
try {
|
|
6434
|
+
const r = await fetch(API_BASE + '/api/step-tester/' + previewState.testerId + '/status');
|
|
6435
|
+
const d = await r.json();
|
|
6436
|
+
if (!d.active) {
|
|
6437
|
+
clearInterval(poll);
|
|
6438
|
+
previewState.testerId = null;
|
|
6439
|
+
btn.disabled = false;
|
|
6440
|
+
btn.textContent = 'Preview';
|
|
6441
|
+
btn.onclick = startBuilderPreview;
|
|
6442
|
+
}
|
|
6443
|
+
} catch { clearInterval(poll); }
|
|
6444
|
+
}, 1500);
|
|
6445
|
+
|
|
6428
6446
|
} catch (err) {
|
|
6429
6447
|
showToast('Error: ' + err.message);
|
|
6430
6448
|
btn.disabled = false;
|