synapse-hub 2.4.1 → 2.4.3

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 (77) hide show
  1. package/.agents/rules/graphify.md +14 -14
  2. package/.agents/rules/mandatory-playwright-live.md +29 -29
  3. package/.agents/skills/bats-testing-patterns/resources/implementation-playbook.md +614 -614
  4. package/.agents/skills/clean-pom-crafter/examples/standard_test_case.groovy +28 -28
  5. package/.agents/skills/clean-pom-crafter/references/pom_patterns.groovy +138 -138
  6. package/.agents/skills/e2e-testing-patterns/resources/implementation-playbook.md +522 -522
  7. package/.agents/skills/failure-autopsy-and-healing/references/healing_matrix.md +64 -64
  8. package/.agents/skills/failure-autopsy-and-healing/references/qa_investigation_protocol.md +56 -56
  9. package/.agents/skills/failure-autopsy-and-healing/scripts/triage_failures.sh +98 -98
  10. package/.agents/skills/katalon-cli-runner/references/groovy-patterns.md +209 -209
  11. package/.agents/skills/katalon-cli-runner/references/katalon-api.md +155 -155
  12. package/.agents/skills/katalon-cli-runner/references/runner_commands.md +67 -67
  13. package/.agents/skills/playwright-live-interaction/references/advanced_superpowers.md +160 -160
  14. package/.agents/skills/playwright-live-interaction/references/compact_accessibility_snapshots.md +75 -75
  15. package/.agents/skills/playwright-live-interaction/references/recipes.md +388 -388
  16. package/.agents/skills/playwright-live-interaction/references/swarm_orchestration.md +134 -134
  17. package/.agents/skills/wcag-audit-patterns/resources/implementation-playbook.md +541 -541
  18. package/.agents/templates/completion_report.md +57 -57
  19. package/.agents/workflows/graphify.md +10 -10
  20. package/.cursor/rules/language.mdc +7 -7
  21. package/README.en.md +1 -1
  22. package/README.md +1 -1
  23. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-06_api_contract_drift.json +21 -21
  24. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-07_api_contract_drift.json +21 -21
  25. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-08_api_contract_drift.json +21 -21
  26. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-09_api_contract_drift.json +21 -21
  27. package/benchmarks/qa_eval/dataset/api_contract_drift/qa-challenge-10_api_contract_drift.json +21 -21
  28. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-21_fake_pass_tautology.json +20 -20
  29. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-22_fake_pass_tautology.json +20 -20
  30. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-23_fake_pass_tautology.json +20 -20
  31. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-24_fake_pass_tautology.json +20 -20
  32. package/benchmarks/qa_eval/dataset/fake_pass_tautology/qa-challenge-25_fake_pass_tautology.json +20 -20
  33. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-01_locator_drift.json +22 -22
  34. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-02_locator_drift.json +22 -22
  35. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-03_locator_drift.json +22 -22
  36. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-04_locator_drift.json +22 -22
  37. package/benchmarks/qa_eval/dataset/locator_drift/qa-challenge-05_locator_drift.json +22 -22
  38. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-16_stale_and_mutation.json +21 -21
  39. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-17_stale_and_mutation.json +21 -21
  40. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-18_stale_and_mutation.json +21 -21
  41. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-19_stale_and_mutation.json +21 -21
  42. package/benchmarks/qa_eval/dataset/stale_and_mutation/qa-challenge-20_stale_and_mutation.json +22 -22
  43. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-11_timing_and_race.json +21 -21
  44. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-12_timing_and_race.json +21 -21
  45. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-13_timing_and_race.json +21 -21
  46. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-14_timing_and_race.json +21 -21
  47. package/benchmarks/qa_eval/dataset/timing_and_race/qa-challenge-15_timing_and_race.json +21 -21
  48. package/bin/agent-qa.js +0 -0
  49. package/docs/ARCHITECTURE.md +12 -1
  50. package/package.json +1 -1
  51. package/scripts/install.ps1 +112 -112
  52. package/scripts/lint_skills.ps1 +57 -57
  53. package/skills_manifest.json +1 -1
  54. package/synapse.config.json +1 -1
  55. package/tools/__init__.py +1 -1
  56. package/tools/agent_canary.py +501 -501
  57. package/tools/api_fuzzer.py +11 -2
  58. package/tools/browser_helpers.js +2 -2
  59. package/tools/bump_version.py +1 -0
  60. package/tools/check_env.py +71 -13
  61. package/tools/cli.py +2 -2
  62. package/tools/dashboard_generator.py +2 -2
  63. package/tools/e2e_flow_prober.sh +0 -0
  64. package/tools/generate_allure_report.sh +0 -0
  65. package/tools/generate_test_reports.sh +0 -0
  66. package/tools/mcp_excel_server.py +3 -1
  67. package/tools/mcp_excel_server.sh +0 -0
  68. package/tools/mcp_server.py +1 -1
  69. package/tools/pinpoint_failure.py +88 -88
  70. package/tools/setup_project.py +8 -0
  71. package/tools/update_sentinel.py +10 -9
  72. package/tools/verify_all.sh +0 -0
  73. package/tools/visual_som_helper.py +14 -3
  74. package/tools/welcome_page.py +1 -1
  75. package/benchmarks/qa_eval/reports/AB_METHODOLOGY_REPORT.md +0 -83
  76. package/benchmarks/qa_eval/reports/BENCHMARK_REPORT.md +0 -69
  77. package/benchmarks/qa_eval/reports/eval_results.json +0 -105
