evizi-kit 1.0.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.
- package/README.md +506 -0
- package/kits/agent/.agent/skills/claude-code-subagent-creator/SKILL.md +292 -0
- package/kits/agent/.agent/skills/claude-code-subagent-creator/references/claude-code-subagent-configuration.md +158 -0
- package/kits/agent/.agent/skills/claude-code-subagent-creator/templates/subagent-profile.template.md +26 -0
- package/kits/agent/.agent/skills/skill-creator/LICENSE.txt +202 -0
- package/kits/agent/.agent/skills/skill-creator/SKILL.md +485 -0
- package/kits/agent/.agent/skills/skill-creator/agents/analyzer.md +274 -0
- package/kits/agent/.agent/skills/skill-creator/agents/comparator.md +202 -0
- package/kits/agent/.agent/skills/skill-creator/agents/grader.md +223 -0
- package/kits/agent/.agent/skills/skill-creator/assets/eval_review.html +146 -0
- package/kits/agent/.agent/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/kits/agent/.agent/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/kits/agent/.agent/skills/skill-creator/references/schemas.md +430 -0
- package/kits/agent/.agent/skills/skill-creator/scripts/__init__.py +0 -0
- package/kits/agent/.agent/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/kits/agent/.agent/skills/skill-creator/scripts/generate_report.py +326 -0
- package/kits/agent/.agent/skills/skill-creator/scripts/improve_description.py +247 -0
- package/kits/agent/.agent/skills/skill-creator/scripts/package_skill.py +136 -0
- package/kits/agent/.agent/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/kits/agent/.agent/skills/skill-creator/scripts/run_eval.py +310 -0
- package/kits/agent/.agent/skills/skill-creator/scripts/run_loop.py +328 -0
- package/kits/agent/.agent/skills/skill-creator/scripts/utils.py +47 -0
- package/kits/agent/manifest.json +10 -0
- package/kits/claude/.claude/agents/code-pusher.md +46 -0
- package/kits/claude/.claude/agents/feature-document-updater.md +37 -0
- package/kits/claude/.claude/agents/self-reviewer.md +32 -0
- package/kits/claude/.claude/agents/web-auto-agentic-workflow-initializer.md +42 -0
- package/kits/claude/.claude/agents/web-auto-assisted-fix-and-runner.md +36 -0
- package/kits/claude/.claude/agents/web-auto-chrome-devtools-selector-extractor.md +36 -0
- package/kits/claude/.claude/agents/web-auto-coder.md +33 -0
- package/kits/claude/.claude/agents/web-auto-fe-selector-extractor.md +31 -0
- package/kits/claude/.claude/agents/web-auto-fix-and-runner.md +35 -0
- package/kits/claude/.claude/agents/web-auto-lessons-learned-extractor.md +34 -0
- package/kits/claude/.claude/agents/web-auto-playwright-mcp-selector-extractor.md +37 -0
- package/kits/claude/.claude/agents/web-auto-source-instructions-updater.md +43 -0
- package/kits/claude/.claude/agents/web-auto-test-cases-generator.md +29 -0
- package/kits/claude/.claude/agents/web-auto-ticket-designer.md +35 -0
- package/kits/claude/.claude/agents/web-auto-ticket-playbook-planner.md +36 -0
- package/kits/claude/.claude/agents/web-auto.md +382 -0
- package/kits/claude/.claude/skills/claude-code-subagent-creator/SKILL.md +292 -0
- package/kits/claude/.claude/skills/claude-code-subagent-creator/references/claude-code-subagent-configuration.md +158 -0
- package/kits/claude/.claude/skills/claude-code-subagent-creator/templates/subagent-profile.template.md +26 -0
- package/kits/claude/.claude/skills/skill-creator/LICENSE.txt +202 -0
- package/kits/claude/.claude/skills/skill-creator/SKILL.md +485 -0
- package/kits/claude/.claude/skills/skill-creator/agents/analyzer.md +274 -0
- package/kits/claude/.claude/skills/skill-creator/agents/comparator.md +202 -0
- package/kits/claude/.claude/skills/skill-creator/agents/grader.md +223 -0
- package/kits/claude/.claude/skills/skill-creator/assets/eval_review.html +146 -0
- package/kits/claude/.claude/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/kits/claude/.claude/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/kits/claude/.claude/skills/skill-creator/references/schemas.md +430 -0
- package/kits/claude/.claude/skills/skill-creator/scripts/__init__.py +0 -0
- package/kits/claude/.claude/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/kits/claude/.claude/skills/skill-creator/scripts/generate_report.py +326 -0
- package/kits/claude/.claude/skills/skill-creator/scripts/improve_description.py +247 -0
- package/kits/claude/.claude/skills/skill-creator/scripts/package_skill.py +136 -0
- package/kits/claude/.claude/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/kits/claude/.claude/skills/skill-creator/scripts/run_eval.py +310 -0
- package/kits/claude/.claude/skills/skill-creator/scripts/run_loop.py +328 -0
- package/kits/claude/.claude/skills/skill-creator/scripts/utils.py +47 -0
- package/kits/claude/manifest.json +10 -0
- package/kits/cursor/.cursor/agents/code-pusher.agent.md +43 -0
- package/kits/cursor/.cursor/agents/feature-document-updater.agent.md +34 -0
- package/kits/cursor/.cursor/agents/self-reviewer.agent.md +29 -0
- package/kits/cursor/.cursor/agents/web-auto-agentic-workflow-initializer.agent.md +37 -0
- package/kits/cursor/.cursor/agents/web-auto-assisted-fix-and-runner.agent.md +33 -0
- package/kits/cursor/.cursor/agents/web-auto-chrome-devtools-selector-extractor.agent.md +31 -0
- package/kits/cursor/.cursor/agents/web-auto-coder.agent.md +30 -0
- package/kits/cursor/.cursor/agents/web-auto-fe-selector-extractor.agent.md +28 -0
- package/kits/cursor/.cursor/agents/web-auto-fix-and-runner.agent.md +32 -0
- package/kits/cursor/.cursor/agents/web-auto-lessons-learned-extractor.agent.md +31 -0
- package/kits/cursor/.cursor/agents/web-auto-playwright-mcp-selector-extractor.agent.md +32 -0
- package/kits/cursor/.cursor/agents/web-auto-source-instructions-updater.agent.md +40 -0
- package/kits/cursor/.cursor/agents/web-auto-test-cases-generator.agent.md +26 -0
- package/kits/cursor/.cursor/agents/web-auto-ticket-designer.agent.md +32 -0
- package/kits/cursor/.cursor/agents/web-auto-ticket-playbook-planner.agent.md +33 -0
- package/kits/cursor/.cursor/agents/web-auto.agent.md +379 -0
- package/kits/cursor/.cursor/skills/claude-code-subagent-creator/SKILL.md +292 -0
- package/kits/cursor/.cursor/skills/claude-code-subagent-creator/references/claude-code-subagent-configuration.md +158 -0
- package/kits/cursor/.cursor/skills/claude-code-subagent-creator/templates/subagent-profile.template.md +26 -0
- package/kits/cursor/.cursor/skills/skill-creator/LICENSE.txt +202 -0
- package/kits/cursor/.cursor/skills/skill-creator/SKILL.md +485 -0
- package/kits/cursor/.cursor/skills/skill-creator/agents/analyzer.md +274 -0
- package/kits/cursor/.cursor/skills/skill-creator/agents/comparator.md +202 -0
- package/kits/cursor/.cursor/skills/skill-creator/agents/grader.md +223 -0
- package/kits/cursor/.cursor/skills/skill-creator/assets/eval_review.html +146 -0
- package/kits/cursor/.cursor/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/kits/cursor/.cursor/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/kits/cursor/.cursor/skills/skill-creator/references/schemas.md +430 -0
- package/kits/cursor/.cursor/skills/skill-creator/scripts/__init__.py +0 -0
- package/kits/cursor/.cursor/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/kits/cursor/.cursor/skills/skill-creator/scripts/generate_report.py +326 -0
- package/kits/cursor/.cursor/skills/skill-creator/scripts/improve_description.py +247 -0
- package/kits/cursor/.cursor/skills/skill-creator/scripts/package_skill.py +136 -0
- package/kits/cursor/.cursor/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/kits/cursor/.cursor/skills/skill-creator/scripts/run_eval.py +310 -0
- package/kits/cursor/.cursor/skills/skill-creator/scripts/run_loop.py +328 -0
- package/kits/cursor/.cursor/skills/skill-creator/scripts/utils.py +47 -0
- package/kits/cursor/manifest.json +10 -0
- package/kits/github/.github/agents/code-pusher.agent.md +45 -0
- package/kits/github/.github/agents/feature-document-updater.agent.md +36 -0
- package/kits/github/.github/agents/self-reviewer.agent.md +31 -0
- package/kits/github/.github/agents/web-auto-agentic-workflow-initializer.agent.md +39 -0
- package/kits/github/.github/agents/web-auto-assisted-fix-and-runner.agent.md +35 -0
- package/kits/github/.github/agents/web-auto-chrome-devtools-selector-extractor.agent.md +33 -0
- package/kits/github/.github/agents/web-auto-coder.agent.md +32 -0
- package/kits/github/.github/agents/web-auto-fe-selector-extractor.agent.md +30 -0
- package/kits/github/.github/agents/web-auto-fix-and-runner.agent.md +34 -0
- package/kits/github/.github/agents/web-auto-lessons-learned-extractor.agent.md +33 -0
- package/kits/github/.github/agents/web-auto-playwright-mcp-selector-extractor.agent.md +34 -0
- package/kits/github/.github/agents/web-auto-source-instructions-updater.agent.md +42 -0
- package/kits/github/.github/agents/web-auto-test-cases-generator.agent.md +28 -0
- package/kits/github/.github/agents/web-auto-ticket-designer.agent.md +34 -0
- package/kits/github/.github/agents/web-auto-ticket-playbook-creator.agent.md +35 -0
- package/kits/github/.github/agents/web-auto.agent.md +382 -0
- package/kits/github/.github/skills/claude-code-subagent-creator/SKILL.md +310 -0
- package/kits/github/.github/skills/claude-code-subagent-creator/references/claude-code-subagent-configuration.md +158 -0
- package/kits/github/.github/skills/claude-code-subagent-creator/templates/subagent-profile.template.md +37 -0
- package/kits/github/.github/skills/skill-creator/LICENSE.txt +202 -0
- package/kits/github/.github/skills/skill-creator/SKILL.md +485 -0
- package/kits/github/.github/skills/skill-creator/agents/analyzer.md +274 -0
- package/kits/github/.github/skills/skill-creator/agents/comparator.md +202 -0
- package/kits/github/.github/skills/skill-creator/agents/grader.md +223 -0
- package/kits/github/.github/skills/skill-creator/assets/eval_review.html +146 -0
- package/kits/github/.github/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/kits/github/.github/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/kits/github/.github/skills/skill-creator/references/schemas.md +430 -0
- package/kits/github/.github/skills/skill-creator/scripts/__init__.py +0 -0
- package/kits/github/.github/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/kits/github/.github/skills/skill-creator/scripts/generate_report.py +326 -0
- package/kits/github/.github/skills/skill-creator/scripts/improve_description.py +247 -0
- package/kits/github/.github/skills/skill-creator/scripts/package_skill.py +136 -0
- package/kits/github/.github/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/kits/github/.github/skills/skill-creator/scripts/run_eval.py +310 -0
- package/kits/github/.github/skills/skill-creator/scripts/run_loop.py +328 -0
- package/kits/github/.github/skills/skill-creator/scripts/utils.py +47 -0
- package/kits/github/manifest.json +10 -0
- package/kits/shared/docs/ai-code-review.md +440 -0
- package/kits/shared/docs/increase-unit-test-coverage.md +77 -0
- package/kits/shared/docs/pr-review-agent.md +501 -0
- package/kits/shared/docs/self-review-agent.md +246 -0
- package/kits/shared/docs/web-auto-agentic-workflow.md +506 -0
- package/kits/shared/manifest.json +11 -0
- package/kits/shared/skills/fix-automation-tests/SKILL.md +280 -0
- package/kits/shared/skills/fix-automation-tests/scripts/fetch_pr_changes.py +300 -0
- package/kits/shared/skills/fix-automation-tests/templates/impact-report.template.md +42 -0
- package/kits/shared/skills/increase-unit-test-coverage/SKILL.md +117 -0
- package/kits/shared/skills/increase-unit-test-coverage/scripts/filter_low_coverage.py +447 -0
- package/kits/shared/skills/pr-review/SKILL.md +200 -0
- package/kits/shared/skills/pr-review/references/automation.md +62 -0
- package/kits/shared/skills/pr-review/references/backend.md +95 -0
- package/kits/shared/skills/pr-review/references/frontend.md +103 -0
- package/kits/shared/skills/pr-review/references/mobile.md +108 -0
- package/kits/shared/skills/pr-review/references/output-schema.md +130 -0
- package/kits/shared/skills/pr-review/scripts/post-review.py +1395 -0
- package/kits/shared/skills/push-code/SKILL.md +176 -0
- package/kits/shared/skills/self-review/SKILL.md +234 -0
- package/kits/shared/skills/self-review/evals/evals.json +23 -0
- package/kits/shared/skills/self-review/references/automation.md +62 -0
- package/kits/shared/skills/self-review/references/backend.md +95 -0
- package/kits/shared/skills/self-review/references/frontend.md +103 -0
- package/kits/shared/skills/self-review/references/mobile.md +108 -0
- package/kits/shared/skills/self-review/templates/issues.template.md +72 -0
- package/kits/shared/skills/update-feature-document/SKILL.md +156 -0
- package/kits/shared/skills/update-feature-document/templates/delta.template.yaml +58 -0
- package/kits/shared/skills/update-feature-document/templates/feature.template.md +25 -0
- package/kits/shared/skills/web-auto-assisted-fix-and-run/SKILL.md +130 -0
- package/kits/shared/skills/web-auto-assisted-fix-and-run/references/resolve-api-error.md +108 -0
- package/kits/shared/skills/web-auto-assisted-fix-and-run/references/resolve-selector.md +60 -0
- package/kits/shared/skills/web-auto-assisted-fix-and-run/templates/issues-resolution-report-append.template.md +54 -0
- package/kits/shared/skills/web-auto-chrome-devtools-mcp-extract-selectors/SKILL.md +284 -0
- package/kits/shared/skills/web-auto-coding/SKILL.md +152 -0
- package/kits/shared/skills/web-auto-extract-lessons-learned/SKILL.md +168 -0
- package/kits/shared/skills/web-auto-extract-lessons-learned/templates/lessons-learned.template.md +115 -0
- package/kits/shared/skills/web-auto-fe-extract-selectors/SKILL.md +282 -0
- package/kits/shared/skills/web-auto-fe-extract-selectors/evals/evals.json +23 -0
- package/kits/shared/skills/web-auto-fix-and-run-test/SKILL.md +183 -0
- package/kits/shared/skills/web-auto-fix-and-run-test/templates/issues-resolution-report.template.md +77 -0
- package/kits/shared/skills/web-auto-generate-best-practices/SKILL.md +123 -0
- package/kits/shared/skills/web-auto-generate-instructions/SKILL.md +200 -0
- package/kits/shared/skills/web-auto-generate-instructions/evals/evals.json +23 -0
- package/kits/shared/skills/web-auto-generate-instructions/references/analysis-guide.md +145 -0
- package/kits/shared/skills/web-auto-generate-instructions/templates/web-auto-instructions.template.md +184 -0
- package/kits/shared/skills/web-auto-generate-project-blueprint/SKILL.md +181 -0
- package/kits/shared/skills/web-auto-generate-project-blueprint/evals/evals.json +57 -0
- package/kits/shared/skills/web-auto-generate-project-blueprint/templates/web-auto-project-blueprint.template.md +161 -0
- package/kits/shared/skills/web-auto-playwright-mcp-extract-selectors/SKILL.md +293 -0
- package/kits/shared/skills/web-auto-test-cases/SKILL.md +138 -0
- package/kits/shared/skills/web-auto-test-cases/evals/evals.json +129 -0
- package/kits/shared/skills/web-auto-test-cases/templates/test-cases.template.md +53 -0
- package/kits/shared/skills/web-auto-ticket-design/SKILL.md +199 -0
- package/kits/shared/skills/web-auto-ticket-design/templates/ticket-design.template.md +138 -0
- package/kits/shared/skills/web-auto-ticket-playbook/SKILL.md +218 -0
- package/kits/shared/skills/web-auto-ticket-playbook/evals/evals.json +23 -0
- package/kits/shared/skills/web-auto-ticket-playbook/templates/ticket-playbook.template.md +148 -0
- package/kits/shared/skills/web-auto-update-source-instructions/SKILL.md +156 -0
- package/kits/shared/skills/web-auto-update-source-instructions/evals/evals.json +22 -0
- package/kits/shared/skills/workspace-ai-nav-creator/SKILL.md +168 -0
- package/kits/shared/skills/workspace-ai-nav-creator/templates/agents-md.template.md +112 -0
- package/kits/shared/skills/workspace-ai-nav-creator/templates/claude-md.template.md +86 -0
- package/package.json +16 -0
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: fix-automation-tests
|
|
3
|
+
description: Fix web automation test cases when frontend code changes in a PR. Analyzes FE code diff against the automation test codebase, generates an impact report of affected test cases, and fixes them after user confirmation. ALWAYS use this skill when the user mentions fixing, updating, or repairing automation tests due to FE/frontend changes, PR code changes, broken selectors, failing e2e tests after a deploy, or regression from a pull request. Triggers on patterns like "Fix the test cases for the FE code that changed in PR 42", "fix automation tests for PR #123", "update test cases for FE PR 15", "FE code changed in PR 8 fix the tests", "selectors changed and tests are broken", "e2e tests failing after frontend update", "tests broke after merging PR 10", or "update page objects for the new UI". Even if the user doesn't say "automation" explicitly — if they mention broken tests related to FE/UI changes, use this skill.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Fix Automation Tests
|
|
7
|
+
|
|
8
|
+
Analyze frontend code changes from a PR, identify affected web automation test cases, generate an impact report, and fix all affected tests after user confirmation.
|
|
9
|
+
|
|
10
|
+
**Why this skill exists:** Frontend PRs frequently break automation tests by changing selectors, restructuring pages, or altering user flows. Manually hunting down affected tests is tedious and error-prone. This skill systematically cross-references the FE diff against the test codebase so nothing gets missed, then applies targeted fixes that preserve test intent while adapting to the new UI.
|
|
11
|
+
|
|
12
|
+
## Input Parameters
|
|
13
|
+
|
|
14
|
+
| Parameter | Type | Required | Description |
|
|
15
|
+
|-----------|------|----------|-------------|
|
|
16
|
+
| `PR_NUMBER` | number | Yes | The PR number containing FE code changes |
|
|
17
|
+
|
|
18
|
+
## Workflow
|
|
19
|
+
|
|
20
|
+
### Step 1: Read Configuration
|
|
21
|
+
|
|
22
|
+
Read `.documents-design/project.config.json`. The fetch script needs this to know which platform/repo to pull the PR diff from.
|
|
23
|
+
|
|
24
|
+
**Required config fields:**
|
|
25
|
+
- `platform` - Git platform (`github`, `gitea`, `gitlab`, `bitbucket`)
|
|
26
|
+
- `platformConfig.{platform}.apiUrl` - API base URL
|
|
27
|
+
- `repos.webApp.{platform}` - FE repository connection details (structure varies by platform, see Configuration section)
|
|
28
|
+
|
|
29
|
+
**If config missing:** STOP, ask user to create `.documents-design/project.config.json`.
|
|
30
|
+
|
|
31
|
+
### Step 2: Fetch FE Code Changes
|
|
32
|
+
|
|
33
|
+
Run the fetch script to pull FE code changes and save to `fe-code-changed.txt`:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
python3 {SKILL_PATH}/scripts/fetch_pr_changes.py {PR_NUMBER}
|
|
37
|
+
|
|
38
|
+
# Or target a different repo
|
|
39
|
+
python3 {SKILL_PATH}/scripts/fetch_pr_changes.py {PR_NUMBER} --repo webApp
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
- `{SKILL_PATH}` is the absolute path to this skill's directory
|
|
43
|
+
- The script reads `platform`, `platformConfig`, and `repos` from `.documents-design/project.config.json` automatically
|
|
44
|
+
- Default repo: `webApp` (configurable via `--repo` flag)
|
|
45
|
+
|
|
46
|
+
**If script fails:** STOP, show error message to user.
|
|
47
|
+
|
|
48
|
+
**If script succeeds:** Confirm to user that FE changes were saved, showing line count.
|
|
49
|
+
|
|
50
|
+
### Step 3: Ask for PR Requirements
|
|
51
|
+
|
|
52
|
+
Context from the user dramatically improves analysis accuracy. A diff alone can't tell you *why* a page was restructured — but the user often knows the intent, which helps distinguish between "this selector moved" vs "this entire flow was replaced."
|
|
53
|
+
|
|
54
|
+
Ask the user:
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
FE code changes saved successfully.
|
|
58
|
+
|
|
59
|
+
Do you have any requirements or context for this PR? (optional - press Enter to skip)
|
|
60
|
+
Examples: "This PR redesigns the login page layout", "New checkout flow with 3 steps instead of 2"
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**If user provides requirements:** Save them to `pr-requirements.md` in the project root and confirm the file was saved.
|
|
64
|
+
|
|
65
|
+
**If user skips:** Proceed without creating the file.
|
|
66
|
+
|
|
67
|
+
### Step 4: Analyze Impact
|
|
68
|
+
|
|
69
|
+
This is the most critical analytical step. A thorough analysis here prevents missed breakages and false positives in the report. The goal is to build a clear mapping: for every meaningful FE change, find every test that touches it.
|
|
70
|
+
|
|
71
|
+
Read `fe-code-changed.txt` and `pr-requirements.md` (if exists), then work through these three phases:
|
|
72
|
+
|
|
73
|
+
#### Phase 1: Parse the FE diff
|
|
74
|
+
|
|
75
|
+
Extract a concrete list of what changed. Don't just skim — be specific:
|
|
76
|
+
- **Selector changes** — old vs new values for class names, IDs, `data-testid`, ARIA labels, `name` attributes
|
|
77
|
+
- **Removed elements** — elements that no longer exist in the DOM
|
|
78
|
+
- **Added elements** — new interactive or assertable elements
|
|
79
|
+
- **Flow changes** — navigation paths, form steps, modal triggers, redirect logic
|
|
80
|
+
- **Text/content changes** — button labels, headings, error messages, placeholder text
|
|
81
|
+
- **URL/route changes** — path changes, query param changes
|
|
82
|
+
- **Component restructuring** — elements moved in the DOM tree (affects ancestor-based selectors like XPath)
|
|
83
|
+
- **API endpoint changes** — if the diff touches API calls used in test data setup
|
|
84
|
+
|
|
85
|
+
#### Phase 2: Discover existing tests
|
|
86
|
+
|
|
87
|
+
Search the automation test codebase systematically. Start by identifying the test framework in use, then find all relevant files:
|
|
88
|
+
|
|
89
|
+
1. **Find test files** — search for patterns like `*.spec.ts`, `*.spec.js`, `*.test.ts`, `*.test.js`, `*Test.java`, `*.feature`, `*_test.py`
|
|
90
|
+
2. **Find Page Objects / page models** — these are the most common place where selectors live. Look for directories named `pages/`, `page-objects/`, `pageObjects/`, `models/`, or files matching `*Page.ts`, `*Page.js`, `*Page.java`
|
|
91
|
+
3. **Find shared utilities** — selector constants, helper functions, fixture files that might reference affected elements
|
|
92
|
+
|
|
93
|
+
Use grep/search to find references to the specific selectors, text values, and URLs identified in Phase 1. This is more reliable than reading every test file top-to-bottom.
|
|
94
|
+
|
|
95
|
+
#### Phase 3: Cross-reference
|
|
96
|
+
|
|
97
|
+
For each FE change from Phase 1, find every test artifact (test file, Page Object, helper) that references it. Build the impact mapping:
|
|
98
|
+
- Which Page Object fields use the changed selector?
|
|
99
|
+
- Which test cases call methods on those Page Objects?
|
|
100
|
+
- Which assertions check the changed text or URL?
|
|
101
|
+
- Which test flows navigate through the changed path?
|
|
102
|
+
|
|
103
|
+
**Important:** Follow the reference chain. A selector change in a Page Object affects every test that uses that Page Object method — even if the test file itself never mentions the selector directly. Think through the full dependency graph.
|
|
104
|
+
|
|
105
|
+
**Analysis checklist (verify each):**
|
|
106
|
+
- [ ] Selector changes (class names, IDs, data-testid attributes, ARIA labels)
|
|
107
|
+
- [ ] Element additions or removals
|
|
108
|
+
- [ ] Page flow/navigation changes
|
|
109
|
+
- [ ] Form field changes (added, removed, reordered)
|
|
110
|
+
- [ ] Text content changes used in assertions
|
|
111
|
+
- [ ] URL/route changes
|
|
112
|
+
- [ ] Component restructuring affecting DOM hierarchy
|
|
113
|
+
- [ ] API endpoint changes affecting test data setup
|
|
114
|
+
|
|
115
|
+
### Step 5: Generate Impact Report
|
|
116
|
+
|
|
117
|
+
Create `impact-report.md` in the project root using the template at [templates/impact-report.template.md](templates/impact-report.template.md).
|
|
118
|
+
|
|
119
|
+
The report must include:
|
|
120
|
+
1. **PR Information** - PR number, title, date, and user-provided requirements
|
|
121
|
+
2. **Summary** - Total affected test cases count and files count
|
|
122
|
+
3. **Affected Test Cases Table** - Every affected test case with file path, test name, brief cause, and fix type
|
|
123
|
+
4. **Detailed Analysis** - For each affected test case: the specific FE change that caused the impact and exactly what fix is needed
|
|
124
|
+
|
|
125
|
+
### Step 6: Present Report for Review
|
|
126
|
+
|
|
127
|
+
**If no test cases are affected:** Skip report generation, clean up temporary files (`fe-code-changed.txt`, `pr-requirements.md` if exists), and inform the user:
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
No affected test cases found. The FE changes in PR #{PR_NUMBER} do not impact any existing automation tests.
|
|
131
|
+
|
|
132
|
+
Cleaned up temporary files.
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
**If affected test cases are found:** Display the report summary in chat:
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
Impact Analysis Complete!
|
|
139
|
+
|
|
140
|
+
PR #{PR_NUMBER} affects {TOTAL_COUNT} test case(s) across {FILE_COUNT} file(s).
|
|
141
|
+
|
|
142
|
+
Affected Test Cases:
|
|
143
|
+
1. {FILE_PATH} > {TEST_CASE_NAME} - {BRIEF_CAUSE}
|
|
144
|
+
2. {FILE_PATH} > {TEST_CASE_NAME} - {BRIEF_CAUSE}
|
|
145
|
+
...
|
|
146
|
+
|
|
147
|
+
Full report saved to: impact-report.md
|
|
148
|
+
|
|
149
|
+
Please review the report. You can:
|
|
150
|
+
- Confirm it is correct, and I will fix all affected test cases
|
|
151
|
+
- Request corrections (e.g., "Test X is not affected", "You missed test Y")
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### Step 7: Handle User Feedback Loop
|
|
155
|
+
|
|
156
|
+
**If user requests corrections:**
|
|
157
|
+
1. Update `impact-report.md` with the corrections
|
|
158
|
+
2. Present the updated report summary again
|
|
159
|
+
3. Ask for confirmation again
|
|
160
|
+
4. Repeat until user confirms
|
|
161
|
+
|
|
162
|
+
**If user confirms the report is correct:** Proceed to Step 8.
|
|
163
|
+
|
|
164
|
+
### Step 8: Fix All Affected Test Cases
|
|
165
|
+
|
|
166
|
+
This is where every test gets fixed. The key principle: **fix at the source, not at every consumer**. If a selector changed, update it once in the Page Object — all tests using that PO method benefit automatically. Avoid duplicating fixes across test files when a single Page Object update solves it.
|
|
167
|
+
|
|
168
|
+
#### Fix order matters — group and batch
|
|
169
|
+
|
|
170
|
+
Don't fix test cases one by one in report order. Instead, group them by root cause for efficiency:
|
|
171
|
+
|
|
172
|
+
1. **Page Object fixes first** — Group all selector/element changes by Page Object. Fix each Page Object once. This automatically resolves every test case that depended on those selectors.
|
|
173
|
+
2. **Shared utilities next** — If helper functions, fixtures, or constants reference changed values, fix those next.
|
|
174
|
+
3. **Individual test files last** — Only now fix test-level changes: flow logic, assertions, added/removed steps. Many of these may already be resolved by the PO fixes above.
|
|
175
|
+
|
|
176
|
+
#### For each file, follow this process:
|
|
177
|
+
|
|
178
|
+
1. Read the full file and understand its structure before editing
|
|
179
|
+
2. Identify all changes needed in that file (there may be multiple from different impact items)
|
|
180
|
+
3. Apply all changes to the file at once — don't make multiple passes
|
|
181
|
+
4. Verify the edit is internally consistent (no broken references, no orphaned imports)
|
|
182
|
+
|
|
183
|
+
#### Fix patterns by type
|
|
184
|
+
|
|
185
|
+
**Selector Update** — Find the old selector value, replace with the new one. If the project uses a selector strategy (e.g., always `data-testid`), verify the new selector follows the same strategy.
|
|
186
|
+
|
|
187
|
+
**Flow Change** — Map old flow steps to new ones. If steps were reordered, reorder the test steps to match. If a step was split into multiple steps (e.g., one form became a multi-step wizard), expand the test accordingly. If steps were collapsed, consolidate.
|
|
188
|
+
|
|
189
|
+
**Assertion Update** — Update expected values to match the new UI. Be careful with partial matches (`toContain` vs `toBe`) — keep the same match strategy unless the change warrants otherwise.
|
|
190
|
+
|
|
191
|
+
**Element Removed** — Remove the corresponding test step and its assertions. Check if the removal breaks the test flow (e.g., removing a "Next" button click that was needed to advance). If so, replace with the new navigation path.
|
|
192
|
+
|
|
193
|
+
**Element Added** — Only add test steps for new elements if they are part of an existing test scenario's flow. Don't create entirely new test cases — that's out of scope for this skill.
|
|
194
|
+
|
|
195
|
+
**Page Restructure** — When the DOM hierarchy changed significantly, Page Object locators using ancestor-based strategies (XPath with parent paths, CSS with deep nesting) may all break. Rewrite the affected locators using the new structure. Prefer resilient selectors (`data-testid`, `role` + `name`) over brittle ones (deep CSS paths, positional XPath).
|
|
196
|
+
|
|
197
|
+
#### Fix guidelines
|
|
198
|
+
|
|
199
|
+
- **Preserve test intent** — only change what the FE diff requires. A working test that doesn't touch anything in the diff should never be modified.
|
|
200
|
+
- **Match existing conventions** — use the same selector strategy, assertion style, wait patterns, and naming conventions already in the codebase
|
|
201
|
+
- **Don't add waits/retries speculatively** — only add them if the FE change introduced async behavior where there was none before
|
|
202
|
+
- **Keep imports clean** — if you remove the last usage of an imported PO method or utility, remove the import too
|
|
203
|
+
|
|
204
|
+
### Step 9: Report Completion
|
|
205
|
+
|
|
206
|
+
After fixing all test cases, display the summary so the user can review:
|
|
207
|
+
|
|
208
|
+
```
|
|
209
|
+
All {TOTAL_COUNT} affected test case(s) have been fixed.
|
|
210
|
+
|
|
211
|
+
Fixed Files:
|
|
212
|
+
- {FILE_PATH_1} ({NUMBER_OF_CHANGES} changes)
|
|
213
|
+
- {FILE_PATH_2} ({NUMBER_OF_CHANGES} changes)
|
|
214
|
+
...
|
|
215
|
+
|
|
216
|
+
Temporary files kept for reference:
|
|
217
|
+
- fe-code-changed.txt (FE diff)
|
|
218
|
+
- pr-requirements.md (PR context, if created)
|
|
219
|
+
- impact-report.md (impact analysis)
|
|
220
|
+
|
|
221
|
+
Recommend running the test suite to verify all fixes.
|
|
222
|
+
Once you've confirmed the fixes work, I can clean up the temporary files.
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### Step 10: Cleanup (after user confirms fixes work)
|
|
226
|
+
|
|
227
|
+
Don't clean up automatically — the user may need to reference the diff or report while verifying fixes. Wait for the user to confirm the fixes are working, then remove:
|
|
228
|
+
|
|
229
|
+
1. Delete `fe-code-changed.txt`
|
|
230
|
+
2. Delete `pr-requirements.md` (if it exists)
|
|
231
|
+
3. Delete `impact-report.md`
|
|
232
|
+
|
|
233
|
+
If the user doesn't explicitly ask for cleanup, remind them once that temp files remain and can be cleaned up when ready.
|
|
234
|
+
|
|
235
|
+
## Configuration
|
|
236
|
+
|
|
237
|
+
Required in `.documents-design/project.config.json`. Add the FE repo under the `repos` map:
|
|
238
|
+
|
|
239
|
+
```json
|
|
240
|
+
{
|
|
241
|
+
"platform": "gitea",
|
|
242
|
+
"platformConfig": {
|
|
243
|
+
"gitea": { "apiUrl": "https://gitea.example.com/api/v1" }
|
|
244
|
+
},
|
|
245
|
+
"repos": {
|
|
246
|
+
"webApp": {
|
|
247
|
+
"gitea": { "owner": "your-org", "repo": "your-fe-repo" }
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### Repo Fields by Platform
|
|
254
|
+
|
|
255
|
+
| Platform | Fields | Description |
|
|
256
|
+
|----------|--------|-------------|
|
|
257
|
+
| **GitHub** | `owner`, `repo` | Repo owner and name |
|
|
258
|
+
| **Gitea** | `owner`, `repo` | Repo owner and name |
|
|
259
|
+
| **GitLab** | `projectId` | Project ID |
|
|
260
|
+
| **Bitbucket** | `workspace`, `repoSlug` | Workspace and repo slug |
|
|
261
|
+
|
|
262
|
+
### Platform Authentication
|
|
263
|
+
|
|
264
|
+
| Platform | Environment Variable |
|
|
265
|
+
|----------|---------------------|
|
|
266
|
+
| GitHub | `GITHUB_TOKEN` |
|
|
267
|
+
| Gitea | `GITEA_TOKEN` |
|
|
268
|
+
| GitLab | `GITLAB_TOKEN` |
|
|
269
|
+
| Bitbucket | `BITBUCKET_USERNAME` + `BITBUCKET_TOKEN` |
|
|
270
|
+
|
|
271
|
+
## Dependencies
|
|
272
|
+
|
|
273
|
+
- **Python 3.10+** - For running the fetch script (uses only stdlib, no pip dependencies)
|
|
274
|
+
|
|
275
|
+
## Resources
|
|
276
|
+
|
|
277
|
+
| Resource | Path | Purpose |
|
|
278
|
+
|----------|------|---------|
|
|
279
|
+
| Fetch script | `scripts/fetch_pr_changes.py` | Pull FE code changes from a PR |
|
|
280
|
+
| Report template | `templates/impact-report.template.md` | Impact report output format |
|
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Fetch FE code changes from a PR and save to fe-code-changed.txt.
|
|
3
|
+
|
|
4
|
+
Reads platform and repo config from .documents-design/project.config.json.
|
|
5
|
+
Resolves repo connection details from repos.{repoName}.{platform}.
|
|
6
|
+
Supports GitHub (gh CLI), Gitea, GitLab, and Bitbucket (REST API).
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import argparse
|
|
10
|
+
import base64
|
|
11
|
+
import json
|
|
12
|
+
import os
|
|
13
|
+
import ssl
|
|
14
|
+
|
|
15
|
+
import sys
|
|
16
|
+
import urllib.request
|
|
17
|
+
import urllib.error
|
|
18
|
+
from datetime import datetime
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
OUTPUT_FILE = "fe-code-changed.txt"
|
|
22
|
+
|
|
23
|
+
CONFIG_LOCATIONS = [".documents-design"]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def create_no_proxy_opener():
|
|
27
|
+
"""Create a URL opener that bypasses proxy settings with SSL verification disabled."""
|
|
28
|
+
ctx = ssl.create_default_context()
|
|
29
|
+
ctx.check_hostname = False
|
|
30
|
+
ctx.verify_mode = ssl.CERT_NONE
|
|
31
|
+
return urllib.request.build_opener(
|
|
32
|
+
urllib.request.ProxyHandler({}),
|
|
33
|
+
urllib.request.HTTPSHandler(context=ctx)
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def find_config() -> dict | None:
|
|
38
|
+
for directory in CONFIG_LOCATIONS:
|
|
39
|
+
path = Path(directory) / "project.config.json"
|
|
40
|
+
if path.exists():
|
|
41
|
+
with open(path) as f:
|
|
42
|
+
return json.load(f)
|
|
43
|
+
return None
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def fetch_github(pr_number: str, api_url: str, owner: str, repo: str, token: str | None) -> tuple[dict | None, str]:
|
|
47
|
+
"""Fetch PR data using GitHub REST API."""
|
|
48
|
+
headers = {"Accept": "application/vnd.github.v3.diff"}
|
|
49
|
+
if token:
|
|
50
|
+
headers["Authorization"] = f"token {token}"
|
|
51
|
+
opener = create_no_proxy_opener()
|
|
52
|
+
|
|
53
|
+
diff_url = f"{api_url}/repos/{owner}/{repo}/pulls/{pr_number}"
|
|
54
|
+
req = urllib.request.Request(diff_url, headers=headers)
|
|
55
|
+
try:
|
|
56
|
+
with opener.open(req, timeout=60) as resp:
|
|
57
|
+
diff = resp.read().decode("utf-8")
|
|
58
|
+
except urllib.error.HTTPError as e:
|
|
59
|
+
raise RuntimeError(f"GitHub API error ({e.code}): {e.reason} - {diff_url}")
|
|
60
|
+
|
|
61
|
+
metadata = None
|
|
62
|
+
meta_headers = {"Accept": "application/vnd.github+json"}
|
|
63
|
+
if token:
|
|
64
|
+
meta_headers["Authorization"] = f"token {token}"
|
|
65
|
+
req = urllib.request.Request(diff_url, headers=meta_headers)
|
|
66
|
+
try:
|
|
67
|
+
with opener.open(req, timeout=60) as resp:
|
|
68
|
+
raw = json.loads(resp.read().decode("utf-8"))
|
|
69
|
+
metadata = {
|
|
70
|
+
"title": raw.get("title", "N/A"),
|
|
71
|
+
"url": raw.get("html_url", "N/A"),
|
|
72
|
+
"headRefName": raw.get("head", {}).get("ref", "N/A"),
|
|
73
|
+
"baseRefName": raw.get("base", {}).get("ref", "N/A"),
|
|
74
|
+
}
|
|
75
|
+
except (urllib.error.HTTPError, json.JSONDecodeError):
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
return metadata, diff
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def fetch_gitea(pr_number: str, api_url: str, owner: str, repo: str, token: str | None) -> tuple[dict | None, str]:
|
|
82
|
+
"""Fetch PR data using Gitea REST API."""
|
|
83
|
+
headers = {}
|
|
84
|
+
if token:
|
|
85
|
+
headers["Authorization"] = f"token {token}"
|
|
86
|
+
opener = create_no_proxy_opener()
|
|
87
|
+
|
|
88
|
+
diff_url = f"{api_url}/repos/{owner}/{repo}/pulls/{pr_number}.diff"
|
|
89
|
+
req = urllib.request.Request(diff_url, headers=headers)
|
|
90
|
+
try:
|
|
91
|
+
with opener.open(req, timeout=60) as resp:
|
|
92
|
+
diff = resp.read().decode("utf-8")
|
|
93
|
+
except urllib.error.HTTPError as e:
|
|
94
|
+
raise RuntimeError(f"Gitea API error ({e.code}): {e.reason} - {diff_url}")
|
|
95
|
+
|
|
96
|
+
metadata = None
|
|
97
|
+
meta_url = f"{api_url}/repos/{owner}/{repo}/pulls/{pr_number}"
|
|
98
|
+
req = urllib.request.Request(meta_url, headers=headers)
|
|
99
|
+
try:
|
|
100
|
+
with opener.open(req, timeout=60) as resp:
|
|
101
|
+
raw = json.loads(resp.read().decode("utf-8"))
|
|
102
|
+
metadata = {
|
|
103
|
+
"title": raw.get("title", "N/A"),
|
|
104
|
+
"url": raw.get("html_url", raw.get("url", "N/A")),
|
|
105
|
+
"headRefName": raw.get("head", {}).get("ref", "N/A"),
|
|
106
|
+
"baseRefName": raw.get("base", {}).get("ref", "N/A"),
|
|
107
|
+
}
|
|
108
|
+
except (urllib.error.HTTPError, json.JSONDecodeError):
|
|
109
|
+
pass
|
|
110
|
+
|
|
111
|
+
return metadata, diff
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def fetch_gitlab(pr_number: str, api_url: str, project_id: str, token: str | None) -> tuple[dict | None, str]:
|
|
115
|
+
"""Fetch MR data using GitLab REST API."""
|
|
116
|
+
headers = {}
|
|
117
|
+
if token:
|
|
118
|
+
headers["PRIVATE-TOKEN"] = token
|
|
119
|
+
opener = create_no_proxy_opener()
|
|
120
|
+
|
|
121
|
+
diff_url = f"{api_url}/projects/{project_id}/merge_requests/{pr_number}/diffs"
|
|
122
|
+
req = urllib.request.Request(diff_url, headers=headers)
|
|
123
|
+
try:
|
|
124
|
+
with opener.open(req, timeout=60) as resp:
|
|
125
|
+
diffs_raw = json.loads(resp.read().decode("utf-8"))
|
|
126
|
+
diff_lines = []
|
|
127
|
+
for d in diffs_raw:
|
|
128
|
+
diff_lines.append(f"diff --git a/{d.get('old_path', '')} b/{d.get('new_path', '')}")
|
|
129
|
+
diff_lines.append(d.get("diff", ""))
|
|
130
|
+
diff = "\n".join(diff_lines)
|
|
131
|
+
except urllib.error.HTTPError as e:
|
|
132
|
+
raise RuntimeError(f"GitLab API error ({e.code}): {e.reason}")
|
|
133
|
+
|
|
134
|
+
metadata = None
|
|
135
|
+
meta_url = f"{api_url}/projects/{project_id}/merge_requests/{pr_number}"
|
|
136
|
+
req = urllib.request.Request(meta_url, headers=headers)
|
|
137
|
+
try:
|
|
138
|
+
with opener.open(req, timeout=60) as resp:
|
|
139
|
+
raw = json.loads(resp.read().decode("utf-8"))
|
|
140
|
+
metadata = {
|
|
141
|
+
"title": raw.get("title", "N/A"),
|
|
142
|
+
"url": raw.get("web_url", "N/A"),
|
|
143
|
+
"headRefName": raw.get("source_branch", "N/A"),
|
|
144
|
+
"baseRefName": raw.get("target_branch", "N/A"),
|
|
145
|
+
}
|
|
146
|
+
except (urllib.error.HTTPError, json.JSONDecodeError):
|
|
147
|
+
pass
|
|
148
|
+
|
|
149
|
+
return metadata, diff
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def fetch_bitbucket(pr_number: str, api_url: str, workspace: str, repo_slug: str,
|
|
153
|
+
username: str | None, token: str | None) -> tuple[dict | None, str]:
|
|
154
|
+
"""Fetch PR data using Bitbucket REST API."""
|
|
155
|
+
headers = {}
|
|
156
|
+
if username and token:
|
|
157
|
+
credentials = base64.b64encode(f"{username}:{token}".encode()).decode()
|
|
158
|
+
headers["Authorization"] = f"Basic {credentials}"
|
|
159
|
+
opener = create_no_proxy_opener()
|
|
160
|
+
|
|
161
|
+
diff_url = f"{api_url}/repositories/{workspace}/{repo_slug}/pullrequests/{pr_number}/diff"
|
|
162
|
+
req = urllib.request.Request(diff_url, headers=headers)
|
|
163
|
+
try:
|
|
164
|
+
with opener.open(req, timeout=60) as resp:
|
|
165
|
+
diff = resp.read().decode("utf-8")
|
|
166
|
+
except urllib.error.HTTPError as e:
|
|
167
|
+
raise RuntimeError(f"Bitbucket API error ({e.code}): {e.reason} - {diff_url}")
|
|
168
|
+
|
|
169
|
+
metadata = None
|
|
170
|
+
meta_url = f"{api_url}/repositories/{workspace}/{repo_slug}/pullrequests/{pr_number}"
|
|
171
|
+
req = urllib.request.Request(meta_url, headers=headers)
|
|
172
|
+
try:
|
|
173
|
+
with opener.open(req, timeout=60) as resp:
|
|
174
|
+
raw = json.loads(resp.read().decode("utf-8"))
|
|
175
|
+
source = raw.get("source", {}).get("branch", {})
|
|
176
|
+
dest = raw.get("destination", {}).get("branch", {})
|
|
177
|
+
metadata = {
|
|
178
|
+
"title": raw.get("title", "N/A"),
|
|
179
|
+
"url": raw.get("links", {}).get("html", {}).get("href", "N/A"),
|
|
180
|
+
"headRefName": source.get("name", "N/A"),
|
|
181
|
+
"baseRefName": dest.get("name", "N/A"),
|
|
182
|
+
}
|
|
183
|
+
except (urllib.error.HTTPError, json.JSONDecodeError):
|
|
184
|
+
pass
|
|
185
|
+
|
|
186
|
+
return metadata, diff
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
def write_output(pr_number: str, metadata: dict | None, diff: str):
|
|
190
|
+
with open(OUTPUT_FILE, "w") as f:
|
|
191
|
+
f.write("=" * 60 + "\n")
|
|
192
|
+
f.write(f"PR #{pr_number} - Code Changes\n")
|
|
193
|
+
f.write("=" * 60 + "\n")
|
|
194
|
+
|
|
195
|
+
if metadata:
|
|
196
|
+
f.write("\n--- PR Metadata ---\n")
|
|
197
|
+
f.write(f"Title: {metadata.get('title', 'N/A')}\n")
|
|
198
|
+
f.write(f"URL: {metadata.get('url', 'N/A')}\n")
|
|
199
|
+
f.write(f"Branch: {metadata.get('headRefName', 'N/A')} -> {metadata.get('baseRefName', 'N/A')}\n")
|
|
200
|
+
f.write(f"Fetched at: {datetime.now().isoformat()}\n")
|
|
201
|
+
files = metadata.get("files", [])
|
|
202
|
+
if files:
|
|
203
|
+
f.write(f"\nChanged files ({len(files)}):\n")
|
|
204
|
+
for file_info in files:
|
|
205
|
+
path = file_info.get("path", file_info) if isinstance(file_info, dict) else file_info
|
|
206
|
+
f.write(f" - {path}\n")
|
|
207
|
+
|
|
208
|
+
f.write("\n--- Diff ---\n")
|
|
209
|
+
f.write(diff)
|
|
210
|
+
|
|
211
|
+
with open(OUTPUT_FILE, "r") as f:
|
|
212
|
+
line_count = sum(1 for _ in f)
|
|
213
|
+
return line_count
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
def main():
|
|
217
|
+
parser = argparse.ArgumentParser(description="Fetch FE code changes from a PR")
|
|
218
|
+
parser.add_argument("pr_number", help="Pull request number")
|
|
219
|
+
parser.add_argument("--repo", "-r", default="webApp",
|
|
220
|
+
help="Repo name from repos map in project.config.json (default: webApp)")
|
|
221
|
+
args = parser.parse_args()
|
|
222
|
+
|
|
223
|
+
config = find_config()
|
|
224
|
+
if not config:
|
|
225
|
+
print("Error: project.config.json not found in .documents-design/", file=sys.stderr)
|
|
226
|
+
sys.exit(1)
|
|
227
|
+
|
|
228
|
+
platform = config.get("platform", "github")
|
|
229
|
+
platform_cfg = config.get("platformConfig", {}).get(platform, {})
|
|
230
|
+
|
|
231
|
+
if not platform_cfg:
|
|
232
|
+
print(f"Error: 'platformConfig.{platform}' is not configured in project.config.json", file=sys.stderr)
|
|
233
|
+
sys.exit(1)
|
|
234
|
+
|
|
235
|
+
repo_config = config.get("repos", {}).get(args.repo, {}).get(platform, {})
|
|
236
|
+
if not repo_config:
|
|
237
|
+
print(f"Error: 'repos.{args.repo}.{platform}' is not configured in project.config.json", file=sys.stderr)
|
|
238
|
+
sys.exit(1)
|
|
239
|
+
|
|
240
|
+
api_url = platform_cfg.get("apiUrl", "")
|
|
241
|
+
|
|
242
|
+
try:
|
|
243
|
+
if platform == "github":
|
|
244
|
+
owner = repo_config.get("owner", "")
|
|
245
|
+
repo = repo_config.get("repo", "")
|
|
246
|
+
if not api_url or not owner or not repo:
|
|
247
|
+
print(f"Error: 'platformConfig.github.apiUrl' and 'repos.{args.repo}.github.owner/repo' are required", file=sys.stderr)
|
|
248
|
+
sys.exit(1)
|
|
249
|
+
token = os.environ.get("GITHUB_TOKEN")
|
|
250
|
+
print(f"Fetching PR #{args.pr_number} from GitHub ({owner}/{repo})...")
|
|
251
|
+
metadata, diff = fetch_github(args.pr_number, api_url, owner, repo, token)
|
|
252
|
+
|
|
253
|
+
elif platform == "gitea":
|
|
254
|
+
owner = repo_config.get("owner", "")
|
|
255
|
+
repo = repo_config.get("repo", "")
|
|
256
|
+
if not api_url or not owner or not repo:
|
|
257
|
+
print(f"Error: 'platformConfig.gitea.apiUrl' and 'repos.{args.repo}.gitea.owner/repo' are required", file=sys.stderr)
|
|
258
|
+
sys.exit(1)
|
|
259
|
+
token = os.environ.get("GITEA_TOKEN")
|
|
260
|
+
print(f"Fetching PR #{args.pr_number} from Gitea ({owner}/{repo})...")
|
|
261
|
+
metadata, diff = fetch_gitea(args.pr_number, api_url, owner, repo, token)
|
|
262
|
+
|
|
263
|
+
elif platform == "gitlab":
|
|
264
|
+
project_id = repo_config.get("projectId", "")
|
|
265
|
+
if not api_url or not project_id:
|
|
266
|
+
print(f"Error: 'platformConfig.gitlab.apiUrl' and 'repos.{args.repo}.gitlab.projectId' are required", file=sys.stderr)
|
|
267
|
+
sys.exit(1)
|
|
268
|
+
token = os.environ.get("GITLAB_TOKEN")
|
|
269
|
+
print(f"Fetching MR #{args.pr_number} from GitLab (project {project_id})...")
|
|
270
|
+
metadata, diff = fetch_gitlab(args.pr_number, api_url, project_id, token)
|
|
271
|
+
|
|
272
|
+
elif platform == "bitbucket":
|
|
273
|
+
workspace = repo_config.get("workspace", "")
|
|
274
|
+
repo_slug = repo_config.get("repoSlug", "")
|
|
275
|
+
if not api_url or not workspace or not repo_slug:
|
|
276
|
+
print(f"Error: 'platformConfig.bitbucket.apiUrl' and 'repos.{args.repo}.bitbucket.workspace/repoSlug' are required", file=sys.stderr)
|
|
277
|
+
sys.exit(1)
|
|
278
|
+
username = os.environ.get("BITBUCKET_USERNAME")
|
|
279
|
+
token = os.environ.get("BITBUCKET_TOKEN")
|
|
280
|
+
print(f"Fetching PR #{args.pr_number} from Bitbucket ({workspace}/{repo_slug})...")
|
|
281
|
+
metadata, diff = fetch_bitbucket(args.pr_number, api_url, workspace, repo_slug, username, token)
|
|
282
|
+
|
|
283
|
+
else:
|
|
284
|
+
print(f"Error: Unsupported platform '{platform}'", file=sys.stderr)
|
|
285
|
+
sys.exit(1)
|
|
286
|
+
|
|
287
|
+
except RuntimeError as e:
|
|
288
|
+
print(f"Error: {e}", file=sys.stderr)
|
|
289
|
+
sys.exit(1)
|
|
290
|
+
|
|
291
|
+
if not diff.strip():
|
|
292
|
+
print(f"Error: PR #{args.pr_number} has no code changes", file=sys.stderr)
|
|
293
|
+
sys.exit(1)
|
|
294
|
+
|
|
295
|
+
line_count = write_output(args.pr_number, metadata, diff)
|
|
296
|
+
print(f"Saved PR #{args.pr_number} changes to {OUTPUT_FILE} ({line_count} lines)")
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
if __name__ == "__main__":
|
|
300
|
+
main()
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Impact Analysis Report
|
|
2
|
+
|
|
3
|
+
## PR Information
|
|
4
|
+
|
|
5
|
+
| Field | Value |
|
|
6
|
+
|-------|-------|
|
|
7
|
+
| **PR Number** | #{PR_NUMBER} |
|
|
8
|
+
| **PR Title** | {PR_TITLE} |
|
|
9
|
+
| **Analysis Date** | {DATE} |
|
|
10
|
+
| **Requirements** | {REQUIREMENTS or "Not provided"} |
|
|
11
|
+
|
|
12
|
+
## Summary
|
|
13
|
+
|
|
14
|
+
- **Total Affected Test Cases:** {TOTAL_COUNT}
|
|
15
|
+
- **Test Files Affected:** {FILE_COUNT}
|
|
16
|
+
|
|
17
|
+
## Affected Test Cases
|
|
18
|
+
|
|
19
|
+
| # | Test File | Test Case | Cause | Fix Type |
|
|
20
|
+
|---|-----------|-----------|-------|----------|
|
|
21
|
+
| {N} | `{FILE_PATH}` | {TEST_CASE_NAME} | {BRIEF_CAUSE_DESCRIPTION} | {FIX_TYPE} |
|
|
22
|
+
|
|
23
|
+
### Fix Types Legend
|
|
24
|
+
|
|
25
|
+
| Type | Description |
|
|
26
|
+
|------|-------------|
|
|
27
|
+
| **Selector Update** | Element selectors changed (class, id, data-testid, etc.) |
|
|
28
|
+
| **Flow Change** | User interaction flow or page navigation changed |
|
|
29
|
+
| **Assertion Update** | Expected values or validation logic changed |
|
|
30
|
+
| **Element Removed** | UI element removed, test step needs removal or replacement |
|
|
31
|
+
| **Element Added** | New UI element added, test needs additional steps |
|
|
32
|
+
| **Page Restructure** | Page layout significantly changed, Page Object needs rewrite |
|
|
33
|
+
| **API Change** | Backend API contract changed affecting test data setup |
|
|
34
|
+
|
|
35
|
+
## Detailed Analysis
|
|
36
|
+
|
|
37
|
+
### {N}. {TEST_FILE_PATH}
|
|
38
|
+
|
|
39
|
+
**Test Case:** `{TEST_CASE_NAME}`
|
|
40
|
+
**Cause:** {DETAILED_DESCRIPTION_OF_WHY_THIS_TEST_IS_AFFECTED}
|
|
41
|
+
**FE Change:** {SPECIFIC_FE_CODE_CHANGE_THAT_CAUSED_THE_IMPACT}
|
|
42
|
+
**Fix Required:** {DESCRIPTION_OF_WHAT_NEEDS_TO_CHANGE_IN_THE_TEST}
|