@autotests/playwright-impact 0.1.0 → 0.1.2

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/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2026 Alex Kiselev
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md CHANGED
@@ -1,117 +1,149 @@
1
- # test-impact-core
1
+ # Playwright Spec Impact
2
2
 
3
- Select only impacted Playwright specs from changed POM and utility methods.
3
+ If you use Playwright + POM and your CI runs are slow, this library selects only specs affected by your changes.
4
4
 
5
- `test-impact-core` is built for Playwright teams using Page Object Model who want faster feedback and shorter CI cycles without running the full test suite on every commit.
6
-
7
- It solves a common problem: broad reruns after small UI/POM changes. Instead of running everything, it computes the smallest reliable spec set to execute.
5
+ It reads changed files, finds impacted specs, and helps you run only what matters.
8
6
 
9
7
  ## Install
10
8
 
11
9
  ```bash
12
10
  // npm
13
- npm i @autotests/test-impact-core
11
+ npm i @autotests/playwright-impact
14
12
 
15
13
  // pnpm
16
- pnpm add @autotests/test-impact-core
14
+ pnpm add @autotests/playwright-impact
17
15
  ```
18
16
 
19
- ## Why
17
+ ## Quick Start (Copy & Run)
20
18
 
21
- - Large Playwright projects grow quickly, and full-suite runs become expensive.
22
- - POM-heavy repositories often change in narrow areas but still trigger wide test execution.
23
- - Running all specs for each PR slows CI, delays triage, and increases infrastructure cost.
24
- - `test-impact-core` changes this by selecting only specs impacted by changed files and changed method behavior.
19
+ ### Minimal working code
25
20
 
26
- ## 30-Second Setup (Minimum Required Configuration)
21
+ Create `impact.js` in your repo root:
27
22
 
28
- Only these fields are required. Everything else has defaults.
23
+ ```js
24
+ const { analyzeImpactedSpecs } = require('@autotests/playwright-impact');
29
25
 
30
- - `repoRoot`: absolute path to repository root.
31
- - `profile.testsRootRelative`: where Playwright specs live.
32
- - `profile.changedSpecPrefix`: prefix used to detect directly changed spec files.
33
- - `profile.isRelevantPomPath(filePath)`: rule that marks which source files are considered POM/utility inputs for impact analysis.
26
+ const result = analyzeImpactedSpecs({
27
+ repoRoot: process.cwd(),
28
+ profile: {
29
+ testsRootRelative: 'tests',
30
+ changedSpecPrefix: 'tests/',
31
+ isRelevantPomPath: (filePath) =>
32
+ (filePath.startsWith('src/pages/') || filePath.startsWith('src/utils/')) &&
33
+ (filePath.endsWith('.ts') || filePath.endsWith('.tsx')),
34
+ },
35
+ });
34
36
 
35
- Public API entry point: `analyzeImpactedSpecs`.
37
+ if (!result.hasAnythingToRun) {
38
+ console.log('No impacted specs found');
39
+ process.exit(0);
40
+ }
36
41
 
37
- ## Typical CI Usage
42
+ for (const spec of result.selectedSpecsRelative) {
43
+ console.log(spec);
44
+ }
45
+ ```
38
46
 
39
- Typical workflow in CI:
47
+ Save as `impact.js`
40
48
 
41
- 1. Compare feature branch changes against `main` (via `baseRef`).
42
- 2. Compute impacted specs.
43
- 3. Exit early when `hasAnythingToRun` is false.
44
- 4. Run only `selectedSpecsRelative` in Playwright.
49
+ Run: `node impact.js`
45
50
 
46
- This pattern reduces pipeline time while keeping selection practical and explainable.
51
+ Use output paths in your Playwright CLI
47
52
 
48
- ## How It Works (High Level)
53
+ ### What you need to change
49
54
 
50
- 1. Read changed files from Git.
51
- 2. Mark directly changed spec files.
52
- 3. Detect semantic impact in changed POM/utility methods.
53
- 4. Map impacted methods to fixture usage in specs.
54
- 5. Apply selection policy and return final spec set.
55
+ You only need to adjust:
55
56
 
56
- ## Before/After Example (Text)
57
+ - `testsRootRelative`: folder where your Playwright specs live.
58
+ - `changedSpecPrefix`: prefix used to detect directly changed specs.
59
+ - `isRelevantPomPath`: rule for which source files are treated as POM/utility inputs.
57
60
 
58
- Before:
59
- - A change in one shared POM/utility file often leads teams to run a large suite or the full project.
61
+ ### Example output
60
62
 