@@ -1,209 +1,209 @@
1
- # Groovy Patterns for Katalon Studio
2
-
3
- This document provides common Groovy patterns and best practices for Katalon Studio custom keywords and test scripts.
4
-
5
- ## Custom Keyword Structure
6
-
7
- ### Basic Custom Keyword Class
8
-
9
- ```groovy
10
- package com.enterprise.keywords
11
-
12
- import com.kms.katalon.core.annotation.Keyword
13
- import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
14
- import internal.GlobalVariable
15
-
16
- class LoginKeywords {
17
-
18
- @Keyword
19
- def login(String username, String password) {
20
- WebUI.setText(findTestObject('Page_Login/input_Username'), username)
21
- WebUI.setEncryptedText(findTestObject('Page_Login/input_Password'), password)
22
- WebUI.click(findTestObject('Page_Login/btn_Login'))
23
- WebUI.waitForPageLoad(GlobalVariable.timeout)
24
- }
25
-
26
- @Keyword
27
- def loginWithGlobalVariables() {
28
- login(GlobalVariable.username, GlobalVariable.password)
29
- }
30
-
31
- @Keyword
32
- def verifyLoginSuccess() {
33
- WebUI.verifyElementPresent(findTestObject('Page_Dashboard/header_Welcome'),
34
- GlobalVariable.timeout)
35
- }
36
- }
37
- ```
38
-
39
- ### Static Keywords
40
-
41
- When keywords don't need instance state, make them static:
42
-
43
- ```groovy
44
- package com.enterprise.utils
45
-
46
- import com.kms.katalon.core.annotation.Keyword
47
- import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
48
-
49
- class NavigationUtils {
50
-
51
- @Keyword
52
- static def navigateToPage(String pageName) {
53
- String url = "${GlobalVariable.baseUrl}/${pageName}"
54
- WebUI.navigateToUrl(url)
55
- }
56
-
57
- @Keyword
58
- static def refreshUntilElementVisible(TestObject element, int maxAttempts = 5) {
59
- int attempts = 0
60
- while (attempts < maxAttempts) {
61
- if (WebUI.verifyElementVisible(element, FailureHandling.OPTIONAL)) {
62
- return true
63
- }
64
- WebUI.refresh()
65
- attempts++
66
- }
67
- return false
68
- }
69
- }
70
- ```
71
-
72
- ## Common Patterns
73
-
74
- ### Wait and Retry Pattern
75
-
76
- ```groovy
77
- @Keyword
78
- def waitAndRetry(TestObject element, int maxAttempts = 3, int delaySeconds = 2) {
79
- for (int i = 0; i < maxAttempts; i++) {
80
- try {
81
- WebUI.waitForElementPresent(element, delaySeconds)
82
- return true
83
- } catch (Exception e) {
84
- if (i == maxAttempts - 1) {
85
- throw e
86
- }
87
- WebUI.delay(delaySeconds)
88
- }
89
- }
90
- return false
91
- }
92
- ```
93
-
94
- ### Conditional Element Interaction
95
-
96
- ```groovy
97
- @Keyword
98
- def clickIfPresent(TestObject element, int timeout = 5) {
99
- if (WebUI.verifyElementPresent(element, timeout, FailureHandling.OPTIONAL)) {
100
- WebUI.click(element)
101
- return true
102
- }
103
- return false
104
- }
105
-
106
- @Keyword
107
- def closePopupIfExists(TestObject closeButton) {
108
- if (WebUI.verifyElementVisible(closeButton, FailureHandling.OPTIONAL)) {
109
- WebUI.click(closeButton)
110
- WebUI.delay(1)
111
- }
112
- }
113
- ```
114
-
115
- ### Dynamic Object Creation
116
-
117
- ```groovy
118
- @Keyword
119
- def clickDynamicElement(String xpath) {
120
- TestObject dynamicObject = new TestObject()
121
- dynamicObject.addProperty('xpath', ConditionType.EQUALS, xpath)
122
- WebUI.click(dynamicObject)
123
- }
124
-
125
- @Keyword
126
- def findElementByText(String tagName, String text) {
127
- String xpath = "//${tagName}[contains(text(), '${text}')]"
128
- TestObject element = new TestObject()
129
- element.addProperty('xpath', ConditionType.EQUALS, xpath)
130
- return element
131
- }
132
- ```
133
-
134
- ### Data-Driven Helpers
135
-
136
- ```groovy
137
- @Keyword
138
- def executeWithTestData(String testDataName, Closure action) {
139
- TestData data = findTestData(testDataName)
140
- int rowCount = data.getRowNumbers()
141
-
142
- for (int i = 1; i <= rowCount; i++) {
143
- def row = [:]
144
- data.getColumnNames().each { col ->
145
- row[col] = data.getValue(col, i)
146
- }
147
- action(row)
148
- }
149
- }
150
- ```
151
-
152
- ### Page Object Pattern
153
-
154
- ```groovy
155
- package com.enterprise.pages
156
-
157
- import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
158
- import internal.GlobalVariable
159
-
160
- class LoginPage {
161
-
162
- def open() {
163
- WebUI.navigateToUrl(GlobalVariable.loginUrl)
164
- return this
165
- }
166
-
167
- def login(String username, String password) {
168
- // Implementation
169
- }
170
- }
171
- ```
172
-
173
- ### Error Handling and Logging
174
-
175
- ```groovy
176
- import com.kms.katalon.core.util.KeywordUtil
177
-
178
- @Keyword
179
- def performActionWithErrorHandling(Closure action) {
180
- try {
181
- action()
182
- KeywordUtil.markPassed("Action completed successfully")
183
- } catch (Exception e) {
184
- KeywordUtil.logInfo("Error occurred: ${e.message}")
185
- WebUI.takeScreenshot()
186
- KeywordUtil.markFailed("Action failed: ${e.message}")
187
- throw e
188
- }
189
- }
190
-
191
- @Keyword
192
- def safeClick(TestObject element, String elementName = "Element") {
193
- try {
194
- WebUI.waitForElementClickable(element, 10)
195
- WebUI.click(element)
196
- KeywordUtil.logInfo("Clicked on ${elementName}")
197
- } catch (Exception e) {
198
- KeywordUtil.markWarning("Could not click ${elementName}: ${e.message}")
199
- WebUI.takeScreenshot()
200
- }
201
- }
202
- ```
203
-
204
- ### Best Practices
205
-
206
- 1. **Use Descriptive Names**: Use clear, readable keyword names.
207
- 2. **Handle Timeouts Gracefully**: Always set explicit wait timeouts rather than hard sleeps.
208
- 3. **Parameterize Magic Numbers**: Define constants for retries and timeouts.
209
- 4. **Failure Handling**: Use `FailureHandling.STOP_ON_FAILURE` for critical steps, `OPTIONAL` for transient dialogs.
1
+ # Groovy Patterns for Katalon Studio
2
+
3
+ This document provides common Groovy patterns and best practices for Katalon Studio custom keywords and test scripts.
4
+
5
+ ## Custom Keyword Structure
6
+
7
+ ### Basic Custom Keyword Class
8
+
9
+ ```groovy
10
+ package com.enterprise.keywords
11
+
12
+ import com.kms.katalon.core.annotation.Keyword
13
+ import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
14
+ import internal.GlobalVariable
15
+
16
+ class LoginKeywords {
17
+
18
+ @Keyword
19
+ def login(String username, String password) {
20
+ WebUI.setText(findTestObject('Page_Login/input_Username'), username)
21
+ WebUI.setEncryptedText(findTestObject('Page_Login/input_Password'), password)
22
+ WebUI.click(findTestObject('Page_Login/btn_Login'))
23
+ WebUI.waitForPageLoad(GlobalVariable.timeout)
24
+ }
25
+
26
+ @Keyword
27
+ def loginWithGlobalVariables() {
28
+ login(GlobalVariable.username, GlobalVariable.password)
29
+ }
30
+
31
+ @Keyword
32
+ def verifyLoginSuccess() {
33
+ WebUI.verifyElementPresent(findTestObject('Page_Dashboard/header_Welcome'),
34
+ GlobalVariable.timeout)
35
+ }
36
+ }
37
+ ```
38
+
39
+ ### Static Keywords
40
+
41
+ When keywords don't need instance state, make them static:
42
+
43
+ ```groovy
44
+ package com.enterprise.utils
45
+
46
+ import com.kms.katalon.core.annotation.Keyword
47
+ import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
48
+
49
+ class NavigationUtils {
50
+
51
+ @Keyword
52
+ static def navigateToPage(String pageName) {
53
+ String url = "${GlobalVariable.baseUrl}/${pageName}"
54
+ WebUI.navigateToUrl(url)
55
+ }
56
+
57
+ @Keyword
58
+ static def refreshUntilElementVisible(TestObject element, int maxAttempts = 5) {
59
+ int attempts = 0
60
+ while (attempts < maxAttempts) {
61
+ if (WebUI.verifyElementVisible(element, FailureHandling.OPTIONAL)) {
62
+ return true
63
+ }
64
+ WebUI.refresh()
65
+ attempts++
66
+ }
67
+ return false
68
+ }
69
+ }
70
+ ```
71
+
72
+ ## Common Patterns
73
+
74
+ ### Wait and Retry Pattern
75
+
76
+ ```groovy
77
+ @Keyword
78
+ def waitAndRetry(TestObject element, int maxAttempts = 3, int delaySeconds = 2) {
79
+ for (int i = 0; i < maxAttempts; i++) {
80
+ try {
81
+ WebUI.waitForElementPresent(element, delaySeconds)
82
+ return true
83
+ } catch (Exception e) {
84
+ if (i == maxAttempts - 1) {
85
+ throw e
86
+ }
87
+ WebUI.delay(delaySeconds)
88
+ }
89
+ }
90
+ return false
91
+ }
92
+ ```
93
+
94
+ ### Conditional Element Interaction
95
+
96
+ ```groovy
97
+ @Keyword
98
+ def clickIfPresent(TestObject element, int timeout = 5) {
99
+ if (WebUI.verifyElementPresent(element, timeout, FailureHandling.OPTIONAL)) {
100
+ WebUI.click(element)
101
+ return true
102
+ }
103
+ return false
104
+ }
105
+
106
+ @Keyword
107
+ def closePopupIfExists(TestObject closeButton) {
108
+ if (WebUI.verifyElementVisible(closeButton, FailureHandling.OPTIONAL)) {
109
+ WebUI.click(closeButton)
110
+ WebUI.delay(1)
111
+ }
112
+ }
113
+ ```
114
+
115
+ ### Dynamic Object Creation
116
+
117
+ ```groovy
118
+ @Keyword
119
+ def clickDynamicElement(String xpath) {
120
+ TestObject dynamicObject = new TestObject()
121
+ dynamicObject.addProperty('xpath', ConditionType.EQUALS, xpath)
122
+ WebUI.click(dynamicObject)
123
+ }
124
+
125
+ @Keyword
126
+ def findElementByText(String tagName, String text) {
127
+ String xpath = "//${tagName}[contains(text(), '${text}')]"
128
+ TestObject element = new TestObject()
129
+ element.addProperty('xpath', ConditionType.EQUALS, xpath)
130
+ return element
131
+ }
132
+ ```
133
+
134
+ ### Data-Driven Helpers
135
+
136
+ ```groovy
137
+ @Keyword
138
+ def executeWithTestData(String testDataName, Closure action) {
139
+ TestData data = findTestData(testDataName)
140
+ int rowCount = data.getRowNumbers()
141
+
142
+ for (int i = 1; i <= rowCount; i++) {
143
+ def row = [:]
144
+ data.getColumnNames().each { col ->
145
+ row[col] = data.getValue(col, i)
146
+ }
147
+ action(row)
148
+ }
149
+ }
150
+ ```
151
+
152
+ ### Page Object Pattern
153
+
154
+ ```groovy
155
+ package com.enterprise.pages
156
+
157
+ import com.kms.katalon.core.webui.keyword.WebUiBuiltInKeywords as WebUI
158
+ import internal.GlobalVariable
159
+
160
+ class LoginPage {
161
+
162
+ def open() {
163
+ WebUI.navigateToUrl(GlobalVariable.loginUrl)
164
+ return this
165
+ }
166
+
167
+ def login(String username, String password) {
168
+ // Implementation
169
+ }
170
+ }
171
+ ```
172
+
173
+ ### Error Handling and Logging
174
+
175
+ ```groovy
176
+ import com.kms.katalon.core.util.KeywordUtil
177
+
178
+ @Keyword
179
+ def performActionWithErrorHandling(Closure action) {
180
+ try {
181
+ action()
182
+ KeywordUtil.markPassed("Action completed successfully")
183
+ } catch (Exception e) {
184
+ KeywordUtil.logInfo("Error occurred: ${e.message}")
185
+ WebUI.takeScreenshot()
186
+ KeywordUtil.markFailed("Action failed: ${e.message}")
187
+ throw e
188
+ }
189
+ }
190
+
191
+ @Keyword
192
+ def safeClick(TestObject element, String elementName = "Element") {
193
+ try {
194
+ WebUI.waitForElementClickable(element, 10)
195
+ WebUI.click(element)
196
+ KeywordUtil.logInfo("Clicked on ${elementName}")
197
+ } catch (Exception e) {
198
+ KeywordUtil.markWarning("Could not click ${elementName}: ${e.message}")
199
+ WebUI.takeScreenshot()
200
+ }
201
+ }
202
+ ```
203
+
204
+ ### Best Practices
205
+
206
+ 1. **Use Descriptive Names**: Use clear, readable keyword names.
207
+ 2. **Handle Timeouts Gracefully**: Always set explicit wait timeouts rather than hard sleeps.
208
+ 3. **Parameterize Magic Numbers**: Define constants for retries and timeouts.
209
+ 4. **Failure Handling**: Use `FailureHandling.STOP_ON_FAILURE` for critical steps, `OPTIONAL` for transient dialogs.