skopix 2.0.83 → 2.0.85
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 +64 -0
- package/package.json +1 -1
|
@@ -1022,6 +1022,10 @@ export async function dashboardCommand(options) {
|
|
|
1022
1022
|
const userEnv = await resolveUserSecretsEnv(currentUser && currentUser.id, teamMode);
|
|
1023
1023
|
Object.assign(process.env, userEnv || {});
|
|
1024
1024
|
const result = await processRecording({ steps, testName, url, provider: provider || 'gemini' });
|
|
1025
|
+
// Match processed steps against library — substitute known elements
|
|
1026
|
+
const matched = await matchStepsToLibrary(suitesDir, result.steps || []);
|
|
1027
|
+
result.steps = matched.steps;
|
|
1028
|
+
result.matchedCount = matched.count;
|
|
1025
1029
|
sendJSON(res, 200, result);
|
|
1026
1030
|
} catch (err) { sendJSON(res, 500, { error: err.message }); }
|
|
1027
1031
|
return;
|
|
@@ -3867,6 +3871,66 @@ async function syncIssuesStatus() {
|
|
|
3867
3871
|
// STEP LIBRARY — persistent store of reusable UI interactions
|
|
3868
3872
|
// ═══════════════════════════════════════════════════════════════
|
|
3869
3873
|
|
|
3874
|
+
// Match recorded steps against library — substitute known elements automatically
|
|
3875
|
+
async function matchStepsToLibrary(suitesDir, steps) {
|
|
3876
|
+
const library = await listLibrarySteps(suitesDir);
|
|
3877
|
+
if (!library.length || !steps.length) return { steps, count: 0 };
|
|
3878
|
+
|
|
3879
|
+
let count = 0;
|
|
3880
|
+
const matched = steps.map(step => {
|
|
3881
|
+
const sSel = (step.stableSelector || step.selector || '').toLowerCase().trim();
|
|
3882
|
+
if (!sSel) return step;
|
|
3883
|
+
|
|
3884
|
+
const match = library.find(lib => {
|
|
3885
|
+
const lSel = (lib.stableSelector || lib.selector || '').toLowerCase().trim();
|
|
3886
|
+
if (!lSel) return false;
|
|
3887
|
+
|
|
3888
|
+
// 1. Exact match
|
|
3889
|
+
if (sSel === lSel) return true;
|
|
3890
|
+
|
|
3891
|
+
// 2. Extract pi-test-identifier values from both and compare
|
|
3892
|
+
const piFrom = (sSel.match(/pi-test-identifier[*^]?=["']([^"']+)["']/) || [])[1];
|
|
3893
|
+
const piLib = (lSel.match(/pi-test-identifier[*^]?=["']([^"']+)["']/) || [])[1];
|
|
3894
|
+
if (piFrom && piLib) {
|
|
3895
|
+
if (piFrom === piLib) return true;
|
|
3896
|
+
// One starts with the other (handles *= vs =)
|
|
3897
|
+
if (piFrom.startsWith(piLib) || piLib.startsWith(piFrom)) return true;
|
|
3898
|
+
}
|
|
3899
|
+
|
|
3900
|
+
// 3. Both use same has-text value (e.g. :has-text("Mariadb"))
|
|
3901
|
+
const textFrom = (sSel.match(/has-text\(["']([^"']+)["']\)/) || [])[1];
|
|
3902
|
+
const textLib = (lSel.match(/has-text\(["']([^"']+)["']\)/) || [])[1];
|
|
3903
|
+
if (textFrom && textLib && textFrom.toLowerCase() === textLib.toLowerCase()) {
|
|
3904
|
+
// Only match if same element type or one contains the other
|
|
3905
|
+
const tagFrom = sSel.split(':')[0].split(' ').pop();
|
|
3906
|
+
const tagLib = lSel.split(':')[0].split(' ').pop();
|
|
3907
|
+
if (tagFrom === tagLib || sSel.includes(lSel) || lSel.includes(sSel)) return true;
|
|
3908
|
+
}
|
|
3909
|
+
|
|
3910
|
+
// 4. Step selector is a child/descendant of library selector
|
|
3911
|
+
// e.g. "a[title='x'] i.fa-plus" should match "a[title='x']"
|
|
3912
|
+
if (lSel.length > 10 && sSel.includes(lSel)) return true;
|
|
3913
|
+
if (sSel.length > 10 && lSel.includes(sSel)) return true;
|
|
3914
|
+
|
|
3915
|
+
return false;
|
|
3916
|
+
});
|
|
3917
|
+
|
|
3918
|
+
if (match) {
|
|
3919
|
+
count++;
|
|
3920
|
+
return {
|
|
3921
|
+
...step,
|
|
3922
|
+
stableSelector: match.stableSelector || match.selector,
|
|
3923
|
+
selector: match.selector || match.stableSelector,
|
|
3924
|
+
description: match.name || step.description,
|
|
3925
|
+
libraryId: match.id,
|
|
3926
|
+
};
|
|
3927
|
+
}
|
|
3928
|
+
return step;
|
|
3929
|
+
});
|
|
3930
|
+
|
|
3931
|
+
return { steps: matched, count };
|
|
3932
|
+
}
|
|
3933
|
+
|
|
3870
3934
|
const FOLDERS_FILE = () => path.join(os.homedir(), '.skopix', 'folders.yaml');
|
|
3871
3935
|
|
|
3872
3936
|
async function getFolders() {
|
package/package.json
CHANGED