agentic-qe 2.5.6 → 2.5.7

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 (134) 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 +41 -0
  22. package/README.md +7 -4
  23. package/dist/agents/n8n/N8nAPIClient.d.ts +121 -0
  24. package/dist/agents/n8n/N8nAPIClient.d.ts.map +1 -0
  25. package/dist/agents/n8n/N8nAPIClient.js +367 -0
  26. package/dist/agents/n8n/N8nAPIClient.js.map +1 -0
  27. package/dist/agents/n8n/N8nAuditPersistence.d.ts +120 -0
  28. package/dist/agents/n8n/N8nAuditPersistence.d.ts.map +1 -0
  29. package/dist/agents/n8n/N8nAuditPersistence.js +473 -0
  30. package/dist/agents/n8n/N8nAuditPersistence.js.map +1 -0
  31. package/dist/agents/n8n/N8nBDDScenarioTesterAgent.d.ts +159 -0
  32. package/dist/agents/n8n/N8nBDDScenarioTesterAgent.d.ts.map +1 -0
  33. package/dist/agents/n8n/N8nBDDScenarioTesterAgent.js +697 -0
  34. package/dist/agents/n8n/N8nBDDScenarioTesterAgent.js.map +1 -0
  35. package/dist/agents/n8n/N8nBaseAgent.d.ts +126 -0
  36. package/dist/agents/n8n/N8nBaseAgent.d.ts.map +1 -0
  37. package/dist/agents/n8n/N8nBaseAgent.js +446 -0
  38. package/dist/agents/n8n/N8nBaseAgent.js.map +1 -0
  39. package/dist/agents/n8n/N8nCIOrchestratorAgent.d.ts +164 -0
  40. package/dist/agents/n8n/N8nCIOrchestratorAgent.d.ts.map +1 -0
  41. package/dist/agents/n8n/N8nCIOrchestratorAgent.js +610 -0
  42. package/dist/agents/n8n/N8nCIOrchestratorAgent.js.map +1 -0
  43. package/dist/agents/n8n/N8nChaosTesterAgent.d.ts +205 -0
  44. package/dist/agents/n8n/N8nChaosTesterAgent.d.ts.map +1 -0
  45. package/dist/agents/n8n/N8nChaosTesterAgent.js +729 -0
  46. package/dist/agents/n8n/N8nChaosTesterAgent.js.map +1 -0
  47. package/dist/agents/n8n/N8nComplianceValidatorAgent.d.ts +228 -0
  48. package/dist/agents/n8n/N8nComplianceValidatorAgent.d.ts.map +1 -0
  49. package/dist/agents/n8n/N8nComplianceValidatorAgent.js +986 -0
  50. package/dist/agents/n8n/N8nComplianceValidatorAgent.js.map +1 -0
  51. package/dist/agents/n8n/N8nContractTesterAgent.d.ts +213 -0
  52. package/dist/agents/n8n/N8nContractTesterAgent.d.ts.map +1 -0
  53. package/dist/agents/n8n/N8nContractTesterAgent.js +989 -0
  54. package/dist/agents/n8n/N8nContractTesterAgent.js.map +1 -0
  55. package/dist/agents/n8n/N8nExpressionValidatorAgent.d.ts +99 -0
  56. package/dist/agents/n8n/N8nExpressionValidatorAgent.d.ts.map +1 -0
  57. package/dist/agents/n8n/N8nExpressionValidatorAgent.js +632 -0
  58. package/dist/agents/n8n/N8nExpressionValidatorAgent.js.map +1 -0
  59. package/dist/agents/n8n/N8nFailureModeTesterAgent.d.ts +238 -0
  60. package/dist/agents/n8n/N8nFailureModeTesterAgent.d.ts.map +1 -0
  61. package/dist/agents/n8n/N8nFailureModeTesterAgent.js +956 -0
  62. package/dist/agents/n8n/N8nFailureModeTesterAgent.js.map +1 -0
  63. package/dist/agents/n8n/N8nIdempotencyTesterAgent.d.ts +242 -0
  64. package/dist/agents/n8n/N8nIdempotencyTesterAgent.d.ts.map +1 -0
  65. package/dist/agents/n8n/N8nIdempotencyTesterAgent.js +992 -0
  66. package/dist/agents/n8n/N8nIdempotencyTesterAgent.js.map +1 -0
  67. package/dist/agents/n8n/N8nIntegrationTestAgent.d.ts +104 -0
  68. package/dist/agents/n8n/N8nIntegrationTestAgent.d.ts.map +1 -0
  69. package/dist/agents/n8n/N8nIntegrationTestAgent.js +653 -0
  70. package/dist/agents/n8n/N8nIntegrationTestAgent.js.map +1 -0
  71. package/dist/agents/n8n/N8nMonitoringValidatorAgent.d.ts +210 -0
  72. package/dist/agents/n8n/N8nMonitoringValidatorAgent.d.ts.map +1 -0
  73. package/dist/agents/n8n/N8nMonitoringValidatorAgent.js +669 -0
  74. package/dist/agents/n8n/N8nMonitoringValidatorAgent.js.map +1 -0
  75. package/dist/agents/n8n/N8nNodeValidatorAgent.d.ts +142 -0
  76. package/dist/agents/n8n/N8nNodeValidatorAgent.d.ts.map +1 -0
  77. package/dist/agents/n8n/N8nNodeValidatorAgent.js +1090 -0
  78. package/dist/agents/n8n/N8nNodeValidatorAgent.js.map +1 -0
  79. package/dist/agents/n8n/N8nPerformanceTesterAgent.d.ts +198 -0
  80. package/dist/agents/n8n/N8nPerformanceTesterAgent.d.ts.map +1 -0
  81. package/dist/agents/n8n/N8nPerformanceTesterAgent.js +653 -0
  82. package/dist/agents/n8n/N8nPerformanceTesterAgent.js.map +1 -0
  83. package/dist/agents/n8n/N8nReplayabilityTesterAgent.d.ts +245 -0
  84. package/dist/agents/n8n/N8nReplayabilityTesterAgent.d.ts.map +1 -0
  85. package/dist/agents/n8n/N8nReplayabilityTesterAgent.js +952 -0
  86. package/dist/agents/n8n/N8nReplayabilityTesterAgent.js.map +1 -0
  87. package/dist/agents/n8n/N8nSecretsHygieneAuditorAgent.d.ts +325 -0
  88. package/dist/agents/n8n/N8nSecretsHygieneAuditorAgent.d.ts.map +1 -0
  89. package/dist/agents/n8n/N8nSecretsHygieneAuditorAgent.js +1187 -0
  90. package/dist/agents/n8n/N8nSecretsHygieneAuditorAgent.js.map +1 -0
  91. package/dist/agents/n8n/N8nSecurityAuditorAgent.d.ts +91 -0
  92. package/dist/agents/n8n/N8nSecurityAuditorAgent.d.ts.map +1 -0
  93. package/dist/agents/n8n/N8nSecurityAuditorAgent.js +825 -0
  94. package/dist/agents/n8n/N8nSecurityAuditorAgent.js.map +1 -0
  95. package/dist/agents/n8n/N8nTestHarness.d.ts +131 -0
  96. package/dist/agents/n8n/N8nTestHarness.d.ts.map +1 -0
  97. package/dist/agents/n8n/N8nTestHarness.js +456 -0
  98. package/dist/agents/n8n/N8nTestHarness.js.map +1 -0
  99. package/dist/agents/n8n/N8nTriggerTestAgent.d.ts +119 -0
  100. package/dist/agents/n8n/N8nTriggerTestAgent.d.ts.map +1 -0
  101. package/dist/agents/n8n/N8nTriggerTestAgent.js +652 -0
  102. package/dist/agents/n8n/N8nTriggerTestAgent.js.map +1 -0
  103. package/dist/agents/n8n/N8nUnitTesterAgent.d.ts +130 -0
  104. package/dist/agents/n8n/N8nUnitTesterAgent.d.ts.map +1 -0
  105. package/dist/agents/n8n/N8nUnitTesterAgent.js +522 -0
  106. package/dist/agents/n8n/N8nUnitTesterAgent.js.map +1 -0
  107. package/dist/agents/n8n/N8nVersionComparatorAgent.d.ts +201 -0
  108. package/dist/agents/n8n/N8nVersionComparatorAgent.d.ts.map +1 -0
  109. package/dist/agents/n8n/N8nVersionComparatorAgent.js +645 -0
  110. package/dist/agents/n8n/N8nVersionComparatorAgent.js.map +1 -0
  111. package/dist/agents/n8n/N8nWorkflowExecutorAgent.d.ts +120 -0
  112. package/dist/agents/n8n/N8nWorkflowExecutorAgent.d.ts.map +1 -0
  113. package/dist/agents/n8n/N8nWorkflowExecutorAgent.js +347 -0
  114. package/dist/agents/n8n/N8nWorkflowExecutorAgent.js.map +1 -0
  115. package/dist/agents/n8n/index.d.ts +119 -0
  116. package/dist/agents/n8n/index.d.ts.map +1 -0
  117. package/dist/agents/n8n/index.js +298 -0
  118. package/dist/agents/n8n/index.js.map +1 -0
  119. package/dist/agents/n8n/types.d.ts +486 -0
  120. package/dist/agents/n8n/types.d.ts.map +1 -0
  121. package/dist/agents/n8n/types.js +8 -0
  122. package/dist/agents/n8n/types.js.map +1 -0
  123. package/dist/cli/init/agents.d.ts.map +1 -1
  124. package/dist/cli/init/agents.js +29 -0
  125. package/dist/cli/init/agents.js.map +1 -1
  126. package/dist/cli/init/skills.d.ts.map +1 -1
  127. package/dist/cli/init/skills.js +7 -1
  128. package/dist/cli/init/skills.js.map +1 -1
  129. package/dist/core/memory/HNSWVectorMemory.js +1 -1
  130. package/dist/mcp/server-instructions.d.ts +1 -1
  131. package/dist/mcp/server-instructions.js +1 -1
  132. package/docs/reference/agents.md +91 -2
  133. package/docs/reference/skills.md +97 -2
  134. package/package.json +2 -2
