skopix 2.0.31 → 2.0.32
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 +33 -35
- package/package.json +1 -1
|
@@ -1800,14 +1800,14 @@ export async function dashboardCommand(options) {
|
|
|
1800
1800
|
return;
|
|
1801
1801
|
}
|
|
1802
1802
|
if (pathname === '/api/step-library' && method === 'POST') {
|
|
1803
|
-
const data = await readBody(req);
|
|
1803
|
+
const data = JSON.parse(await readBody(req));
|
|
1804
1804
|
const step = await addLibraryStep(suitesDir, data);
|
|
1805
1805
|
sendJSON(res, 200, step);
|
|
1806
1806
|
return;
|
|
1807
1807
|
}
|
|
1808
1808
|
if (pathname.match(/^\/api\/step-library\/[^/]+$/) && method === 'PUT') {
|
|
1809
1809
|
const id = decodeURIComponent(pathname.split('/')[3]);
|
|
1810
|
-
const data = await readBody(req);
|
|
1810
|
+
const data = JSON.parse(await readBody(req));
|
|
1811
1811
|
const step = await updateLibraryStep(suitesDir, id, data);
|
|
1812
1812
|
if (!step) sendJSON(res, 404, { error: 'Not found' });
|
|
1813
1813
|
else sendJSON(res, 200, step);
|
|
@@ -3650,11 +3650,12 @@ async function addLibraryStep(suitesDir, stepData) {
|
|
|
3650
3650
|
const id = 'lib-' + Math.random().toString(36).slice(2, 10);
|
|
3651
3651
|
const step = {
|
|
3652
3652
|
id,
|
|
3653
|
-
name: stepData.name || stepData.description || 'Unnamed
|
|
3654
|
-
action: stepData.action,
|
|
3653
|
+
name: stepData.name || stepData.description || 'Unnamed element',
|
|
3655
3654
|
selector: stepData.stableSelector || stepData.selector || null,
|
|
3656
3655
|
stableSelector: stepData.stableSelector || stepData.selector || null,
|
|
3657
|
-
|
|
3656
|
+
// Store default action as hint but element is primary
|
|
3657
|
+
defaultAction: stepData.action || stepData.defaultAction || null,
|
|
3658
|
+
defaultValue: stepData.value || stepData.defaultValue || null,
|
|
3658
3659
|
assertType: stepData.assertType || null,
|
|
3659
3660
|
attribute: stepData.attribute || null,
|
|
3660
3661
|
description: stepData.description || null,
|
|
@@ -3682,53 +3683,50 @@ async function deleteLibraryStep(suitesDir, id) {
|
|
|
3682
3683
|
await saveLibrarySteps(filtered);
|
|
3683
3684
|
}
|
|
3684
3685
|
|
|
3685
|
-
// Similarity check —
|
|
3686
|
+
// Similarity check — element-based, matches on selector only
|
|
3686
3687
|
function stepSimilarity(a, b) {
|
|
3687
|
-
if (a.action !== b.action) return 0;
|
|
3688
3688
|
const selA = (a.stableSelector || a.selector || '').toLowerCase();
|
|
3689
3689
|
const selB = (b.stableSelector || b.selector || '').toLowerCase();
|
|
3690
|
-
if (selA
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
const shared = tokA.filter(t => tokB.includes(t) && t.length > 2);
|
|
3698
|
-
if (shared.length > 0) return Math.min(0.8, shared.length / Math.max(tokA.length, tokB.length));
|
|
3699
|
-
}
|
|
3700
|
-
const descA = (a.description || '').toLowerCase();
|
|
3701
|
-
const descB = (b.description || '').toLowerCase();
|
|
3702
|
-
if (descA && descB && descA === descB) return 0.9;
|
|
3690
|
+
if (!selA || !selB) return 0;
|
|
3691
|
+
if (selA === selB) return 1;
|
|
3692
|
+
if (selA.includes(selB) || selB.includes(selA)) return 0.85;
|
|
3693
|
+
const tokA = selA.split(/[\s>+~.,#\[\]()=]/).filter(Boolean);
|
|
3694
|
+
const tokB = selB.split(/[\s>+~.,#\[\]()=]/).filter(Boolean);
|
|
3695
|
+
const shared = tokA.filter(t => tokB.includes(t) && t.length > 2);
|
|
3696
|
+
if (shared.length > 0) return Math.min(0.8, shared.length / Math.max(tokA.length, tokB.length));
|
|
3703
3697
|
return 0;
|
|
3704
3698
|
}
|
|
3705
3699
|
|
|
3706
|
-
// Extract unique
|
|
3700
|
+
// Extract unique elements from a test and add to library (skip duplicates)
|
|
3707
3701
|
async function extractStepsToLibrary(suitesDir, steps, testName) {
|
|
3708
3702
|
if (!steps || steps.length === 0) return;
|
|
3709
3703
|
const existing = await listLibrarySteps(suitesDir);
|
|
3710
3704
|
const toAdd = [];
|
|
3705
|
+
const seenSelectors = new Set(existing.map(e => (e.stableSelector || e.selector || '').toLowerCase()));
|
|
3711
3706
|
|
|
3712
3707
|
for (const step of steps) {
|
|
3713
|
-
if (!step.action || step.action === 'navigate') continue;
|
|
3714
|
-
// Skip steps with no selector (e.g. scroll)
|
|
3708
|
+
if (!step.action || step.action === 'navigate' || step.action === 'scroll') continue;
|
|
3715
3709
|
const sel = step.stableSelector || step.selector;
|
|
3716
|
-
if (!sel
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
if (
|
|
3720
|
-
|
|
3721
|
-
|
|
3710
|
+
if (!sel) continue;
|
|
3711
|
+
const selLower = sel.toLowerCase();
|
|
3712
|
+
// Skip click steps if we already have this selector from a type step (deduplicate click/type pairs)
|
|
3713
|
+
if (seenSelectors.has(selLower)) {
|
|
3714
|
+
const existing2 = existing.find(e => (e.stableSelector||e.selector||'').toLowerCase() === selLower) ||
|
|
3715
|
+
toAdd.find(e => (e.stableSelector||e.selector||'').toLowerCase() === selLower);
|
|
3716
|
+
if (existing2) { existing2.usageCount = (existing2.usageCount || 0) + 1; }
|
|
3722
3717
|
continue;
|
|
3723
3718
|
}
|
|
3724
|
-
|
|
3719
|
+
seenSelectors.add(selLower);
|
|
3720
|
+
// Generate clean name — strip action prefix
|
|
3721
|
+
let name = step.description || '';
|
|
3722
|
+
name = name.replace(/^(click|type|check|assert|select)\s+/i, '').trim() || sel.slice(0, 50);
|
|
3725
3723
|
toAdd.push({
|
|
3726
3724
|
id: 'lib-' + Math.random().toString(36).slice(2, 10),
|
|
3727
|
-
name
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3725
|
+
name,
|
|
3726
|
+
selector: sel,
|
|
3727
|
+
stableSelector: step.stableSelector || sel,
|
|
3728
|
+
defaultAction: step.action,
|
|
3729
|
+
defaultValue: step.value || null,
|
|
3732
3730
|
assertType: step.assertType || null,
|
|
3733
3731
|
attribute: step.attribute || null,
|
|
3734
3732
|
description: step.description || null,
|
package/package.json
CHANGED