agentic-qe 2.5.6 → 2.5.8

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 (210) hide show
  1. package/.claude/agents/n8n/n8n-base-agent.md +376 -0
  2. package/.claude/agents/n8n/n8n-bdd-scenario-tester.md +613 -0
  3. package/.claude/agents/n8n/n8n-chaos-tester.md +654 -0
  4. package/.claude/agents/n8n/n8n-ci-orchestrator.md +850 -0
  5. package/.claude/agents/n8n/n8n-compliance-validator.md +685 -0
  6. package/.claude/agents/n8n/n8n-expression-validator.md +560 -0
  7. package/.claude/agents/n8n/n8n-integration-test.md +602 -0
  8. package/.claude/agents/n8n/n8n-monitoring-validator.md +589 -0
  9. package/.claude/agents/n8n/n8n-node-validator.md +455 -0
  10. package/.claude/agents/n8n/n8n-performance-tester.md +630 -0
  11. package/.claude/agents/n8n/n8n-security-auditor.md +786 -0
  12. package/.claude/agents/n8n/n8n-trigger-test.md +500 -0
  13. package/.claude/agents/n8n/n8n-unit-tester.md +633 -0
  14. package/.claude/agents/n8n/n8n-version-comparator.md +567 -0
  15. package/.claude/agents/n8n/n8n-workflow-executor.md +392 -0
  16. package/.claude/skills/n8n-expression-testing/SKILL.md +434 -0
  17. package/.claude/skills/n8n-integration-testing-patterns/SKILL.md +540 -0
  18. package/.claude/skills/n8n-security-testing/SKILL.md +599 -0
  19. package/.claude/skills/n8n-trigger-testing-strategies/SKILL.md +541 -0
  20. package/.claude/skills/n8n-workflow-testing-fundamentals/SKILL.md +447 -0
  21. package/CHANGELOG.md +127 -0
  22. package/README.md +7 -4
  23. package/dist/agents/BaseAgent.d.ts +142 -0
  24. package/dist/agents/BaseAgent.d.ts.map +1 -1
  25. package/dist/agents/BaseAgent.js +372 -2
  26. package/dist/agents/BaseAgent.js.map +1 -1
  27. package/dist/agents/TestGeneratorAgent.d.ts +5 -0
  28. package/dist/agents/TestGeneratorAgent.d.ts.map +1 -1
  29. package/dist/agents/TestGeneratorAgent.js +38 -0
  30. package/dist/agents/TestGeneratorAgent.js.map +1 -1
  31. package/dist/agents/index.d.ts +1 -1
  32. package/dist/agents/index.d.ts.map +1 -1
  33. package/dist/agents/index.js.map +1 -1
  34. package/dist/agents/n8n/N8nAPIClient.d.ts +121 -0
  35. package/dist/agents/n8n/N8nAPIClient.d.ts.map +1 -0
  36. package/dist/agents/n8n/N8nAPIClient.js +367 -0
  37. package/dist/agents/n8n/N8nAPIClient.js.map +1 -0
  38. package/dist/agents/n8n/N8nAuditPersistence.d.ts +120 -0
  39. package/dist/agents/n8n/N8nAuditPersistence.d.ts.map +1 -0
  40. package/dist/agents/n8n/N8nAuditPersistence.js +473 -0
  41. package/dist/agents/n8n/N8nAuditPersistence.js.map +1 -0
  42. package/dist/agents/n8n/N8nBDDScenarioTesterAgent.d.ts +159 -0
  43. package/dist/agents/n8n/N8nBDDScenarioTesterAgent.d.ts.map +1 -0
  44. package/dist/agents/n8n/N8nBDDScenarioTesterAgent.js +697 -0
  45. package/dist/agents/n8n/N8nBDDScenarioTesterAgent.js.map +1 -0
  46. package/dist/agents/n8n/N8nBaseAgent.d.ts +126 -0
  47. package/dist/agents/n8n/N8nBaseAgent.d.ts.map +1 -0
  48. package/dist/agents/n8n/N8nBaseAgent.js +446 -0
  49. package/dist/agents/n8n/N8nBaseAgent.js.map +1 -0
  50. package/dist/agents/n8n/N8nCIOrchestratorAgent.d.ts +164 -0
  51. package/dist/agents/n8n/N8nCIOrchestratorAgent.d.ts.map +1 -0
  52. package/dist/agents/n8n/N8nCIOrchestratorAgent.js +610 -0
  53. package/dist/agents/n8n/N8nCIOrchestratorAgent.js.map +1 -0
  54. package/dist/agents/n8n/N8nChaosTesterAgent.d.ts +205 -0
  55. package/dist/agents/n8n/N8nChaosTesterAgent.d.ts.map +1 -0
  56. package/dist/agents/n8n/N8nChaosTesterAgent.js +729 -0
  57. package/dist/agents/n8n/N8nChaosTesterAgent.js.map +1 -0
  58. package/dist/agents/n8n/N8nComplianceValidatorAgent.d.ts +228 -0
  59. package/dist/agents/n8n/N8nComplianceValidatorAgent.d.ts.map +1 -0
  60. package/dist/agents/n8n/N8nComplianceValidatorAgent.js +986 -0
  61. package/dist/agents/n8n/N8nComplianceValidatorAgent.js.map +1 -0
  62. package/dist/agents/n8n/N8nContractTesterAgent.d.ts +213 -0
  63. package/dist/agents/n8n/N8nContractTesterAgent.d.ts.map +1 -0
  64. package/dist/agents/n8n/N8nContractTesterAgent.js +989 -0
  65. package/dist/agents/n8n/N8nContractTesterAgent.js.map +1 -0
  66. package/dist/agents/n8n/N8nExpressionValidatorAgent.d.ts +99 -0
  67. package/dist/agents/n8n/N8nExpressionValidatorAgent.d.ts.map +1 -0
  68. package/dist/agents/n8n/N8nExpressionValidatorAgent.js +632 -0
  69. package/dist/agents/n8n/N8nExpressionValidatorAgent.js.map +1 -0
  70. package/dist/agents/n8n/N8nFailureModeTesterAgent.d.ts +238 -0
  71. package/dist/agents/n8n/N8nFailureModeTesterAgent.d.ts.map +1 -0
  72. package/dist/agents/n8n/N8nFailureModeTesterAgent.js +956 -0
  73. package/dist/agents/n8n/N8nFailureModeTesterAgent.js.map +1 -0
  74. package/dist/agents/n8n/N8nIdempotencyTesterAgent.d.ts +242 -0
  75. package/dist/agents/n8n/N8nIdempotencyTesterAgent.d.ts.map +1 -0
  76. package/dist/agents/n8n/N8nIdempotencyTesterAgent.js +992 -0
  77. package/dist/agents/n8n/N8nIdempotencyTesterAgent.js.map +1 -0
  78. package/dist/agents/n8n/N8nIntegrationTestAgent.d.ts +104 -0
  79. package/dist/agents/n8n/N8nIntegrationTestAgent.d.ts.map +1 -0
  80. package/dist/agents/n8n/N8nIntegrationTestAgent.js +653 -0
  81. package/dist/agents/n8n/N8nIntegrationTestAgent.js.map +1 -0
  82. package/dist/agents/n8n/N8nMonitoringValidatorAgent.d.ts +210 -0
  83. package/dist/agents/n8n/N8nMonitoringValidatorAgent.d.ts.map +1 -0
  84. package/dist/agents/n8n/N8nMonitoringValidatorAgent.js +669 -0
  85. package/dist/agents/n8n/N8nMonitoringValidatorAgent.js.map +1 -0
  86. package/dist/agents/n8n/N8nNodeValidatorAgent.d.ts +142 -0
  87. package/dist/agents/n8n/N8nNodeValidatorAgent.d.ts.map +1 -0
  88. package/dist/agents/n8n/N8nNodeValidatorAgent.js +1090 -0
  89. package/dist/agents/n8n/N8nNodeValidatorAgent.js.map +1 -0
  90. package/dist/agents/n8n/N8nPerformanceTesterAgent.d.ts +198 -0
  91. package/dist/agents/n8n/N8nPerformanceTesterAgent.d.ts.map +1 -0
  92. package/dist/agents/n8n/N8nPerformanceTesterAgent.js +653 -0
  93. package/dist/agents/n8n/N8nPerformanceTesterAgent.js.map +1 -0
  94. package/dist/agents/n8n/N8nReplayabilityTesterAgent.d.ts +245 -0
  95. package/dist/agents/n8n/N8nReplayabilityTesterAgent.d.ts.map +1 -0
  96. package/dist/agents/n8n/N8nReplayabilityTesterAgent.js +952 -0
  97. package/dist/agents/n8n/N8nReplayabilityTesterAgent.js.map +1 -0
  98. package/dist/agents/n8n/N8nSecretsHygieneAuditorAgent.d.ts +325 -0
  99. package/dist/agents/n8n/N8nSecretsHygieneAuditorAgent.d.ts.map +1 -0
  100. package/dist/agents/n8n/N8nSecretsHygieneAuditorAgent.js +1187 -0
  101. package/dist/agents/n8n/N8nSecretsHygieneAuditorAgent.js.map +1 -0
  102. package/dist/agents/n8n/N8nSecurityAuditorAgent.d.ts +91 -0
  103. package/dist/agents/n8n/N8nSecurityAuditorAgent.d.ts.map +1 -0
  104. package/dist/agents/n8n/N8nSecurityAuditorAgent.js +825 -0
  105. package/dist/agents/n8n/N8nSecurityAuditorAgent.js.map +1 -0
  106. package/dist/agents/n8n/N8nTestHarness.d.ts +131 -0
  107. package/dist/agents/n8n/N8nTestHarness.d.ts.map +1 -0
  108. package/dist/agents/n8n/N8nTestHarness.js +456 -0
  109. package/dist/agents/n8n/N8nTestHarness.js.map +1 -0
  110. package/dist/agents/n8n/N8nTriggerTestAgent.d.ts +119 -0
  111. package/dist/agents/n8n/N8nTriggerTestAgent.d.ts.map +1 -0
  112. package/dist/agents/n8n/N8nTriggerTestAgent.js +652 -0
  113. package/dist/agents/n8n/N8nTriggerTestAgent.js.map +1 -0
  114. package/dist/agents/n8n/N8nUnitTesterAgent.d.ts +130 -0
  115. package/dist/agents/n8n/N8nUnitTesterAgent.d.ts.map +1 -0
  116. package/dist/agents/n8n/N8nUnitTesterAgent.js +522 -0
  117. package/dist/agents/n8n/N8nUnitTesterAgent.js.map +1 -0
  118. package/dist/agents/n8n/N8nVersionComparatorAgent.d.ts +201 -0
  119. package/dist/agents/n8n/N8nVersionComparatorAgent.d.ts.map +1 -0
  120. package/dist/agents/n8n/N8nVersionComparatorAgent.js +645 -0
  121. package/dist/agents/n8n/N8nVersionComparatorAgent.js.map +1 -0
  122. package/dist/agents/n8n/N8nWorkflowExecutorAgent.d.ts +120 -0
  123. package/dist/agents/n8n/N8nWorkflowExecutorAgent.d.ts.map +1 -0
  124. package/dist/agents/n8n/N8nWorkflowExecutorAgent.js +347 -0
  125. package/dist/agents/n8n/N8nWorkflowExecutorAgent.js.map +1 -0
  126. package/dist/agents/n8n/index.d.ts +119 -0
  127. package/dist/agents/n8n/index.d.ts.map +1 -0
  128. package/dist/agents/n8n/index.js +298 -0
  129. package/dist/agents/n8n/index.js.map +1 -0
  130. package/dist/agents/n8n/types.d.ts +486 -0
  131. package/dist/agents/n8n/types.d.ts.map +1 -0
  132. package/dist/agents/n8n/types.js +8 -0
  133. package/dist/agents/n8n/types.js.map +1 -0
  134. package/dist/cli/init/agents.d.ts.map +1 -1
  135. package/dist/cli/init/agents.js +29 -0
  136. package/dist/cli/init/agents.js.map +1 -1
  137. package/dist/cli/init/skills.d.ts.map +1 -1
  138. package/dist/cli/init/skills.js +7 -1
  139. package/dist/cli/init/skills.js.map +1 -1
  140. package/dist/core/memory/HNSWVectorMemory.js +1 -1
  141. package/dist/core/memory/RuVectorPatternStore.d.ts +90 -0
  142. package/dist/core/memory/RuVectorPatternStore.d.ts.map +1 -1
  143. package/dist/core/memory/RuVectorPatternStore.js +209 -0
  144. package/dist/core/memory/RuVectorPatternStore.js.map +1 -1
  145. package/dist/learning/FederatedManager.d.ts +232 -0
  146. package/dist/learning/FederatedManager.d.ts.map +1 -0
  147. package/dist/learning/FederatedManager.js +489 -0
  148. package/dist/learning/FederatedManager.js.map +1 -0
  149. package/dist/learning/HNSWPatternAdapter.d.ts +117 -0
  150. package/dist/learning/HNSWPatternAdapter.d.ts.map +1 -0
  151. package/dist/learning/HNSWPatternAdapter.js +262 -0
  152. package/dist/learning/HNSWPatternAdapter.js.map +1 -0
  153. package/dist/learning/LearningEngine.d.ts +27 -0
  154. package/dist/learning/LearningEngine.d.ts.map +1 -1
  155. package/dist/learning/LearningEngine.js +75 -1
  156. package/dist/learning/LearningEngine.js.map +1 -1
  157. package/dist/learning/PatternCurator.d.ts +217 -0
  158. package/dist/learning/PatternCurator.d.ts.map +1 -0
  159. package/dist/learning/PatternCurator.js +393 -0
  160. package/dist/learning/PatternCurator.js.map +1 -0
  161. package/dist/learning/index.d.ts +6 -0
  162. package/dist/learning/index.d.ts.map +1 -1
  163. package/dist/learning/index.js +16 -1
  164. package/dist/learning/index.js.map +1 -1
  165. package/dist/learning/types.d.ts +4 -0
  166. package/dist/learning/types.d.ts.map +1 -1
  167. package/dist/mcp/server-instructions.d.ts +1 -1
  168. package/dist/mcp/server-instructions.js +1 -1
  169. package/dist/memory/HNSWPatternStore.d.ts +176 -0
  170. package/dist/memory/HNSWPatternStore.d.ts.map +1 -0
  171. package/dist/memory/HNSWPatternStore.js +392 -0
  172. package/dist/memory/HNSWPatternStore.js.map +1 -0
  173. package/dist/memory/index.d.ts +8 -0
  174. package/dist/memory/index.d.ts.map +1 -0
  175. package/dist/memory/index.js +13 -0
  176. package/dist/memory/index.js.map +1 -0
  177. package/dist/providers/HybridRouter.d.ts +85 -4
  178. package/dist/providers/HybridRouter.d.ts.map +1 -1
  179. package/dist/providers/HybridRouter.js +332 -10
  180. package/dist/providers/HybridRouter.js.map +1 -1
  181. package/dist/providers/LLMBaselineTracker.d.ts +120 -0
  182. package/dist/providers/LLMBaselineTracker.d.ts.map +1 -0
  183. package/dist/providers/LLMBaselineTracker.js +305 -0
  184. package/dist/providers/LLMBaselineTracker.js.map +1 -0
  185. package/dist/providers/OpenRouterProvider.d.ts +26 -0
  186. package/dist/providers/OpenRouterProvider.d.ts.map +1 -1
  187. package/dist/providers/OpenRouterProvider.js +75 -6
  188. package/dist/providers/OpenRouterProvider.js.map +1 -1
  189. package/dist/providers/RuVectorClient.d.ts +259 -0
  190. package/dist/providers/RuVectorClient.d.ts.map +1 -0
  191. package/dist/providers/RuVectorClient.js +416 -0
  192. package/dist/providers/RuVectorClient.js.map +1 -0
  193. package/dist/providers/RuvllmPatternCurator.d.ts +116 -0
  194. package/dist/providers/RuvllmPatternCurator.d.ts.map +1 -0
  195. package/dist/providers/RuvllmPatternCurator.js +323 -0
  196. package/dist/providers/RuvllmPatternCurator.js.map +1 -0
  197. package/dist/providers/RuvllmProvider.d.ts +233 -1
  198. package/dist/providers/RuvllmProvider.d.ts.map +1 -1
  199. package/dist/providers/RuvllmProvider.js +781 -11
  200. package/dist/providers/RuvllmProvider.js.map +1 -1
  201. package/dist/providers/index.d.ts +5 -1
  202. package/dist/providers/index.d.ts.map +1 -1
  203. package/dist/providers/index.js +12 -2
  204. package/dist/providers/index.js.map +1 -1
  205. package/dist/utils/ruvllm-loader.d.ts +98 -1
  206. package/dist/utils/ruvllm-loader.d.ts.map +1 -1
  207. package/dist/utils/ruvllm-loader.js.map +1 -1
  208. package/docs/reference/agents.md +91 -2
  209. package/docs/reference/skills.md +97 -2
  210. package/package.json +2 -2
