@sun-asterisk/sungen 2.5.1 → 2.6.0

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.
Files changed (170) hide show
  1. package/dist/cli/commands/add-flow.d.ts +3 -0
  2. package/dist/cli/commands/add-flow.d.ts.map +1 -0
  3. package/dist/cli/commands/add-flow.js +27 -0
  4. package/dist/cli/commands/add-flow.js.map +1 -0
  5. package/dist/cli/commands/delivery.d.ts.map +1 -1
  6. package/dist/cli/commands/delivery.js +95 -60
  7. package/dist/cli/commands/delivery.js.map +1 -1
  8. package/dist/cli/commands/generate.d.ts.map +1 -1
  9. package/dist/cli/commands/generate.js +38 -6
  10. package/dist/cli/commands/generate.js.map +1 -1
  11. package/dist/cli/index.js +3 -1
  12. package/dist/cli/index.js.map +1 -1
  13. package/dist/generators/test-generator/adapters/adapter-interface.d.ts +1 -0
  14. package/dist/generators/test-generator/adapters/adapter-interface.d.ts.map +1 -1
  15. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.d.ts +1 -0
  16. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.d.ts.map +1 -1
  17. package/dist/generators/test-generator/adapters/playwright/playwright-adapter.js.map +1 -1
  18. package/dist/generators/test-generator/adapters/playwright/templates/imports.hbs +2 -2
  19. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/alert-accept-action.hbs +1 -1
  20. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/alert-dismiss-action.hbs +1 -1
  21. package/dist/generators/test-generator/adapters/playwright/templates/steps/actions/alert-fill-action.hbs +1 -1
  22. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/alert-text-assertion.hbs +2 -2
  23. package/dist/generators/test-generator/adapters/playwright/templates/steps/assertions/column-cell-assertion.hbs +1 -0
  24. package/dist/generators/test-generator/adapters/playwright/templates/steps/navigation/navigation.hbs +2 -1
  25. package/dist/generators/test-generator/adapters/playwright/templates/steps/navigation/route-assertion.hbs +1 -2
  26. package/dist/generators/test-generator/adapters/playwright/templates/steps/navigation/wait-timeout.hbs +1 -1
  27. package/dist/generators/test-generator/code-generator.d.ts +1 -0
  28. package/dist/generators/test-generator/code-generator.d.ts.map +1 -1
  29. package/dist/generators/test-generator/code-generator.js +30 -12
  30. package/dist/generators/test-generator/code-generator.js.map +1 -1
  31. package/dist/generators/test-generator/step-mapper.d.ts +4 -0
  32. package/dist/generators/test-generator/step-mapper.d.ts.map +1 -1
  33. package/dist/generators/test-generator/step-mapper.js +7 -0
  34. package/dist/generators/test-generator/step-mapper.js.map +1 -1
  35. package/dist/generators/test-generator/template-engine.d.ts +1 -0
  36. package/dist/generators/test-generator/template-engine.d.ts.map +1 -1
  37. package/dist/generators/test-generator/template-engine.js +1 -1
  38. package/dist/generators/test-generator/template-engine.js.map +1 -1
  39. package/dist/generators/test-generator/utils/data-resolver.d.ts +3 -20
  40. package/dist/generators/test-generator/utils/data-resolver.d.ts.map +1 -1
  41. package/dist/generators/test-generator/utils/data-resolver.js +23 -66
  42. package/dist/generators/test-generator/utils/data-resolver.js.map +1 -1
  43. package/dist/generators/test-generator/utils/selector-resolver.d.ts +2 -6
  44. package/dist/generators/test-generator/utils/selector-resolver.d.ts.map +1 -1
  45. package/dist/generators/test-generator/utils/selector-resolver.js +18 -80
  46. package/dist/generators/test-generator/utils/selector-resolver.js.map +1 -1
  47. package/dist/orchestrator/ai-rules-updater.d.ts.map +1 -1
  48. package/dist/orchestrator/ai-rules-updater.js +4 -0
  49. package/dist/orchestrator/ai-rules-updater.js.map +1 -1
  50. package/dist/orchestrator/flow-manager.d.ts +22 -0
  51. package/dist/orchestrator/flow-manager.d.ts.map +1 -0
  52. package/dist/orchestrator/flow-manager.js +251 -0
  53. package/dist/orchestrator/flow-manager.js.map +1 -0
  54. package/dist/orchestrator/project-initializer.d.ts.map +1 -1
  55. package/dist/orchestrator/project-initializer.js +1 -0
  56. package/dist/orchestrator/project-initializer.js.map +1 -1
  57. package/dist/orchestrator/templates/ai-instructions/claude-cmd-add-flow.md +88 -0
  58. package/dist/orchestrator/templates/ai-instructions/claude-cmd-create-test.md +11 -8
  59. package/dist/orchestrator/templates/ai-instructions/claude-cmd-review.md +8 -6
  60. package/dist/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +15 -11
  61. package/dist/orchestrator/templates/ai-instructions/claude-config.md +41 -10
  62. package/dist/orchestrator/templates/ai-instructions/claude-skill-capture-live.md +12 -0
  63. package/dist/orchestrator/templates/ai-instructions/claude-skill-delivery.md +19 -18
  64. package/dist/orchestrator/templates/ai-instructions/claude-skill-error-mapping.md +12 -0
  65. package/dist/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +52 -0
  66. package/dist/orchestrator/templates/ai-instructions/claude-skill-selector-fix.md +31 -3
  67. package/dist/orchestrator/templates/ai-instructions/claude-skill-selector-keys.md +45 -0
  68. package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +69 -0
  69. package/dist/orchestrator/templates/ai-instructions/claude-skill-tc-review.md +30 -0
  70. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-add-flow.md +86 -0
  71. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-create-test.md +13 -10
  72. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-delivery.md +18 -17
  73. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-review.md +9 -7
  74. package/dist/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +23 -19
  75. package/dist/orchestrator/templates/ai-instructions/copilot-config.md +40 -9
  76. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-capture-live.md +12 -0
  77. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-delivery.md +19 -18
  78. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-error-mapping.md +12 -0
  79. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md +52 -0
  80. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md +31 -3
  81. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-selector-keys.md +45 -0
  82. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +70 -0
  83. package/dist/orchestrator/templates/ai-instructions/github-skill-sungen-tc-review.md +30 -0
  84. package/dist/orchestrator/templates/playwright.config.d.ts.map +1 -1
  85. package/dist/orchestrator/templates/playwright.config.js +3 -1
  86. package/dist/orchestrator/templates/playwright.config.js.map +1 -1
  87. package/dist/orchestrator/templates/playwright.config.ts +4 -1
  88. package/dist/orchestrator/templates/specs-base.d.ts.map +1 -1
  89. package/dist/orchestrator/templates/specs-base.js +11 -56
  90. package/dist/orchestrator/templates/specs-base.js.map +1 -1
  91. package/dist/orchestrator/templates/specs-base.ts +11 -61
  92. package/dist/orchestrator/templates/specs-test-data.d.ts +3 -1
  93. package/dist/orchestrator/templates/specs-test-data.d.ts.map +1 -1
  94. package/dist/orchestrator/templates/specs-test-data.js +10 -2
  95. package/dist/orchestrator/templates/specs-test-data.js.map +1 -1
  96. package/dist/orchestrator/templates/specs-test-data.ts +9 -2
  97. package/package.json +1 -1
  98. package/src/cli/commands/add-flow.ts +25 -0
  99. package/src/cli/commands/delivery.ts +109 -58
  100. package/src/cli/commands/generate.ts +43 -6
  101. package/src/cli/index.ts +3 -1
  102. package/src/generators/test-generator/adapters/adapter-interface.ts +1 -1
  103. package/src/generators/test-generator/adapters/playwright/playwright-adapter.ts +1 -1
  104. package/src/generators/test-generator/adapters/playwright/templates/imports.hbs +2 -2
  105. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/alert-accept-action.hbs +1 -1
  106. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/alert-dismiss-action.hbs +1 -1
  107. package/src/generators/test-generator/adapters/playwright/templates/steps/actions/alert-fill-action.hbs +1 -1
  108. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/alert-text-assertion.hbs +2 -2
  109. package/src/generators/test-generator/adapters/playwright/templates/steps/assertions/column-cell-assertion.hbs +1 -0
  110. package/src/generators/test-generator/adapters/playwright/templates/steps/navigation/navigation.hbs +2 -1
  111. package/src/generators/test-generator/adapters/playwright/templates/steps/navigation/route-assertion.hbs +1 -2
  112. package/src/generators/test-generator/adapters/playwright/templates/steps/navigation/wait-timeout.hbs +1 -1
  113. package/src/generators/test-generator/code-generator.ts +32 -14
  114. package/src/generators/test-generator/step-mapper.ts +8 -0
  115. package/src/generators/test-generator/template-engine.ts +2 -2
  116. package/src/generators/test-generator/utils/data-resolver.ts +25 -77
  117. package/src/generators/test-generator/utils/selector-resolver.ts +23 -109
  118. package/src/orchestrator/ai-rules-updater.ts +5 -0
  119. package/src/orchestrator/flow-manager.ts +243 -0
  120. package/src/orchestrator/project-initializer.ts +1 -0
  121. package/src/orchestrator/templates/ai-instructions/claude-cmd-add-flow.md +88 -0
  122. package/src/orchestrator/templates/ai-instructions/claude-cmd-create-test.md +11 -8
  123. package/src/orchestrator/templates/ai-instructions/claude-cmd-review.md +8 -6
  124. package/src/orchestrator/templates/ai-instructions/claude-cmd-run-test.md +15 -11
  125. package/src/orchestrator/templates/ai-instructions/claude-config.md +41 -10
  126. package/src/orchestrator/templates/ai-instructions/claude-skill-capture-live.md +12 -0
  127. package/src/orchestrator/templates/ai-instructions/claude-skill-delivery.md +19 -18
  128. package/src/orchestrator/templates/ai-instructions/claude-skill-error-mapping.md +12 -0
  129. package/src/orchestrator/templates/ai-instructions/claude-skill-gherkin-syntax.md +52 -0
  130. package/src/orchestrator/templates/ai-instructions/claude-skill-selector-fix.md +31 -3
  131. package/src/orchestrator/templates/ai-instructions/claude-skill-selector-keys.md +45 -0
  132. package/src/orchestrator/templates/ai-instructions/claude-skill-tc-generation.md +69 -0
  133. package/src/orchestrator/templates/ai-instructions/claude-skill-tc-review.md +30 -0
  134. package/src/orchestrator/templates/ai-instructions/copilot-cmd-add-flow.md +86 -0
  135. package/src/orchestrator/templates/ai-instructions/copilot-cmd-create-test.md +13 -10
  136. package/src/orchestrator/templates/ai-instructions/copilot-cmd-delivery.md +18 -17
  137. package/src/orchestrator/templates/ai-instructions/copilot-cmd-review.md +9 -7
  138. package/src/orchestrator/templates/ai-instructions/copilot-cmd-run-test.md +23 -19
  139. package/src/orchestrator/templates/ai-instructions/copilot-config.md +40 -9
  140. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-capture-live.md +12 -0
  141. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-delivery.md +19 -18
  142. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-error-mapping.md +12 -0
  143. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-gherkin-syntax.md +52 -0
  144. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-selector-fix.md +31 -3
  145. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-selector-keys.md +45 -0
  146. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-generation.md +70 -0
  147. package/src/orchestrator/templates/ai-instructions/github-skill-sungen-tc-review.md +30 -0
  148. package/src/orchestrator/templates/playwright.config.ts +4 -1
  149. package/src/orchestrator/templates/specs-base.ts +11 -61
  150. package/src/orchestrator/templates/specs-test-data.ts +9 -2
  151. package/dist/utils/feature-finder.d.ts +0 -9
  152. package/dist/utils/feature-finder.d.ts.map +0 -1
  153. package/dist/utils/feature-finder.js +0 -67
  154. package/dist/utils/feature-finder.js.map +0 -1
  155. package/dist/utils/screen-paths.d.ts +0 -10
  156. package/dist/utils/screen-paths.d.ts.map +0 -1
  157. package/dist/utils/screen-paths.js +0 -73
  158. package/dist/utils/screen-paths.js.map +0 -1
  159. package/dist/utils/selector-loader.d.ts +0 -6
  160. package/dist/utils/selector-loader.d.ts.map +0 -1
  161. package/dist/utils/selector-loader.js +0 -20
  162. package/dist/utils/selector-loader.js.map +0 -1
  163. package/dist/utils/test-data-loader.d.ts +0 -6
  164. package/dist/utils/test-data-loader.d.ts.map +0 -1
  165. package/dist/utils/test-data-loader.js +0 -20
  166. package/dist/utils/test-data-loader.js.map +0 -1
  167. package/src/utils/feature-finder.ts +0 -33
  168. package/src/utils/screen-paths.ts +0 -37
  169. package/src/utils/selector-loader.ts +0 -23
  170. package/src/utils/test-data-loader.ts +0 -23