61
- After with `test-impact-core`:
62
- - The same change results in a narrowed list of impacted specs only.
63
- - Directly changed specs are still always included.
64
- - CI runs faster, and failures are easier to link to the actual code change.
63
+ Example output:
65
64
 
66
- ## Configuration
65
+ ```text
66
+ tests/auth/login.spec.ts
67
+ tests/cart/cart.spec.ts
68
+ ```
67
69
 
68
- ### Required
70
+ If nothing is impacted:
69
71
 
70
- - `repoRoot`: absolute path to repository root.
71
- - `profile`: project configuration object.
72
- - `profile.testsRootRelative`: tests root relative path.
73
- - `profile.changedSpecPrefix`: prefix for direct changed spec detection.
74
- - `profile.isRelevantPomPath(filePath)`: function that returns true for relevant POM/utility files.
72
+ ```text
73
+ No impacted specs found
74
+ ```
75
75
 
76
- ### Optional (Advanced)
76
+ ## Minimal CI Script
77
77
 
78
- Most teams can skip these initially.
78
+ Use this when your branch is compared to `origin/main`.
79
79
 
80
- - `analysisRootsRelative`: roots for class/method graph scan. Default: `['src/pages', 'src/utils']`.
81
- - `fixturesTypesRelative`: fixture map file path. Default: `src/fixtures/types.ts`.
82
- - `baseRef`: git ref for comparison (example: `origin/main`).
83
- - `includeUntrackedSpecs` (default `true`): include untracked `*.spec.ts`/`*.spec.tsx` as direct changed specs.
84
- - `includeWorkingTreeWithBase` (default `true`): when `baseRef` is set, union committed diff (`base...HEAD`) with current working tree diff (`HEAD`).
85
- - `fileExtensions` (default `['.ts', '.tsx']`): file extensions to analyze.
86
- - `selectionBias` (default `'fail-open'`): uncertain call-site behavior.
80
+ ```js
81
+ const { analyzeImpactedSpecs } = require('@autotests/playwright-impact');
87
82
 
88
- ## Result Fields (Most Used)
83
+ const result = analyzeImpactedSpecs({
84
+ repoRoot: process.cwd(),
85
+ baseRef: 'origin/main',
86
+ profile: {
87
+ testsRootRelative: 'tests',
88
+ changedSpecPrefix: 'tests/',
89
+ isRelevantPomPath: (filePath) =>
90
+ (filePath.startsWith('src/pages/') || filePath.startsWith('src/utils/')) &&
91
+ (filePath.endsWith('.ts') || filePath.endsWith('.tsx')),
92
+ },
93
+ });
89
94
 
90
- - `selectedSpecsRelative`: relative paths for your test runner CLI.
91
- - `hasAnythingToRun`: quick boolean for early exit.
92
- - `selectionReasons`: reason code per selected spec.
95
+ if (!result.hasAnythingToRun) {
96
+ console.log('No impacted specs found');
97
+ process.exit(0);
98
+ }
93
99
 
94
- ## Advanced Diagnostics
100
+ console.log(result.selectedSpecsRelative.join(' '));
101
+ ```
95
102
 
96
- - `warnings`: compatibility or uncertainty warnings.
97
- - `coverageStats.uncertainCallSites`: count of uncertain call sites encountered.
98
- - `coverageStats.statusFallbackHits`: count of git status fallbacks (`C/T/U/unknown`).
99
- - `changedEntriesBySource`: diagnostics for diff sources (`base...HEAD`, working tree, untracked).
103
+ ## Typical CI Usage
100
104
 
101
- ### Reason Codes
105
+ 1. Compare current branch with `origin/main`.
106
+ 2. Compute impacted specs.
107
+ 3. Exit with `0` if nothing should run.
108
+ 4. Pass `selectedSpecsRelative` to your Playwright runner.
109
+
110
+ ## How It Works (High Level)
111
+
112
+ 1. Read changed files from Git.
113
+ 2. Include directly changed specs.
114
+ 3. Detect impacted specs from changed POM/utility code.
115
+ 4. Return a final spec list.
102
116
 
103
- - `direct-changed-spec`: spec was directly changed in git/untracked set.
104
- - `matched-precise`: spec has precise impacted fixture method usage.
105
- - `matched-uncertain-fail-open`: uncertain match retained by fail-open policy.
106
- - `retained-no-bindings`: spec kept because no fixture bindings were found in callback params.
117
+ ## Advanced Config
107
118
 
