skopix 2.0.79 → 2.0.80

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.
@@ -3901,28 +3901,78 @@ async function saveSavedUrls(urls) {
3901
3901
  }
3902
3902
  // Internal helper — sync selectors across all tests
3903
3903
  async function syncSelectorsInternal(suitesDir, fromSelectors, toSelector, toName) {
3904
- const allTests = await listAllTests(suitesDir);
3904
+ const files = await fs.readdir(suitesDir);
3905
+ const suiteFiles = files.filter(f => f.endsWith('.suite.yaml') || f.endsWith('.suite.yml'));
3905
3906
  let updated = 0;
3906
3907
  const fromLower = fromSelectors.map(s => s.toLowerCase());
3907
3908
  const allFromTokens = fromLower.flatMap(sel =>
3908
3909
  (sel.match(/\.[a-z][a-z0-9_-]+|\[[\w-]+=["'][^"']+["']\]|#[a-z][a-z0-9_-]+/g) || []).filter(t => t.length > 5)
3909
3910
  );
3910
- for (const test of allTests) {
3911
- if (!test.steps || !test.steps.length) continue;
3911
+
3912
+ function matchesSel(sSel) {
3913
+ if (!sSel) return false;
3914
+ const sLower = sSel.toLowerCase();
3915
+ if (fromLower.includes(sLower)) return true;
3916
+ if (allFromTokens.some(tok => sLower.includes(tok))) return true;
3917
+ return fromLower.some(fSel => stepSimilarity({ selector: sLower }, { selector: fSel }) >= 0.7);
3918
+ }
3919
+
3920
+ function syncSteps(steps) {
3921
+ if (!Array.isArray(steps)) return { steps, changed: false };
3912
3922
  let changed = false;
3913
- const newSteps = test.steps.map(step => {
3914
- const sSel = (step.stableSelector||step.selector||'').toLowerCase();
3915
- const isMatch = fromLower.includes(sSel) ||
3916
- allFromTokens.some(tok => sSel.includes(tok)) ||
3917
- fromLower.some(fSel => stepSimilarity({ selector: sSel }, { selector: fSel }) >= 0.7);
3918
- if (isMatch && sSel) {
3923
+ const newSteps = steps.map(step => {
3924
+ const sel = step.stableSelector || step.selector || '';
3925
+ if (matchesSel(sel)) {
3919
3926
  changed = true;
3920
3927
  updated++;
3921
3928
  return { ...step, stableSelector: toSelector, selector: toSelector, description: toName || step.description };
3922
3929
  }
3923
3930
  return step;
3924
3931
  });
3925
- if (changed) await updateTest(suitesDir, test.scope, test.id, { ...test, steps: newSteps });
3932
+ return { steps: newSteps, changed };
3933
+ }
3934
+
3935
+ for (const file of suiteFiles) {
3936
+ const filePath = path.join(suitesDir, file);
3937
+ try {
3938
+ const content = await fs.readFile(filePath, 'utf8');
3939
+ const data = yaml.parse(content);
3940
+ if (!data || !Array.isArray(data.tests)) continue;
3941
+ let fileChanged = false;
3942
+
3943
+ data.tests = data.tests.map(test => {
3944
+ let testChanged = false;
3945
+ // Sync structured steps
3946
+ if (Array.isArray(test.steps) && test.steps.length > 0) {
3947
+ const { steps: newSteps, changed } = syncSteps(test.steps);
3948
+ if (changed) { test = { ...test, steps: newSteps }; testChanged = true; }
3949
+ }
3950
+ // Sync playwrightJs code string
3951
+ if (test.playwrightJs && typeof test.playwrightJs === 'string') {
3952
+ let newJs = test.playwrightJs;
3953
+ for (const oldSel of fromSelectors) {
3954
+ if (newJs.includes(oldSel)) {
3955
+ newJs = newJs.split('"' + oldSel + '"').join('"' + toSelector + '"');
3956
+ newJs = newJs.split("'" + oldSel + "'").join("'" + toSelector + "'");
3957
+ // Update comment descriptions
3958
+ if (toName) {
3959
+ fromSelectors.forEach(s => {}); // placeholder — descriptions in comments are harder to match
3960
+ }
3961
+ testChanged = true;
3962
+ }
3963
+ }
3964
+ if (testChanged) test = { ...test, playwrightJs: newJs };
3965
+ }
3966
+ if (testChanged) fileChanged = true;
3967
+ return test;
3968
+ });
3969
+
3970
+ if (fileChanged) {
3971
+ await fs.writeFile(filePath, yaml.stringify(data));
3972
+ }
3973
+ } catch (err) {
3974
+ process.stderr.write('[sync] error processing ' + file + ': ' + err.message + '\n');
3975
+ }
3926
3976
  }
3927
3977
  return updated;
3928
3978
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skopix",
3
- "version": "2.0.79",
3
+ "version": "2.0.80",
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": {