@@ -22,7 +22,7 @@ export default defineConfig({
22
22
  /* Opt out of parallel tests on CI. */
23
23
  workers: process.env.CI ? 1 : 2,
24
24
  /* Global timeout per test */
25
- timeout: 10_000,
25
+ timeout: 15_000,
26
26
  /* Reporter to use. See https://playwright.dev/docs/test-reporters */
27
27
  /* JSON reporter is required by `sungen delivery` to populate test result columns in the exported CSV. */
28
28
  /* Output file path is controlled by PLAYWRIGHT_JSON_OUTPUT_NAME env var for per-screen isolation. */
@@ -35,6 +35,9 @@ export default defineConfig({
35
35
  /* Base URL to use in actions like `await page.goto('')`. */
36
36
  baseURL: 'https://example.com',
37
37
 
38
+ /* Per-action timeout (click, fill, etc.) */
39
+ actionTimeout: 10_000,
40
+
38
41
  /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
39
42
  trace: 'on-first-retry',
40
43
  },
@@ -1,5 +1,4 @@
1
1
  import { test as base, expect } from '@playwright/test';
2
- import type { BrowserContext, Page } from '@playwright/test';
3
2
 
4
3
  type CleanupConfig = {
5
4
  overlay?: boolean;
@@ -8,11 +7,6 @@ type CleanupConfig = {
8
7
  storage?: boolean;
9
8
  };
10
9
 
11
- // Share one context per storageState — avoids creating multiple sessions
12
- // that trigger server rate limiting or session invalidation
13
- const contextCache = new Map<string, { context: BrowserContext; page: Page }>();
14
- const GOTO_PATCHED = Symbol('goto-patched');
15
-
16
10
  const test = base.extend<{
17
11
  autoCleanup: CleanupConfig;
18
12
  screenshotOnFailure: boolean;
@@ -23,69 +17,25 @@ const test = base.extend<{
23
17
  screenshotOnFailure: [false, { option: true }],
24
18
 
25
19
  page: async ({ browser, storageState }, use) => {
26
- if (storageState) {
27
- const cacheKey = typeof storageState === 'string' ? storageState : JSON.stringify(storageState);
28
-
29
- let cached = contextCache.get(cacheKey);
30
- if (!cached) {
31
- const context = await browser.newContext({ storageState });
32
- const page = await context.newPage();
33
- cached = { context, page };
34
- contextCache.set(cacheKey, cached);
35
- }
36
-
37
- const page = cached.page;
38
-
39
- // Patch goto once: skip navigation if already on the target path
40
- if (!(page as any)[GOTO_PATCHED]) {
41
- const originalGoto = page.goto.bind(page);
42
- page.goto = async function (url: string, options?: any) {
43
- try {
44
- const currentPath = new URL(page.url()).pathname;
45
- if (currentPath === url || currentPath === url + '/') {
46
- const hasOverlay = await page.evaluate(`(() => {
47
- const el = document.elementFromPoint(window.innerWidth / 2, window.innerHeight / 2);
48
- if (!el) return false;
49
- let current = el;
50
- while (current && current !== document.body) {
51
- if (getComputedStyle(current).position === 'fixed') return true;
52
- current = current.parentElement;
53
- }
54
- return false;
55
- })()`).catch(() => true);
56
-
57
- if (hasOverlay) {
58
- return originalGoto(url, options);
59
- }
60
- return null as any;
61
- }
62
- } catch {
63
- // page.url() might be about:blank on first run
64
- }
65
- return originalGoto(url, options);
66
- };
67
- (page as any)[GOTO_PATCHED] = true;
68
- }
69
-
70
- await use(page);
71
- } else {
72
- // No storageState: fresh context (e.g., unauthenticated tests)
73
- const context = await browser.newContext();
74
- const page = await context.newPage();
75
- await use(page);
76
- await page.close();
77
- await context.close();
78
- }
20
+ const context = storageState
21
+ ? await browser.newContext({ storageState })
22
+ : await browser.newContext();
23
+ const page = await context.newPage();
24
+ await use(page);
25
+ await page.close();
26
+ await context.close();
79
27
  },
80
28
 
81
29
  // Auto-cleanup fixture: runs teardown after each test based on @cleanup:* tags
82
- _autoCleanup: [async ({ page, autoCleanup }, use) => {
30
+ _autoCleanup: [async ({ page, autoCleanup }, use, testInfo) => {
83
31
  await use();
84
32
 
33
+ // Only run cleanup when the test failed — avoids masking state for the next test
34
+ if (testInfo.status === testInfo.expectedStatus) return;
35
+
85
36
  if (autoCleanup.overlay) {
86
37
  await page.keyboard.press('Escape').catch(() => {});
87
38
  await page.locator('body').click({ position: { x: 1, y: 1 }, force: true }).catch(() => {});
88
- // Dismiss persistent fixed overlays (modals, dialogs)
89
39
  const hasOverlay = await page.evaluate(`(() => {
90
40
  const el = document.elementFromPoint(window.innerWidth / 2, window.innerHeight / 2);
91
41
  if (!el) return false;
@@ -10,14 +10,21 @@ export class TestDataLoader {
10
10
  }
11
11
 
12
12
  /**
13
- * Load test data for a screen/feature combination.
13
+ * Load test data for a screen/feature or flow/feature combination.
14
14
  *
15
15
  * Priority (later wins):
16
16
  * 1. {feature}.yaml — base data
17
17
  * 2. {feature}.{SUNGEN_ENV}.yaml — environment-specific (if SUNGEN_ENV set)
18
+ *
19
+ * Paths: screenName starting with "flows/" loads from qa/flows/, otherwise qa/screens/
18
20
  */
19
21
  static load(screenName: string, featureName: string): TestDataLoader {
20
- const baseDir = path.join(process.cwd(), 'qa', 'screens', screenName, 'test-data');
22
+ let baseDir: string;
23
+ if (screenName.startsWith('flows/')) {
24
+ baseDir = path.join(process.cwd(), 'qa', screenName, 'test-data');
25
+ } else {
26
+ baseDir = path.join(process.cwd(), 'qa', 'screens', screenName, 'test-data');
27
+ }
21
28
  const env = process.env.SUNGEN_ENV;
22
29
 
23
30
  let data = loadYamlSync(path.join(baseDir, `${featureName}.yaml`)) || {};
@@ -1,9 +0,0 @@
1
- /**
2
- * Find all .feature files for a specific screen.
3
- */
4
- export declare function findFeatureFiles(screensRoot: string, screenName: string): string[];
5
- /**
6
- * Find all .feature files across all screens.
7
- */
8
- export declare function findAllFeatureFiles(screensRoot: string): string[];
9
- //# sourceMappingURL=feature-finder.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"feature-finder.d.ts","sourceRoot":"","sources":["../../src/utils/feature-finder.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAQlF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAYjE"}
@@ -1,67 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.findFeatureFiles = findFeatureFiles;
37
- exports.findAllFeatureFiles = findAllFeatureFiles;
38
- const fs = __importStar(require("fs"));
39
- const path = __importStar(require("path"));
40
- const screen_paths_1 = require("./screen-paths");
41
- /**
42
- * Find all .feature files for a specific screen.
43
- */
44
- function findFeatureFiles(screensRoot, screenName) {
45
- const featuresDir = (0, screen_paths_1.getFeaturesDir)(screensRoot, screenName);
46
- if (!fs.existsSync(featuresDir)) {
47
- return [];
48
- }
49
- return fs.readdirSync(featuresDir)
50
- .filter(f => f.endsWith('.feature'))
51
- .map(f => path.join(featuresDir, f));
52
- }
53
- /**
54
- * Find all .feature files across all screens.
55
- */
56
- function findAllFeatureFiles(screensRoot) {
57
- if (!fs.existsSync(screensRoot)) {
58
- return [];
59
- }
60
- const files = [];
61
- const screens = fs.readdirSync(screensRoot).filter(d => fs.statSync(path.join(screensRoot, d)).isDirectory());
62
- for (const screen of screens) {
63
- files.push(...findFeatureFiles(screensRoot, screen));
64
- }
65
- return files;
66
- }
67
- //# sourceMappingURL=feature-finder.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"feature-finder.js","sourceRoot":"","sources":["../../src/utils/feature-finder.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAOA,4CAQC;AAKD,kDAYC;AAhCD,uCAAyB;AACzB,2CAA6B;AAC7B,iDAAgD;AAEhD;;GAEG;AACH,SAAgB,gBAAgB,CAAC,WAAmB,EAAE,UAAkB;IACtE,MAAM,WAAW,GAAG,IAAA,6BAAc,EAAC,WAAW,EAAE,UAAU,CAAC,CAAC;IAC5D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAChC,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,OAAO,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC;SAC/B,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;SACnC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,SAAgB,mBAAmB,CAAC,WAAmB;IACrD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAChC,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CACrD,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CACrD,CAAC;IACF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,KAAK,CAAC,IAAI,CAAC,GAAG,gBAAgB,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -1,10 +0,0 @@
1
- export declare function getScreenDir(screensRoot: string, screenName: string): string;
2
- export declare function getFeaturesDir(screensRoot: string, screenName: string): string;
3
- export declare function getSelectorsDir(screensRoot: string, screenName: string): string;
4
- export declare function getTestDataDir(screensRoot: string, screenName: string): string;
5
- export declare function getSelectorBasePath(screensRoot: string, screenName: string, featureName: string): string;
6
- export declare function getSelectorOverridePath(screensRoot: string, screenName: string, featureName: string): string;
7
- export declare function getTestDataBasePath(screensRoot: string, screenName: string, featureName: string): string;
8
- export declare function getTestDataOverridePath(screensRoot: string, screenName: string, featureName: string): string;
9
- export declare function getLiveScanPath(screensRoot: string, screenName: string, featureName: string): string;
10
- //# sourceMappingURL=screen-paths.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"screen-paths.d.ts","sourceRoot":"","sources":["../../src/utils/screen-paths.ts"],"names":[],"mappings":"AAEA,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAE5E;AAED,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAE/E;AAED,wBAAgB,cAAc,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAE9E;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAExG;AAED,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAE5G;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAExG;AAED,wBAAgB,uBAAuB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAE5G;AAED,wBAAgB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAEpG"}
@@ -1,73 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.getScreenDir = getScreenDir;
37
- exports.getFeaturesDir = getFeaturesDir;
38
- exports.getSelectorsDir = getSelectorsDir;
39
- exports.getTestDataDir = getTestDataDir;
40
- exports.getSelectorBasePath = getSelectorBasePath;
41
- exports.getSelectorOverridePath = getSelectorOverridePath;
42
- exports.getTestDataBasePath = getTestDataBasePath;
43
- exports.getTestDataOverridePath = getTestDataOverridePath;
44
- exports.getLiveScanPath = getLiveScanPath;
45
- const path = __importStar(require("path"));
46
- function getScreenDir(screensRoot, screenName) {
47
- return path.join(screensRoot, screenName);
48
- }
49
- function getFeaturesDir(screensRoot, screenName) {
50
- return path.join(screensRoot, screenName, 'features');
51
- }
52
- function getSelectorsDir(screensRoot, screenName) {
53
- return path.join(screensRoot, screenName, 'selectors');
54
- }
55
- function getTestDataDir(screensRoot, screenName) {
56
- return path.join(screensRoot, screenName, 'test-data');
57
- }
58
- function getSelectorBasePath(screensRoot, screenName, featureName) {
59
- return path.join(screensRoot, screenName, 'selectors', `${featureName}.yaml`);
60
- }
61
- function getSelectorOverridePath(screensRoot, screenName, featureName) {
62
- return path.join(screensRoot, screenName, 'selectors', `${featureName}.override.yaml`);
63
- }
64
- function getTestDataBasePath(screensRoot, screenName, featureName) {
65
- return path.join(screensRoot, screenName, 'test-data', `${featureName}.yaml`);
66
- }
67
- function getTestDataOverridePath(screensRoot, screenName, featureName) {
68
- return path.join(screensRoot, screenName, 'test-data', `${featureName}.override.yaml`);
69
- }
70
- function getLiveScanPath(screensRoot, screenName, featureName) {
71
- return path.join(screensRoot, screenName, 'selectors', `${featureName}.live-scan.yaml`);
72
- }
73
- //# sourceMappingURL=screen-paths.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"screen-paths.js","sourceRoot":"","sources":["../../src/utils/screen-paths.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,oCAEC;AAED,wCAEC;AAED,0CAEC;AAED,wCAEC;AAED,kDAEC;AAED,0DAEC;AAED,kDAEC;AAED,0DAEC;AAED,0CAEC;AApCD,2CAA6B;AAE7B,SAAgB,YAAY,CAAC,WAAmB,EAAE,UAAkB;IAClE,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;AAC5C,CAAC;AAED,SAAgB,cAAc,CAAC,WAAmB,EAAE,UAAkB;IACpE,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,UAAU,CAAC,CAAC;AACxD,CAAC;AAED,SAAgB,eAAe,CAAC,WAAmB,EAAE,UAAkB;IACrE,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;AACzD,CAAC;AAED,SAAgB,cAAc,CAAC,WAAmB,EAAE,UAAkB;IACpE,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;AACzD,CAAC;AAED,SAAgB,mBAAmB,CAAC,WAAmB,EAAE,UAAkB,EAAE,WAAmB;IAC9F,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,WAAW,OAAO,CAAC,CAAC;AAChF,CAAC;AAED,SAAgB,uBAAuB,CAAC,WAAmB,EAAE,UAAkB,EAAE,WAAmB;IAClG,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,WAAW,gBAAgB,CAAC,CAAC;AACzF,CAAC;AAED,SAAgB,mBAAmB,CAAC,WAAmB,EAAE,UAAkB,EAAE,WAAmB;IAC9F,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,WAAW,OAAO,CAAC,CAAC;AAChF,CAAC;AAED,SAAgB,uBAAuB,CAAC,WAAmB,EAAE,UAAkB,EAAE,WAAmB;IAClG,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,WAAW,gBAAgB,CAAC,CAAC;AACzF,CAAC;AAED,SAAgB,eAAe,CAAC,WAAmB,EAAE,UAAkB,EAAE,WAAmB;IAC1F,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,WAAW,iBAAiB,CAAC,CAAC;AAC1F,CAAC"}
@@ -1,6 +0,0 @@
1
- /**
2
- * Load selectors for a feature, merging base and override files.
3
- * Returns empty object if no files found.
4
- */
5
- export declare function loadSelectors<T = Record<string, any>>(screensRoot: string, screenName: string, featureName: string): T;
6
- //# sourceMappingURL=selector-loader.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"selector-loader.d.ts","sourceRoot":"","sources":["../../src/utils/selector-loader.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EACnD,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,CAAC,CAWH"}
@@ -1,20 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.loadSelectors = loadSelectors;
4
- const yaml_io_1 = require("./yaml-io");
5
- const screen_paths_1 = require("./screen-paths");
6
- /**
7
- * Load selectors for a feature, merging base and override files.
8
- * Returns empty object if no files found.
9
- */
10
- function loadSelectors(screensRoot, screenName, featureName) {
11
- const basePath = (0, screen_paths_1.getSelectorBasePath)(screensRoot, screenName, featureName);
12
- const overridePath = (0, screen_paths_1.getSelectorOverridePath)(screensRoot, screenName, featureName);
13
- const base = (0, yaml_io_1.readYamlIfExists)(basePath) || {};
14
- const override = (0, yaml_io_1.readYamlIfExists)(overridePath);
15
- if (override) {
16
- return { ...base, ...override };
17
- }
18
- return base;
19
- }
20
- //# sourceMappingURL=selector-loader.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"selector-loader.js","sourceRoot":"","sources":["../../src/utils/selector-loader.ts"],"names":[],"mappings":";;AAOA,sCAeC;AAtBD,uCAA6C;AAC7C,iDAA8E;AAE9E;;;GAGG;AACH,SAAgB,aAAa,CAC3B,WAAmB,EACnB,UAAkB,EAClB,WAAmB;IAEnB,MAAM,QAAQ,GAAG,IAAA,kCAAmB,EAAC,WAAW,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IAC3E,MAAM,YAAY,GAAG,IAAA,sCAAuB,EAAC,WAAW,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IAEnF,MAAM,IAAI,GAAG,IAAA,0BAAgB,EAAI,QAAQ,CAAC,IAAI,EAAO,CAAC;IACtD,MAAM,QAAQ,GAAG,IAAA,0BAAgB,EAAI,YAAY,CAAC,CAAC;IAEnD,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,QAAQ,EAAE,CAAC;IAClC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -1,6 +0,0 @@
1
- /**
2
- * Load test data for a feature, merging base and override files.
3
- * Returns empty object if no files found.
4
- */
5
- export declare function loadTestData<T = Record<string, any>>(screensRoot: string, screenName: string, featureName: string): T;
6
- //# sourceMappingURL=test-data-loader.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"test-data-loader.d.ts","sourceRoot":"","sources":["../../src/utils/test-data-loader.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAClD,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,GAClB,CAAC,CAWH"}
@@ -1,20 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.loadTestData = loadTestData;
4
- const yaml_io_1 = require("./yaml-io");
5
- const screen_paths_1 = require("./screen-paths");
6
- /**
7
- * Load test data for a feature, merging base and override files.
8
- * Returns empty object if no files found.
9
- */
10
- function loadTestData(screensRoot, screenName, featureName) {
11
- const basePath = (0, screen_paths_1.getTestDataBasePath)(screensRoot, screenName, featureName);
12
- const overridePath = (0, screen_paths_1.getTestDataOverridePath)(screensRoot, screenName, featureName);
13
- const base = (0, yaml_io_1.readYamlIfExists)(basePath) || {};
14
- const override = (0, yaml_io_1.readYamlIfExists)(overridePath);
15
- if (override) {
16
- return { ...base, ...override };
17
- }
18
- return base;
19
- }
20
- //# sourceMappingURL=test-data-loader.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"test-data-loader.js","sourceRoot":"","sources":["../../src/utils/test-data-loader.ts"],"names":[],"mappings":";;AAOA,oCAeC;AAtBD,uCAA6C;AAC7C,iDAA8E;AAE9E;;;GAGG;AACH,SAAgB,YAAY,CAC1B,WAAmB,EACnB,UAAkB,EAClB,WAAmB;IAEnB,MAAM,QAAQ,GAAG,IAAA,kCAAmB,EAAC,WAAW,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IAC3E,MAAM,YAAY,GAAG,IAAA,sCAAuB,EAAC,WAAW,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;IAEnF,MAAM,IAAI,GAAG,IAAA,0BAAgB,EAAI,QAAQ,CAAC,IAAI,EAAO,CAAC;IACtD,MAAM,QAAQ,GAAG,IAAA,0BAAgB,EAAI,YAAY,CAAC,CAAC;IAEnD,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,QAAQ,EAAE,CAAC;IAClC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -1,33 +0,0 @@
1
- import * as fs from 'fs';
2
- import * as path from 'path';
3
- import { getFeaturesDir } from './screen-paths';
4
-
5
- /**
6
- * Find all .feature files for a specific screen.
7
- */
8
- export function findFeatureFiles(screensRoot: string, screenName: string): string[] {
9
- const featuresDir = getFeaturesDir(screensRoot, screenName);
10
- if (!fs.existsSync(featuresDir)) {
11
- return [];
12
- }
13
- return fs.readdirSync(featuresDir)
14
- .filter(f => f.endsWith('.feature'))
15
- .map(f => path.join(featuresDir, f));
16
- }
17
-
18
- /**
19
- * Find all .feature files across all screens.
20
- */
21
- export function findAllFeatureFiles(screensRoot: string): string[] {
22
- if (!fs.existsSync(screensRoot)) {
23
- return [];
24
- }
25
- const files: string[] = [];
26
- const screens = fs.readdirSync(screensRoot).filter(d =>
27
- fs.statSync(path.join(screensRoot, d)).isDirectory()
28
- );
29
- for (const screen of screens) {
30
- files.push(...findFeatureFiles(screensRoot, screen));
31
- }
32
- return files;
33
- }
@@ -1,37 +0,0 @@
1
- import * as path from 'path';
2
-
3
- export function getScreenDir(screensRoot: string, screenName: string): string {
4
- return path.join(screensRoot, screenName);
5
- }
6
-
7
- export function getFeaturesDir(screensRoot: string, screenName: string): string {
8
- return path.join(screensRoot, screenName, 'features');
9
- }
10
-
11
- export function getSelectorsDir(screensRoot: string, screenName: string): string {
12
- return path.join(screensRoot, screenName, 'selectors');
13
- }
14
-
15
- export function getTestDataDir(screensRoot: string, screenName: string): string {
16
- return path.join(screensRoot, screenName, 'test-data');
17
- }
18
-
19
- export function getSelectorBasePath(screensRoot: string, screenName: string, featureName: string): string {
20
- return path.join(screensRoot, screenName, 'selectors', `${featureName}.yaml`);
21
- }
22
-
23
- export function getSelectorOverridePath(screensRoot: string, screenName: string, featureName: string): string {
24
- return path.join(screensRoot, screenName, 'selectors', `${featureName}.override.yaml`);
25
- }
26
-
27
- export function getTestDataBasePath(screensRoot: string, screenName: string, featureName: string): string {
28
- return path.join(screensRoot, screenName, 'test-data', `${featureName}.yaml`);
29
- }
30
-
31
- export function getTestDataOverridePath(screensRoot: string, screenName: string, featureName: string): string {
32
- return path.join(screensRoot, screenName, 'test-data', `${featureName}.override.yaml`);
33
- }
34
-
35
- export function getLiveScanPath(screensRoot: string, screenName: string, featureName: string): string {
36
- return path.join(screensRoot, screenName, 'selectors', `${featureName}.live-scan.yaml`);
37
- }
@@ -1,23 +0,0 @@
1
- import { readYamlIfExists } from './yaml-io';
2
- import { getSelectorBasePath, getSelectorOverridePath } from './screen-paths';
3
-
4
- /**
5
- * Load selectors for a feature, merging base and override files.
6
- * Returns empty object if no files found.
7
- */
8
- export function loadSelectors<T = Record<string, any>>(
9
- screensRoot: string,
10
- screenName: string,
11
- featureName: string
12
- ): T {
13
- const basePath = getSelectorBasePath(screensRoot, screenName, featureName);
14
- const overridePath = getSelectorOverridePath(screensRoot, screenName, featureName);
15
-
16
- const base = readYamlIfExists<T>(basePath) || {} as T;
17
- const override = readYamlIfExists<T>(overridePath);
18
-
19
- if (override) {
20
- return { ...base, ...override };
21
- }
22
- return base;
23
- }
@@ -1,23 +0,0 @@
1
- import { readYamlIfExists } from './yaml-io';
2
- import { getTestDataBasePath, getTestDataOverridePath } from './screen-paths';
3
-
4
- /**
5
- * Load test data for a feature, merging base and override files.
6
- * Returns empty object if no files found.
7
- */
8
- export function loadTestData<T = Record<string, any>>(
9
- screensRoot: string,
10
- screenName: string,
11
- featureName: string
12
- ): T {
13
- const basePath = getTestDataBasePath(screensRoot, screenName, featureName);
14
- const overridePath = getTestDataOverridePath(screensRoot, screenName, featureName);
15
-
16
- const base = readYamlIfExists<T>(basePath) || {} as T;
17
- const override = readYamlIfExists<T>(overridePath);
18
-
19
- if (override) {
20
- return { ...base, ...override };
21
- }
22
- return base;
23
- }