108
- ### Selection Policy (`selectionBias`)
119
+ Required:
120
+
121
+ - `repoRoot`
122
+ - `profile.testsRootRelative`
123
+ - `profile.changedSpecPrefix`
124
+ - `profile.isRelevantPomPath(filePath)`
125
+
126
+ Optional:
127
+
128
+ - `analysisRootsRelative`
129
+ - `fixturesTypesRelative`
130
+ - `baseRef`
131
+ - `includeUntrackedSpecs`
132
+ - `includeWorkingTreeWithBase`
133
+ - `fileExtensions`
134
+ - `selectionBias`
135
+
136
+ ## Advanced Diagnostics
109
137
 
110
- - Default: `fail-open` for pragmatic safety.
111
- - Alternative: `fail-closed` to drop uncertain matches.
138
+ - `warnings`
139
+ - `selectionReasons`
140
+ - `coverageStats.uncertainCallSites`
141
+ - `coverageStats.statusFallbackHits`
142
+ - `changedEntriesBySource`
112
143
 
113
- ## Notes
144
+ ## Reason Codes
114
145
 
115
- - This library is intentionally pragmatic and defaults to `selectionBias: 'fail-open'`.
116
- - For maximum safety, use `fail-open` in CI and monitor `warnings`/`uncertainCallSites`.
117
- - Use deterministic input (`baseRef`, clean profile predicates) for deterministic output.
146
+ - `direct-changed-spec`
147
+ - `matched-precise`
148
+ - `matched-uncertain-fail-open`
149
+ - `retained-no-bindings`
package/package.json CHANGED
@@ -1,8 +1,16 @@
1
1
  {
2
2
  "name": "@autotests/playwright-impact",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Core impacted-test selection library for changed POM/method analysis",
5
5
  "license": "ISC",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/akiselevaristek/playwright-impact.git"
9
+ },
10
+ "homepage": "https://github.com/akiselevaristek/playwright-impact#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/akiselevaristek/playwright-impact/issues"
13
+ },
6
14
  "main": "src/index.js",
7
15
  "exports": {
8
16
  ".": "./src/index.js"
@@ -11,7 +19,8 @@
11
19
  "files": [
12
20
  "src",
13
21
  "tests",
14
- "README.md"
22
+ "README.md",
23
+ "LICENSE"
15
24
  ],
16
25
  "publishConfig": {
17
26
  "access": "public"
@@ -44,6 +44,34 @@ const createBaseRepo = () => {
44
44
  return dir;
45
45
  };
46
46
 
47
+ test('README minimal profile style works with tests/ root and reports changed spec', () => {
48
+ const dir = createTempDir();
49
+ initGitRepo(dir);
50
+
51
+ writeFile(dir, 'src/pages/LoginPage.ts', 'export class LoginPage { open(){ return 1; } }\n');
52
+ writeFile(dir, 'src/utils/session.ts', 'export const getSession = () => "ok";\n');
53
+ writeFile(dir, 'src/fixtures/types.ts', 'type T = { loginPage: Pages.LoginPage };\n');
54
+ writeFile(dir, 'tests/auth/login.spec.ts', 'test("login", async ({ loginPage }) => { await loginPage.open(); });\n');
55
+ commitAll(dir, 'base');
56
+
57
+ const profile = {
58
+ testsRootRelative: 'tests',
59
+ changedSpecPrefix: 'tests/',
60
+ isRelevantPomPath: (filePath) =>
61
+ (filePath.startsWith('src/pages/') || filePath.startsWith('src/utils/')) &&
62
+ (filePath.endsWith('.ts') || filePath.endsWith('.tsx')),
63
+ };
64
+
65
+ const cleanResult = analyzeImpactedSpecs({ repoRoot: dir, profile });
66
+ assert.equal(cleanResult.hasAnythingToRun, false);
67
+
68
+ writeFile(dir, 'tests/auth/login.spec.ts', 'test("login", async ({ loginPage }) => { await loginPage.open(); await loginPage.open(); });\n');
69
+
70
+ const changedResult = analyzeImpactedSpecs({ repoRoot: dir, profile });
71
+ assert.equal(changedResult.hasAnythingToRun, true);
72
+ assert.equal(changedResult.selectedSpecsRelative.includes('tests/auth/login.spec.ts'), true);
73
+ });
74
+
47
75
  test('analyzeImpactedSpecs returns no work when nothing changed', () => {
48
76
  const dir = createBaseRepo();
49
77
  const result = analyzeImpactedSpecs({ repoRoot: dir, profile: genericProfile, includeUntrackedSpecs: true });