@@ -0,0 +1,652 @@
1
+ "use strict";
2
+ /**
3
+ * N8nTriggerTestAgent
4
+ *
5
+ * Tests n8n workflow triggers including:
6
+ * - Webhook triggers (authentication, payload validation)
7
+ * - Schedule/cron triggers
8
+ * - Polling triggers
9
+ * - Event-driven activation
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.N8nTriggerTestAgent = void 0;
13
+ const N8nBaseAgent_1 = require("./N8nBaseAgent");
14
+ const TRIGGER_TYPES = {
15
+ webhook: ['n8n-nodes-base.webhook', 'n8n-nodes-base.webhookTest'],
16
+ schedule: ['n8n-nodes-base.cron', 'n8n-nodes-base.schedule', 'n8n-nodes-base.scheduleTrigger'],
17
+ email: ['n8n-nodes-base.emailTrigger', 'n8n-nodes-base.emailReadImap'],
18
+ database: ['n8n-nodes-base.postgresTrigger', 'n8n-nodes-base.mysqlTrigger'],
19
+ messaging: [
20
+ 'n8n-nodes-base.slackTrigger',
21
+ 'n8n-nodes-base.telegramTrigger',
22
+ 'n8n-nodes-base.discordTrigger',
23
+ ],
24
+ file: ['n8n-nodes-base.localFileTrigger', 'n8n-nodes-base.s3Trigger'],
25
+ api: ['n8n-nodes-base.httpPollTrigger'],
26
+ };
27
+ class N8nTriggerTestAgent extends N8nBaseAgent_1.N8nBaseAgent {
28
+ constructor(config) {
29
+ const capabilities = [
30
+ {
31
+ name: 'trigger-identification',
32
+ version: '1.0.0',
33
+ description: 'Identify and classify workflow triggers',
34
+ parameters: {},
35
+ },
36
+ {
37
+ name: 'webhook-testing',
38
+ version: '1.0.0',
39
+ description: 'Test webhook trigger configurations',
40
+ parameters: {},
41
+ },
42
+ {
43
+ name: 'authentication-validation',
44
+ version: '1.0.0',
45
+ description: 'Validate trigger authentication settings',
46
+ parameters: {},
47
+ },
48
+ {
49
+ name: 'trigger-simulation',
50
+ version: '1.0.0',
51
+ description: 'Simulate trigger activation',
52
+ parameters: {},
53
+ },
54
+ ];
55
+ super({
56
+ ...config,
57
+ type: 'n8n-trigger-test',
58
+ capabilities: [...capabilities, ...(config.capabilities || [])],
59
+ });
60
+ }
61
+ async performTask(task) {
62
+ const triggerTask = task;
63
+ if (triggerTask.type !== 'trigger-test') {
64
+ throw new Error(`Unsupported task type: ${triggerTask.type}`);
65
+ }
66
+ return this.testTriggers(triggerTask.target, triggerTask.options);
67
+ }
68
+ /**
69
+ * Test all triggers in a workflow
70
+ */
71
+ async testTriggers(workflowId, options) {
72
+ const workflow = await this.getWorkflow(workflowId);
73
+ // Identify triggers
74
+ const triggers = this.identifyTriggers(workflow);
75
+ // Run tests on each trigger
76
+ const testResults = [];
77
+ for (const trigger of triggers) {
78
+ // Configuration tests
79
+ testResults.push(...this.testTriggerConfiguration(trigger, workflow));
80
+ // Authentication tests
81
+ if (options?.testAuthentication) {
82
+ testResults.push(...this.testTriggerAuthentication(trigger));
83
+ }
84
+ // Payload tests (for webhooks)
85
+ if (trigger.type.includes('webhook') && options?.testPayloads) {
86
+ for (const payload of options.testPayloads) {
87
+ testResults.push(await this.testWebhookPayload(trigger, payload, workflowId));
88
+ }
89
+ }
90
+ // Simulate trigger if requested
91
+ if (options?.simulateTriggers) {
92
+ testResults.push(await this.simulateTrigger(trigger, workflowId));
93
+ }
94
+ }
95
+ const result = {
96
+ workflowId,
97
+ triggers,
98
+ testResults,
99
+ summary: {
100
+ total: testResults.length,
101
+ passed: testResults.filter(r => r.actualResult === 'pass').length,
102
+ failed: testResults.filter(r => r.actualResult === 'fail').length,
103
+ },
104
+ };
105
+ // Store result
106
+ await this.storeTestResult(`trigger-test:${workflowId}`, result);
107
+ // Emit event
108
+ this.emitEvent('trigger.test.completed', {
109
+ workflowId,
110
+ triggersFound: triggers.length,
111
+ testsPassed: result.summary.passed,
112
+ testsFailed: result.summary.failed,
113
+ });
114
+ return result;
115
+ }
116
+ /**
117
+ * Identify all triggers in workflow
118
+ */
119
+ identifyTriggers(workflow) {
120
+ const triggers = [];
121
+ for (const node of workflow.nodes) {
122
+ if (this.isTriggerNode(node)) {
123
+ triggers.push({
124
+ nodeId: node.id,
125
+ nodeName: node.name,
126
+ type: node.type,
127
+ configuration: node.parameters,
128
+ authentication: this.getAuthenticationType(node),
129
+ isSecure: this.isSecureTrigger(node),
130
+ });
131
+ }
132
+ }
133
+ return triggers;
134
+ }
135
+ /**
136
+ * Check if node is a trigger
137
+ */
138
+ isTriggerNode(node) {
139
+ const allTriggerTypes = Object.values(TRIGGER_TYPES).flat();
140
+ return (allTriggerTypes.some(t => node.type.includes(t)) ||
141
+ node.type.toLowerCase().includes('trigger'));
142
+ }
143
+ /**
144
+ * Get trigger authentication type
145
+ */
146
+ getAuthenticationType(node) {
147
+ const params = node.parameters;
148
+ if (params.authentication) {
149
+ return params.authentication;
150
+ }
151
+ if (params.headerAuth) {
152
+ return 'headerAuth';
153
+ }
154
+ if (params.basicAuth) {
155
+ return 'basicAuth';
156
+ }
157
+ return null;
158
+ }
159
+ /**
160
+ * Check if trigger is secure
161
+ */
162
+ isSecureTrigger(node) {
163
+ const auth = this.getAuthenticationType(node);
164
+ // Webhook without auth is insecure
165
+ if (node.type.includes('webhook') && (!auth || auth === 'none')) {
166
+ return false;
167
+ }
168
+ return true;
169
+ }
170
+ /**
171
+ * Test trigger configuration
172
+ */
173
+ testTriggerConfiguration(trigger, workflow) {
174
+ const tests = [];
175
+ const startTime = Date.now();
176
+ // Test: Trigger has required configuration
177
+ const hasRequiredConfig = this.hasRequiredTriggerConfig(trigger);
178
+ tests.push({
179
+ triggerId: trigger.nodeId,
180
+ testName: 'Required configuration present',
181
+ input: null,
182
+ expectedBehavior: 'All required parameters configured',
183
+ actualResult: hasRequiredConfig ? 'pass' : 'fail',
184
+ duration: Date.now() - startTime,
185
+ errorMessage: hasRequiredConfig ? undefined : 'Missing required configuration',
186
+ });
187
+ // Test: Trigger is connected to downstream nodes
188
+ const isConnected = this.isTriggerConnected(trigger, workflow);
189
+ tests.push({
190
+ triggerId: trigger.nodeId,
191
+ testName: 'Trigger connected to workflow',
192
+ input: null,
193
+ expectedBehavior: 'Trigger has downstream connections',
194
+ actualResult: isConnected ? 'pass' : 'fail',
195
+ duration: Date.now() - startTime,
196
+ errorMessage: isConnected ? undefined : 'Trigger not connected to any nodes',
197
+ });
198
+ // Test: Security check
199
+ tests.push({
200
+ triggerId: trigger.nodeId,
201
+ testName: 'Security configuration',
202
+ input: null,
203
+ expectedBehavior: 'Trigger is securely configured',
204
+ actualResult: trigger.isSecure ? 'pass' : 'fail',
205
+ duration: Date.now() - startTime,
206
+ errorMessage: trigger.isSecure ? undefined : 'Trigger lacks authentication',
207
+ });
208
+ return tests;
209
+ }
210
+ /**
211
+ * Test trigger authentication
212
+ */
213
+ testTriggerAuthentication(trigger) {
214
+ const tests = [];
215
+ const startTime = Date.now();
216
+ // Only test webhooks for authentication
217
+ if (!trigger.type.includes('webhook')) {
218
+ return tests;
219
+ }
220
+ // Test: Has authentication configured
221
+ tests.push({
222
+ triggerId: trigger.nodeId,
223
+ testName: 'Authentication enabled',
224
+ input: null,
225
+ expectedBehavior: 'Webhook has authentication',
226
+ actualResult: trigger.authentication && trigger.authentication !== 'none' ? 'pass' : 'fail',
227
+ duration: Date.now() - startTime,
228
+ });
229
+ // Test: Authentication type is secure
230
+ const secureAuthTypes = ['headerAuth', 'basicAuth', 'jwtAuth', 'oauth2'];
231
+ const isSecureAuth = trigger.authentication
232
+ ? secureAuthTypes.includes(trigger.authentication)
233
+ : false;
234
+ tests.push({
235
+ triggerId: trigger.nodeId,
236
+ testName: 'Secure authentication type',
237
+ input: null,
238
+ expectedBehavior: 'Uses secure authentication method',
239
+ actualResult: isSecureAuth ? 'pass' : 'fail',
240
+ duration: Date.now() - startTime,
241
+ errorMessage: isSecureAuth ? undefined : `Authentication type "${trigger.authentication}" may not be secure`,
242
+ });
243
+ return tests;
244
+ }
245
+ /**
246
+ * Test webhook with payload via ACTUAL HTTP invocation
247
+ *
248
+ * PRODUCTION TESTING: Tries both test-mode and production URLs
249
+ * - Test URL: /webhook-test/<workflowId>/<path> (doesn't require active workflow)
250
+ * - Production URL: /webhook/<path> (requires active workflow)
251
+ */
252
+ async testWebhookPayload(trigger, payload, workflowId) {
253
+ const startTime = Date.now();
254
+ // Get both webhook URLs
255
+ const urls = this.getAllWebhookUrls(trigger, workflowId);
256
+ // Try test webhook URL first (doesn't require active workflow)
257
+ if (urls.test) {
258
+ try {
259
+ const result = await this.invokeWebhookHttp(trigger, urls.test, payload, startTime);
260
+ // If test webhook succeeds, return that result
261
+ if (result.actualResult === 'pass') {
262
+ return {
263
+ ...result,
264
+ testName: `Webhook test (test-mode): ${JSON.stringify(payload).substring(0, 50)}...`,
265
+ metadata: { ...result.metadata, urlType: 'test' },
266
+ };
267
+ }
268
+ }
269
+ catch {
270
+ // Test webhook failed, try production webhook
271
+ }
272
+ }
273
+ // Try production webhook URL (requires workflow to be active)
274
+ if (urls.production) {
275
+ try {
276
+ const result = await this.invokeWebhookHttp(trigger, urls.production, payload, startTime);
277
+ return {
278
+ ...result,
279
+ metadata: { ...result.metadata, urlType: 'production' },
280
+ };
281
+ }
282
+ catch {
283
+ // Production webhook also failed, fall through to direct execution
284
+ }
285
+ }
286
+ // Fallback: Execute workflow directly with test data
287
+ try {
288
+ const execution = await this.executeWorkflow(workflowId, payload, {
289
+ waitForCompletion: true,
290
+ timeout: 10000,
291
+ });
292
+ return {
293
+ triggerId: trigger.nodeId,
294
+ testName: `Payload test (direct execution): ${JSON.stringify(payload).substring(0, 50)}...`,
295
+ input: payload,
296
+ expectedBehavior: 'Workflow executes successfully with payload',
297
+ actualResult: execution.status === 'success' ? 'pass' : 'fail',
298
+ executionId: execution.id,
299
+ duration: Date.now() - startTime,
300
+ errorMessage: execution.status !== 'success'
301
+ ? execution.data?.resultData?.error?.message
302
+ : undefined,
303
+ metadata: { urlType: 'direct-execution' },
304
+ };
305
+ }
306
+ catch (error) {
307
+ return {
308
+ triggerId: trigger.nodeId,
309
+ testName: `Payload test (direct execution): ${JSON.stringify(payload).substring(0, 50)}...`,
310
+ input: payload,
311
+ expectedBehavior: 'Workflow executes successfully with payload',
312
+ actualResult: 'error',
313
+ duration: Date.now() - startTime,
314
+ errorMessage: error instanceof Error ? error.message : 'Execution failed',
315
+ metadata: { urlType: 'direct-execution', triedUrls: urls },
316
+ };
317
+ }
318
+ }
319
+ /**
320
+ * Invoke webhook via REAL HTTP request
321
+ * This tests the actual webhook endpoint, authentication, and payload handling
322
+ */
323
+ async invokeWebhookHttp(trigger, webhookUrl, payload, startTime) {
324
+ const httpMethod = trigger.configuration.httpMethod || 'POST';
325
+ try {
326
+ // Build headers with authentication if configured
327
+ const headers = {
328
+ 'Content-Type': 'application/json',
329
+ };
330
+ // Add authentication headers based on trigger config
331
+ if (trigger.authentication === 'headerAuth' && trigger.configuration.headerAuthName) {
332
+ headers[trigger.configuration.headerAuthName] =
333
+ trigger.configuration.headerAuthValue || 'test-value';
334
+ }
335
+ if (trigger.authentication === 'basicAuth') {
336
+ const username = trigger.configuration.basicAuthUser || '';
337
+ const password = trigger.configuration.basicAuthPassword || '';
338
+ headers['Authorization'] = 'Basic ' + Buffer.from(`${username}:${password}`).toString('base64');
339
+ }
340
+ // Make the actual HTTP request
341
+ const response = await fetch(webhookUrl, {
342
+ method: httpMethod,
343
+ headers,
344
+ body: httpMethod !== 'GET' ? JSON.stringify(payload) : undefined,
345
+ });
346
+ const responseData = await response.text();
347
+ let responseJson;
348
+ try {
349
+ responseJson = JSON.parse(responseData);
350
+ }
351
+ catch {
352
+ responseJson = responseData;
353
+ }
354
+ // Success is 2xx status code
355
+ const isSuccess = response.status >= 200 && response.status < 300;
356
+ return {
357
+ triggerId: trigger.nodeId,
358
+ testName: `HTTP ${httpMethod} webhook: ${webhookUrl}`,
359
+ input: { payload, headers: Object.keys(headers) },
360
+ expectedBehavior: 'Webhook responds successfully to HTTP request',
361
+ actualResult: isSuccess ? 'pass' : 'fail',
362
+ duration: Date.now() - startTime,
363
+ errorMessage: !isSuccess ? `HTTP ${response.status}: ${responseData.substring(0, 200)}` : undefined,
364
+ metadata: {
365
+ httpStatus: response.status,
366
+ responseData: responseJson,
367
+ method: httpMethod,
368
+ url: webhookUrl,
369
+ },
370
+ };
371
+ }
372
+ catch (error) {
373
+ return {
374
+ triggerId: trigger.nodeId,
375
+ testName: `HTTP ${httpMethod} webhook: ${webhookUrl}`,
376
+ input: payload,
377
+ expectedBehavior: 'Webhook endpoint is reachable',
378
+ actualResult: 'error',
379
+ duration: Date.now() - startTime,
380
+ errorMessage: error instanceof Error ? error.message : 'HTTP request failed',
381
+ metadata: {
382
+ method: httpMethod,
383
+ url: webhookUrl,
384
+ error: error instanceof Error ? error.name : 'Unknown',
385
+ },
386
+ };
387
+ }
388
+ }
389
+ /**
390
+ * Test webhook without authentication (security test)
391
+ * Verifies that protected webhooks reject unauthenticated requests
392
+ */
393
+ async testWebhookWithoutAuth(trigger, payload) {
394
+ const startTime = Date.now();
395
+ const webhookUrl = this.getWebhookUrl(trigger);
396
+ if (!webhookUrl) {
397
+ return {
398
+ triggerId: trigger.nodeId,
399
+ testName: 'Unauthenticated access test',
400
+ input: payload,
401
+ expectedBehavior: 'Cannot determine webhook URL',
402
+ actualResult: 'error',
403
+ duration: Date.now() - startTime,
404
+ errorMessage: 'Webhook URL not available',
405
+ };
406
+ }
407
+ try {
408
+ // Make request WITHOUT authentication headers
409
+ const response = await fetch(webhookUrl, {
410
+ method: trigger.configuration.httpMethod || 'POST',
411
+ headers: { 'Content-Type': 'application/json' },
412
+ body: JSON.stringify(payload),
413
+ });
414
+ // If webhook requires auth, it should reject (4xx status)
415
+ const hasAuth = trigger.authentication && trigger.authentication !== 'none';
416
+ if (hasAuth) {
417
+ // Protected webhook should reject unauthenticated requests
418
+ const rejectedCorrectly = response.status === 401 || response.status === 403;
419
+ return {
420
+ triggerId: trigger.nodeId,
421
+ testName: 'Unauthenticated access blocked',
422
+ input: payload,
423
+ expectedBehavior: 'Protected webhook rejects request without credentials',
424
+ actualResult: rejectedCorrectly ? 'pass' : 'fail',
425
+ duration: Date.now() - startTime,
426
+ errorMessage: !rejectedCorrectly
427
+ ? `Expected 401/403 but got ${response.status} - webhook may be vulnerable`
428
+ : undefined,
429
+ };
430
+ }
431
+ else {
432
+ // Unprotected webhook - just check it responds
433
+ return {
434
+ triggerId: trigger.nodeId,
435
+ testName: 'Public webhook accessible',
436
+ input: payload,
437
+ expectedBehavior: 'Public webhook accepts request',
438
+ actualResult: response.status < 500 ? 'pass' : 'fail',
439
+ duration: Date.now() - startTime,
440
+ };
441
+ }
442
+ }
443
+ catch (error) {
444
+ return {
445
+ triggerId: trigger.nodeId,
446
+ testName: 'Unauthenticated access test',
447
+ input: payload,
448
+ expectedBehavior: 'Webhook endpoint responds',
449
+ actualResult: 'error',
450
+ duration: Date.now() - startTime,
451
+ errorMessage: error instanceof Error ? error.message : 'Request failed',
452
+ };
453
+ }
454
+ }
455
+ /**
456
+ * Test webhook with malformed payloads (robustness test)
457
+ */
458
+ async testWebhookPayloadValidation(trigger) {
459
+ const webhookUrl = this.getWebhookUrl(trigger);
460
+ if (!webhookUrl)
461
+ return [];
462
+ const malformedPayloads = [
463
+ { name: 'Empty body', payload: null },
464
+ { name: 'Invalid JSON string', payload: 'not-json' },
465
+ { name: 'Array instead of object', payload: [1, 2, 3] },
466
+ { name: 'Nested nulls', payload: { a: { b: null, c: undefined } } },
467
+ { name: 'Very large payload', payload: { data: 'x'.repeat(10000) } },
468
+ ];
469
+ const results = [];
470
+ for (const test of malformedPayloads) {
471
+ const startTime = Date.now();
472
+ try {
473
+ const response = await fetch(webhookUrl, {
474
+ method: trigger.configuration.httpMethod || 'POST',
475
+ headers: { 'Content-Type': 'application/json' },
476
+ body: typeof test.payload === 'string' ? test.payload : JSON.stringify(test.payload),
477
+ });
478
+ // Should not crash (5xx) on bad input - graceful handling expected
479
+ results.push({
480
+ triggerId: trigger.nodeId,
481
+ testName: `Payload validation: ${test.name}`,
482
+ input: test.payload,
483
+ expectedBehavior: 'Webhook handles malformed payload gracefully',
484
+ actualResult: response.status < 500 ? 'pass' : 'fail',
485
+ duration: Date.now() - startTime,
486
+ errorMessage: response.status >= 500 ? `Server error ${response.status}` : undefined,
487
+ });
488
+ }
489
+ catch (error) {
490
+ results.push({
491
+ triggerId: trigger.nodeId,
492
+ testName: `Payload validation: ${test.name}`,
493
+ input: test.payload,
494
+ expectedBehavior: 'Webhook handles malformed payload gracefully',
495
+ actualResult: 'error',
496
+ duration: Date.now() - startTime,
497
+ errorMessage: error instanceof Error ? error.message : 'Request failed',
498
+ });
499
+ }
500
+ }
501
+ return results;
502
+ }
503
+ /**
504
+ * Simulate trigger activation
505
+ */
506
+ async simulateTrigger(trigger, workflowId) {
507
+ const startTime = Date.now();
508
+ // Generate test data based on trigger type
509
+ const testData = this.generateTriggerTestData(trigger);
510
+ try {
511
+ const execution = await this.executeWorkflow(workflowId, testData, {
512
+ waitForCompletion: true,
513
+ timeout: 15000,
514
+ });
515
+ return {
516
+ triggerId: trigger.nodeId,
517
+ testName: `Simulate ${trigger.type} trigger`,
518
+ input: testData,
519
+ expectedBehavior: 'Trigger activates workflow successfully',
520
+ actualResult: execution.status === 'success' ? 'pass' : 'fail',
521
+ executionId: execution.id,
522
+ duration: Date.now() - startTime,
523
+ };
524
+ }
525
+ catch (error) {
526
+ return {
527
+ triggerId: trigger.nodeId,
528
+ testName: `Simulate ${trigger.type} trigger`,
529
+ input: testData,
530
+ expectedBehavior: 'Trigger activates workflow successfully',
531
+ actualResult: 'error',
532
+ duration: Date.now() - startTime,
533
+ errorMessage: error instanceof Error ? error.message : 'Simulation failed',
534
+ };
535
+ }
536
+ }
537
+ /**
538
+ * Check if trigger has required configuration
539
+ */
540
+ hasRequiredTriggerConfig(trigger) {
541
+ if (trigger.type.includes('webhook')) {
542
+ return !!(trigger.configuration.httpMethod && trigger.configuration.path);
543
+ }
544
+ if (trigger.type.includes('cron') || trigger.type.includes('schedule')) {
545
+ return !!(trigger.configuration.rule || trigger.configuration.interval);
546
+ }
547
+ // Default to true for other trigger types
548
+ return true;
549
+ }
550
+ /**
551
+ * Check if trigger is connected to downstream nodes
552
+ */
553
+ isTriggerConnected(trigger, workflow) {
554
+ return !!workflow.connections[trigger.nodeName];
555
+ }
556
+ /**
557
+ * Generate test data for trigger type
558
+ */
559
+ generateTriggerTestData(trigger) {
560
+ if (trigger.type.includes('webhook')) {
561
+ return {
562
+ headers: { 'Content-Type': 'application/json' },
563
+ body: { test: true, timestamp: Date.now() },
564
+ query: {},
565
+ };
566
+ }
567
+ if (trigger.type.includes('email')) {
568
+ return {
569
+ from: 'test@example.com',
570
+ subject: 'Test Email',
571
+ text: 'This is a test email',
572
+ date: new Date().toISOString(),
573
+ };
574
+ }
575
+ if (trigger.type.includes('slack')) {
576
+ return {
577
+ type: 'message',
578
+ channel: '#test',
579
+ user: 'U123456',
580
+ text: 'Test message',
581
+ ts: Date.now().toString(),
582
+ };
583
+ }
584
+ // Default test data
585
+ return {
586
+ triggered: true,
587
+ timestamp: Date.now(),
588
+ source: 'test',
589
+ };
590
+ }
591
+ /**
592
+ * Get webhook URL for a trigger
593
+ *
594
+ * n8n webhook URL patterns:
595
+ * - Production (workflow active): /webhook/<path>
596
+ * - Test mode: /webhook-test/<workflowId>/<path>
597
+ * - With UUID path: /webhook/<uuid>
598
+ *
599
+ * Returns both production and test URLs for comprehensive testing
600
+ */
601
+ getWebhookUrl(trigger, workflowId) {
602
+ if (!trigger.type.includes('webhook')) {
603
+ return null;
604
+ }
605
+ const path = trigger.configuration.path;
606
+ if (!path)
607
+ return null;
608
+ // Remove leading slash if present
609
+ const cleanPath = path.replace(/^\//, '');
610
+ // Return production webhook URL
611
+ // For test mode, use getWebhookTestUrl()
612
+ return `${this.n8nConfig.baseUrl}/webhook/${cleanPath}`;
613
+ }
614
+ /**
615
+ * Get webhook TEST URL for a trigger
616
+ * Test mode webhooks don't require the workflow to be active
617
+ */
618
+ getWebhookTestUrl(trigger, workflowId) {
619
+ if (!trigger.type.includes('webhook')) {
620
+ return null;
621
+ }
622
+ const path = trigger.configuration.path;
623
+ if (!path)
624
+ return null;
625
+ // Remove leading slash if present
626
+ const cleanPath = path.replace(/^\//, '');
627
+ // n8n test webhook format: /webhook-test/<workflowId>/<path>
628
+ return `${this.n8nConfig.baseUrl}/webhook-test/${workflowId}/${cleanPath}`;
629
+ }
630
+ /**
631
+ * Get all possible webhook URLs for comprehensive testing
632
+ */
633
+ getAllWebhookUrls(trigger, workflowId) {
634
+ return {
635
+ production: this.getWebhookUrl(trigger, workflowId),
636
+ test: this.getWebhookTestUrl(trigger, workflowId),
637
+ };
638
+ }
639
+ /**
640
+ * Get trigger type category
641
+ */
642
+ getTriggerCategory(trigger) {
643
+ for (const [category, types] of Object.entries(TRIGGER_TYPES)) {
644
+ if (types.some(t => trigger.type.includes(t))) {
645
+ return category;
646
+ }
647
+ }
648
+ return 'other';
649
+ }
650
+ }
651
+ exports.N8nTriggerTestAgent = N8nTriggerTestAgent;
652
+ //# sourceMappingURL=N8nTriggerTestAgent.js.map