@@ -0,0 +1,541 @@
1
+ ---
2
+ name: n8n-trigger-testing-strategies
3
+ description: "Webhook testing, schedule validation, event-driven triggers, and polling mechanism testing for n8n workflows. Use when testing how workflows are triggered."
4
+ category: n8n-testing
5
+ priority: high
6
+ tokenEstimate: 1000
7
+ agents: [n8n-trigger-test]
8
+ implementation_status: production
9
+ optimization_version: 1.0
10
+ last_optimized: 2025-12-15
11
+ dependencies: []
12
+ quick_reference_card: true
13
+ tags: [n8n, triggers, webhook, schedule, cron, polling, testing]
14
+ ---
15
+
16
+ # n8n Trigger Testing Strategies
17
+
18
+ <default_to_action>
19
+ When testing n8n triggers:
20
+ 1. IDENTIFY trigger type (webhook, schedule, polling, event)
21
+ 2. TEST with various valid payloads
22
+ 3. VERIFY authentication and authorization
23
+ 4. CHECK error handling for invalid inputs
24
+ 5. MEASURE response time and reliability
25
+
26
+ **Quick Trigger Checklist:**
27
+ - Trigger activates workflow correctly
28
+ - Payload parsed and validated
29
+ - Authentication enforced (if configured)
30
+ - Error responses are informative
31
+ - Response time is acceptable
32
+
33
+ **Critical Success Factors:**
34
+ - Test edge cases (empty payloads, large payloads)
35
+ - Verify idempotency where needed
36
+ - Check timeout handling
37
+ - Monitor for missed triggers
38
+ </default_to_action>
39
+
40
+ ## Quick Reference Card
41
+
42
+ ### n8n Trigger Types
43
+
44
+ | Type | Use Case | Testing Focus |
45
+ |------|----------|---------------|
46
+ | **Webhook** | External HTTP calls | Payloads, auth, methods |
47
+ | **Schedule** | Timed execution | Cron accuracy, timezone |
48
+ | **Polling** | Check for changes | Interval, deduplication |
49
+ | **Event** | Service events | Event handling, filtering |
50
+
51
+ ### Common Webhook Configurations
52
+
53
+ | Setting | Options | Impact |
54
+ |---------|---------|--------|
55
+ | HTTP Method | GET, POST, PUT, DELETE | Request handling |
56
+ | Authentication | None, Basic, Header | Security |
57
+ | Response Mode | Immediately, Last Node, Custom | Response timing |
58
+ | Path | Custom URL path | Endpoint identification |
59
+
60
+ ---
61
+
62
+ ## Webhook Testing
63
+
64
+ ### Basic Webhook Test
65
+
66
+ ```typescript
67
+ // Test webhook with various payloads
68
+ async function testWebhook(webhookUrl: string): Promise<WebhookTestResult> {
69
+ const testPayloads = [
70
+ // Valid JSON
71
+ { type: 'json', data: { event: 'test', timestamp: Date.now() } },
72
+ // Empty object
73
+ { type: 'empty', data: {} },
74
+ // Large payload
75
+ { type: 'large', data: { items: Array(1000).fill({ id: 1, name: 'test' }) } },
76
+ // Nested data
77
+ { type: 'nested', data: { level1: { level2: { level3: { value: 'deep' } } } } },
78
+ // Special characters
79
+ { type: 'special', data: { text: 'Hello <script>alert("xss")</script>' } }
80
+ ];
81
+
82
+ const results: PayloadTestResult[] = [];
83
+
84
+ for (const payload of testPayloads) {
85
+ const startTime = Date.now();
86
+
87
+ try {
88
+ const response = await fetch(webhookUrl, {
89
+ method: 'POST',
90
+ headers: { 'Content-Type': 'application/json' },
91
+ body: JSON.stringify(payload.data)
92
+ });
93
+
94
+ results.push({
95
+ payloadType: payload.type,
96
+ success: response.ok,
97
+ status: response.status,
98
+ responseTime: Date.now() - startTime,
99
+ responseBody: await response.text()
100
+ });
101
+ } catch (error) {
102
+ results.push({
103
+ payloadType: payload.type,
104
+ success: false,
105
+ error: error.message
106
+ });
107
+ }
108
+ }
109
+
110
+ return { webhookUrl, results };
111
+ }
112
+ ```
113
+
114
+ ### HTTP Method Testing
115
+
116
+ ```typescript
117
+ // Test all HTTP methods
118
+ async function testWebhookMethods(webhookUrl: string): Promise<MethodTestResult[]> {
119
+ const methods = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'];
120
+ const results: MethodTestResult[] = [];
121
+
122
+ for (const method of methods) {
123
+ try {
124
+ const response = await fetch(webhookUrl, {
125
+ method,
126
+ headers: { 'Content-Type': 'application/json' },
127
+ body: ['GET', 'HEAD', 'OPTIONS'].includes(method) ? undefined : '{}'
128
+ });
129
+
130
+ results.push({
131
+ method,
132
+ allowed: response.ok || response.status !== 405,
133
+ status: response.status,
134
+ statusText: response.statusText
135
+ });
136
+ } catch (error) {
137
+ results.push({
138
+ method,
139
+ allowed: false,
140
+ error: error.message
141
+ });
142
+ }
143
+ }
144
+
145
+ return results;
146
+ }
147
+ ```
148
+
149
+ ### Authentication Testing
150
+
151
+ ```typescript
152
+ // Test webhook authentication
153
+ async function testWebhookAuth(webhookUrl: string, authConfig: AuthConfig): Promise<AuthTestResult> {
154
+ const scenarios = [
155
+ // No auth
156
+ { name: 'no-auth', headers: {} },
157
+ // Invalid auth
158
+ { name: 'invalid-auth', headers: { 'Authorization': 'Bearer invalid-token' } },
159
+ // Valid auth
160
+ { name: 'valid-auth', headers: { 'Authorization': `Bearer ${authConfig.token}` } },
161
+ // Expired auth
162
+ { name: 'expired-auth', headers: { 'Authorization': `Bearer ${authConfig.expiredToken}` } }
163
+ ];
164
+
165
+ const results: AuthScenarioResult[] = [];
166
+
167
+ for (const scenario of scenarios) {
168
+ const response = await fetch(webhookUrl, {
169
+ method: 'POST',
170
+ headers: {
171
+ 'Content-Type': 'application/json',
172
+ ...scenario.headers
173
+ },
174
+ body: '{}'
175
+ });
176
+
177
+ results.push({
178
+ scenario: scenario.name,
179
+ status: response.status,
180
+ authenticated: response.ok,
181
+ errorMessage: response.ok ? null : await response.text()
182
+ });
183
+ }
184
+
185
+ return {
186
+ authRequired: !results.find(r => r.scenario === 'no-auth')?.authenticated,
187
+ invalidRejected: !results.find(r => r.scenario === 'invalid-auth')?.authenticated,
188
+ validAccepted: results.find(r => r.scenario === 'valid-auth')?.authenticated,
189
+ results
190
+ };
191
+ }
192
+ ```
193
+
194
+ ---
195
+
196
+ ## Schedule Testing
197
+
198
+ ### Cron Expression Validation
199
+
200
+ ```typescript
201
+ // Validate cron expression
202
+ function validateCronExpression(expression: string): CronValidationResult {
203
+ const parts = expression.trim().split(/\s+/);
204
+
205
+ if (parts.length < 5 || parts.length > 6) {
206
+ return {
207
+ valid: false,
208
+ error: `Expected 5-6 parts, got ${parts.length}`
209
+ };
210
+ }
211
+
212
+ const [minute, hour, dayOfMonth, month, dayOfWeek, year] = parts;
213
+
214
+ const validations = [
215
+ { field: 'minute', value: minute, range: [0, 59] },
216
+ { field: 'hour', value: hour, range: [0, 23] },
217
+ { field: 'dayOfMonth', value: dayOfMonth, range: [1, 31] },
218
+ { field: 'month', value: month, range: [1, 12] },
219
+ { field: 'dayOfWeek', value: dayOfWeek, range: [0, 7] }
220
+ ];
221
+
222
+ for (const v of validations) {
223
+ const result = validateCronField(v.value, v.range);
224
+ if (!result.valid) {
225
+ return { valid: false, error: `Invalid ${v.field}: ${result.error}` };
226
+ }
227
+ }
228
+
229
+ return {
230
+ valid: true,
231
+ description: describeCronExpression(expression),
232
+ nextExecutions: getNextCronExecutions(expression, 5)
233
+ };
234
+ }
235
+
236
+ // Get human-readable description
237
+ function describeCronExpression(expression: string): string {
238
+ // Common patterns
239
+ const patterns: Record<string, string> = {
240
+ '* * * * *': 'Every minute',
241
+ '*/5 * * * *': 'Every 5 minutes',
242
+ '0 * * * *': 'Every hour',
243
+ '0 0 * * *': 'Every day at midnight',
244
+ '0 9 * * 1-5': 'Weekdays at 9:00 AM',
245
+ '0 0 1 * *': 'First day of every month',
246
+ '0 0 * * 0': 'Every Sunday at midnight'
247
+ };
248
+
249
+ return patterns[expression] || 'Custom schedule';
250
+ }
251
+
252
+ // Calculate next execution times
253
+ function getNextCronExecutions(expression: string, count: number): Date[] {
254
+ const executions: Date[] = [];
255
+ let current = new Date();
256
+
257
+ // Simple implementation - use cron-parser library in production
258
+ for (let i = 0; i < count; i++) {
259
+ const next = calculateNextCronExecution(expression, current);
260
+ executions.push(next);
261
+ current = new Date(next.getTime() + 60000); // Move past this execution
262
+ }
263
+
264
+ return executions;
265
+ }
266
+ ```
267
+
268
+ ### Schedule Reliability Testing
269
+
270
+ ```typescript
271
+ // Test schedule trigger reliability
272
+ async function testScheduleReliability(triggerId: string, testDuration: number): Promise<ScheduleTestResult> {
273
+ const startTime = Date.now();
274
+ const expectedExecutions: Date[] = [];
275
+ const actualExecutions: Date[] = [];
276
+
277
+ // Calculate expected execution times
278
+ const cronExpression = await getTriggerCronExpression(triggerId);
279
+ let checkTime = new Date(startTime);
280
+ while (checkTime.getTime() < startTime + testDuration) {
281
+ const nextExec = calculateNextCronExecution(cronExpression, checkTime);
282
+ if (nextExec.getTime() < startTime + testDuration) {
283
+ expectedExecutions.push(nextExec);
284
+ }
285
+ checkTime = new Date(nextExec.getTime() + 60000);
286
+ }
287
+
288
+ // Monitor actual executions
289
+ const executionListener = onExecutionStart(triggerId, (exec) => {
290
+ actualExecutions.push(new Date(exec.startedAt));
291
+ });
292
+
293
+ // Wait for test duration
294
+ await sleep(testDuration);
295
+ executionListener.stop();
296
+
297
+ // Compare expected vs actual
298
+ const comparison = compareExecutions(expectedExecutions, actualExecutions);
299
+
300
+ return {
301
+ testDuration,
302
+ expectedCount: expectedExecutions.length,
303
+ actualCount: actualExecutions.length,
304
+ missedExecutions: comparison.missed,
305
+ extraExecutions: comparison.extra,
306
+ timingAccuracy: comparison.timingAccuracy,
307
+ reliability: (actualExecutions.length / expectedExecutions.length) * 100
308
+ };
309
+ }
310
+ ```
311
+
312
+ ---
313
+
314
+ ## Polling Trigger Testing
315
+
316
+ ```typescript
317
+ // Test polling trigger behavior
318
+ async function testPollingTrigger(triggerId: string, testConfig: PollingTestConfig): Promise<PollingTestResult> {
319
+ const { interval, testDuration, simulateDataChanges } = testConfig;
320
+
321
+ const pollEvents: PollEvent[] = [];
322
+ const triggeredExecutions: Execution[] = [];
323
+
324
+ // Monitor polling events
325
+ const pollListener = onPoll(triggerId, (event) => {
326
+ pollEvents.push({
327
+ timestamp: new Date(),
328
+ dataFound: event.hasNewData,
329
+ itemCount: event.items?.length || 0
330
+ });
331
+ });
332
+
333
+ // Monitor triggered executions
334
+ const execListener = onExecutionStart(triggerId, (exec) => {
335
+ triggeredExecutions.push(exec);
336
+ });
337
+
338
+ // Optionally simulate data changes
339
+ if (simulateDataChanges) {
340
+ for (const change of simulateDataChanges) {
341
+ setTimeout(() => {
342
+ injectTestData(triggerId, change.data);
343
+ }, change.at);
344
+ }
345
+ }
346
+
347
+ // Wait for test duration
348
+ await sleep(testDuration);
349
+
350
+ pollListener.stop();
351
+ execListener.stop();
352
+
353
+ // Analyze results
354
+ const expectedPolls = Math.floor(testDuration / interval);
355
+ const actualPolls = pollEvents.length;
356
+
357
+ return {
358
+ interval,
359
+ testDuration,
360
+ expectedPolls,
361
+ actualPolls,
362
+ pollAccuracy: (actualPolls / expectedPolls) * 100,
363
+ averageInterval: calculateAverageInterval(pollEvents),
364
+ executionsTriggered: triggeredExecutions.length,
365
+ deduplicationWorking: checkDeduplication(triggeredExecutions),
366
+ pollEvents
367
+ };
368
+ }
369
+
370
+ // Check if deduplication is working
371
+ function checkDeduplication(executions: Execution[]): boolean {
372
+ const processedIds = new Set();
373
+
374
+ for (const exec of executions) {
375
+ const itemIds = exec.data?.resultData?.runData?.Trigger?.[0]?.data?.main?.[0]
376
+ ?.map(item => item.json?.id);
377
+
378
+ if (itemIds) {
379
+ for (const id of itemIds) {
380
+ if (processedIds.has(id)) {
381
+ return false; // Duplicate found
382
+ }
383
+ processedIds.add(id);
384
+ }
385
+ }
386
+ }
387
+
388
+ return true;
389
+ }
390
+ ```
391
+
392
+ ---
393
+
394
+ ## Event Trigger Testing
395
+
396
+ ```typescript
397
+ // Test event-driven triggers
398
+ async function testEventTrigger(triggerId: string, eventConfig: EventTestConfig): Promise<EventTestResult> {
399
+ const { eventType, testEvents, timeout } = eventConfig;
400
+
401
+ const results: EventResult[] = [];
402
+
403
+ for (const testEvent of testEvents) {
404
+ // Emit test event
405
+ const startTime = Date.now();
406
+ await emitTestEvent(eventType, testEvent.payload);
407
+
408
+ // Wait for trigger
409
+ try {
410
+ const execution = await waitForTrigger(triggerId, timeout);
411
+
412
+ results.push({
413
+ eventType: testEvent.type,
414
+ triggered: true,
415
+ latency: Date.now() - startTime,
416
+ payloadReceived: execution.data?.inputData
417
+ });
418
+ } catch (error) {
419
+ results.push({
420
+ eventType: testEvent.type,
421
+ triggered: false,
422
+ error: error.message
423
+ });
424
+ }
425
+ }
426
+
427
+ return {
428
+ eventType,
429
+ testsRun: testEvents.length,
430
+ triggered: results.filter(r => r.triggered).length,
431
+ averageLatency: average(results.filter(r => r.triggered).map(r => r.latency)),
432
+ results
433
+ };
434
+ }
435
+ ```
436
+
437
+ ---
438
+
439
+ ## Trigger Response Testing
440
+
441
+ ```typescript
442
+ // Test trigger response modes
443
+ async function testTriggerResponses(webhookUrl: string): Promise<ResponseTestResult> {
444
+ // Test immediate response
445
+ const immediateStart = Date.now();
446
+ const immediateResponse = await fetch(webhookUrl, {
447
+ method: 'POST',
448
+ headers: { 'Content-Type': 'application/json' },
449
+ body: '{"test": "immediate"}'
450
+ });
451
+ const immediateTime = Date.now() - immediateStart;
452
+
453
+ // Test with workflow execution
454
+ const workflowStart = Date.now();
455
+ const workflowResponse = await fetch(`${webhookUrl}?waitForResponse=true`, {
456
+ method: 'POST',
457
+ headers: { 'Content-Type': 'application/json' },
458
+ body: '{"test": "workflow"}'
459
+ });
460
+ const workflowTime = Date.now() - workflowStart;
461
+
462
+ return {
463
+ immediateResponse: {
464
+ status: immediateResponse.status,
465
+ time: immediateTime,
466
+ body: await immediateResponse.text()
467
+ },
468
+ workflowResponse: {
469
+ status: workflowResponse.status,
470
+ time: workflowTime,
471
+ body: await workflowResponse.text()
472
+ },
473
+ responseMode: workflowTime > immediateTime + 100 ? 'workflow' : 'immediate'
474
+ };
475
+ }
476
+ ```
477
+
478
+ ---
479
+
480
+ ## Test Scenarios
481
+
482
+ ```yaml
483
+ Webhook Scenarios:
484
+ - name: Valid JSON POST
485
+ method: POST
486
+ payload: {"event": "test"}
487
+ expected: 200 OK
488
+
489
+ - name: Invalid JSON
490
+ method: POST
491
+ payload: "not valid json"
492
+ expected: 400 Bad Request
493
+
494
+ - name: Missing auth
495
+ method: POST
496
+ headers: {}
497
+ expected: 401 Unauthorized
498
+
499
+ - name: Large payload
500
+ method: POST
501
+ payload: [10MB of data]
502
+ expected: 413 Payload Too Large
503
+
504
+ Schedule Scenarios:
505
+ - name: Every 5 minutes
506
+ cron: "*/5 * * * *"
507
+ verify: 12 executions per hour
508
+
509
+ - name: Weekdays at 9 AM
510
+ cron: "0 9 * * 1-5"
511
+ verify: 5 executions per week
512
+
513
+ Polling Scenarios:
514
+ - name: 1 minute interval
515
+ interval: 60000
516
+ verify: ~60 polls per hour
517
+
518
+ - name: Deduplication
519
+ interval: 60000
520
+ inject_duplicate: true
521
+ verify: No duplicate processing
522
+ ```
523
+
524
+ ---
525
+
526
+ ## Related Skills
527
+ - [n8n-workflow-testing-fundamentals](../n8n-workflow-testing-fundamentals/)
528
+ - [n8n-integration-testing-patterns](../n8n-integration-testing-patterns/)
529
+ - [n8n-security-testing](../n8n-security-testing/)
530
+
531
+ ---
532
+
533
+ ## Remember
534
+
535
+ **n8n triggers are the entry points** to workflows. Testing requires:
536
+ - Webhook: Payload handling, auth, HTTP methods
537
+ - Schedule: Cron accuracy, timezone handling
538
+ - Polling: Interval accuracy, deduplication
539
+ - Event: Event handling, filtering
540
+
541
+ **Key patterns:** Test with various payloads (valid, invalid, edge cases). Verify authentication enforcement. Check response times and reliability over time.