skopix 2.0.68 → 2.0.70

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.
@@ -1919,6 +1919,27 @@ export async function dashboardCommand(options) {
1919
1919
  sendJSON(res, 200, result);
1920
1920
  return;
1921
1921
  }
1922
+ if (pathname === '/api/step-library/sync-selectors' && method === 'POST') {
1923
+ const { fromSelectors, toSelector, toName } = JSON.parse(await readBody(req));
1924
+ const allTests = await listAllTests(suitesDir);
1925
+ let updated = 0;
1926
+ for (const test of allTests) {
1927
+ if (!test.steps || !test.steps.length) continue;
1928
+ let changed = false;
1929
+ const newSteps = test.steps.map(step => {
1930
+ const sSel = (step.stableSelector||step.selector||'').toLowerCase();
1931
+ if (fromSelectors.includes(sSel)) {
1932
+ changed = true;
1933
+ updated++;
1934
+ return { ...step, stableSelector: toSelector, selector: toSelector, description: toName || step.description };
1935
+ }
1936
+ return step;
1937
+ });
1938
+ if (changed) await updateTest(suitesDir, test.scope, test.id, { ...test, steps: newSteps });
1939
+ }
1940
+ sendJSON(res, 200, { updated });
1941
+ return;
1942
+ }
1922
1943
  if (pathname === '/api/step-library/sync' && method === 'POST') {
1923
1944
  const result = await syncTestsToLibrary(suitesDir);
1924
1945
  sendJSON(res, 200, result);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skopix",
3
- "version": "2.0.68",
3
+ "version": "2.0.70",
4
4
  "description": "Browser-based QA tool — record tests by using your app, replay them deterministically, generate Playwright code automatically",
5
5
  "main": "cli/index.js",
6
6
  "bin": {
@@ -5894,15 +5894,29 @@ async function confirmMergeSteps(ids) {
5894
5894
  const toDelete = selected.filter(s => s.id !== canonicalId);
5895
5895
  const totalUses = selected.reduce((sum, s) => sum + (s.usageCount||0), 0);
5896
5896
  closeConfirm();
5897
+
5898
+ // Update canonical usage count
5897
5899
  await fetch(API_BASE + '/api/step-library/' + encodeURIComponent(canonicalId), {
5898
5900
  method: 'PUT',
5899
5901
  headers: { 'Content-Type': 'application/json' },
5900
5902
  body: JSON.stringify({ ...canonical, usageCount: totalUses })
5901
5903
  });
5904
+
5905
+ // Delete the merged ones
5902
5906
  for (const s of toDelete) {
5903
5907
  await fetch(API_BASE + '/api/step-library/' + encodeURIComponent(s.id), { method: 'DELETE' });
5904
5908
  }
5905
- showToast(`Merged ${selected.length} steps into "${canonical.name}"`);
5909
+
5910
+ // Update all tests that used any of the merged selectors to use the canonical selector
5911
+ const allMergedSelectors = selected.map(s => (s.stableSelector||s.selector||'').toLowerCase());
5912
+ const canonicalSel = canonical.stableSelector || canonical.selector;
5913
+ const res = await fetch(API_BASE + '/api/step-library/sync-selectors', {
5914
+ method: 'POST',
5915
+ headers: { 'Content-Type': 'application/json' },
5916
+ body: JSON.stringify({ fromSelectors: allMergedSelectors, toSelector: canonicalSel, toName: canonical.name })
5917
+ });
5918
+ const data = await res.json();
5919
+ showToast(`Merged into "${canonical.name}" — ${data.updated || 0} test step${data.updated !== 1 ? 's' : ''} updated`);
5906
5920
  await loadLibraryView();
5907
5921
  }
5908
5922