agentic-qe 2.5.5 → 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 (168) 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 +111 -0
  22. package/README.md +7 -4
  23. package/dist/adapters/MemoryStoreAdapter.d.ts +75 -123
  24. package/dist/adapters/MemoryStoreAdapter.d.ts.map +1 -1
  25. package/dist/adapters/MemoryStoreAdapter.js +204 -219
  26. package/dist/adapters/MemoryStoreAdapter.js.map +1 -1
  27. package/dist/agents/AccessibilityAllyAgent.d.ts.map +1 -1
  28. package/dist/agents/AccessibilityAllyAgent.js +17 -1
  29. package/dist/agents/AccessibilityAllyAgent.js.map +1 -1
  30. package/dist/agents/BaseAgent.d.ts +18 -250
  31. package/dist/agents/BaseAgent.d.ts.map +1 -1
  32. package/dist/agents/BaseAgent.js +122 -520
  33. package/dist/agents/BaseAgent.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/agents/utils/generators.d.ts +30 -0
  135. package/dist/agents/utils/generators.d.ts.map +1 -0
  136. package/dist/agents/utils/generators.js +44 -0
  137. package/dist/agents/utils/generators.js.map +1 -0
  138. package/dist/agents/utils/index.d.ts +10 -0
  139. package/dist/agents/utils/index.d.ts.map +1 -0
  140. package/dist/agents/utils/index.js +19 -0
  141. package/dist/agents/utils/index.js.map +1 -0
  142. package/dist/agents/utils/validation.d.ts +72 -0
  143. package/dist/agents/utils/validation.d.ts.map +1 -0
  144. package/dist/agents/utils/validation.js +75 -0
  145. package/dist/agents/utils/validation.js.map +1 -0
  146. package/dist/cli/init/agents.d.ts.map +1 -1
  147. package/dist/cli/init/agents.js +29 -0
  148. package/dist/cli/init/agents.js.map +1 -1
  149. package/dist/cli/init/skills.d.ts.map +1 -1
  150. package/dist/cli/init/skills.js +7 -1
  151. package/dist/cli/init/skills.js.map +1 -1
  152. package/dist/core/memory/HNSWVectorMemory.js +1 -1
  153. package/dist/core/memory/SwarmMemoryManager.d.ts +114 -90
  154. package/dist/core/memory/SwarmMemoryManager.d.ts.map +1 -1
  155. package/dist/core/memory/SwarmMemoryManager.js +277 -235
  156. package/dist/core/memory/SwarmMemoryManager.js.map +1 -1
  157. package/dist/learning/baselines/StandardTaskSuite.d.ts.map +1 -1
  158. package/dist/learning/baselines/StandardTaskSuite.js +38 -0
  159. package/dist/learning/baselines/StandardTaskSuite.js.map +1 -1
  160. package/dist/mcp/server-instructions.d.ts +1 -1
  161. package/dist/mcp/server-instructions.js +1 -1
  162. package/dist/types/memory-interfaces.d.ts +76 -68
  163. package/dist/types/memory-interfaces.d.ts.map +1 -1
  164. package/dist/types/memory-interfaces.js +3 -0
  165. package/dist/types/memory-interfaces.js.map +1 -1
  166. package/docs/reference/agents.md +91 -2
  167. package/docs/reference/skills.md +97 -2
  168. package/package.json +2 -2
@@ -0,0 +1,540 @@
1
+ ---
2
+ name: n8n-integration-testing-patterns
3
+ description: "API contract testing, authentication flows, rate limit handling, and error scenario coverage for n8n integrations with external services. Use when testing n8n node integrations."
4
+ category: n8n-testing
5
+ priority: high
6
+ tokenEstimate: 1100
7
+ agents: [n8n-integration-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, integration, api, authentication, oauth, rate-limiting, testing]
14
+ ---
15
+
16
+ # n8n Integration Testing Patterns
17
+
18
+ <default_to_action>
19
+ When testing n8n integrations:
20
+ 1. VERIFY connectivity and authentication
21
+ 2. TEST all configured operations
22
+ 3. VALIDATE API response handling
23
+ 4. CHECK rate limit behavior
24
+ 5. CONFIRM error handling works
25
+
26
+ **Quick Integration Checklist:**
27
+ - Credentials valid and not expired
28
+ - API permissions sufficient for operations
29
+ - Rate limits understood and respected
30
+ - Error responses properly handled
31
+ - Data formats match API expectations
32
+
33
+ **Critical Success Factors:**
34
+ - Test in isolation before workflow integration
35
+ - Verify OAuth token refresh works
36
+ - Check API version compatibility
37
+ - Monitor rate limit headers
38
+ </default_to_action>
39
+
40
+ ## Quick Reference Card
41
+
42
+ ### Common n8n Integrations
43
+
44
+ | Category | Services | Auth Type |
45
+ |----------|----------|-----------|
46
+ | **Communication** | Slack, Teams, Discord | OAuth2, Webhook |
47
+ | **Data Storage** | Google Sheets, Airtable | OAuth2, API Key |
48
+ | **CRM** | Salesforce, HubSpot | OAuth2 |
49
+ | **Dev Tools** | GitHub, Jira, Linear | OAuth2, API Key |
50
+ | **Marketing** | Mailchimp, SendGrid | API Key |
51
+
52
+ ### Authentication Types
53
+
54
+ | Type | Setup | Refresh |
55
+ |------|-------|---------|
56
+ | **OAuth2** | User authorization flow | Automatic token refresh |
57
+ | **API Key** | Manual key entry | Manual rotation |
58
+ | **Basic Auth** | Username/password | No refresh needed |
59
+ | **Header Auth** | Custom header | Manual rotation |
60
+
61
+ ---
62
+
63
+ ## Connectivity Testing
64
+
65
+ ```typescript
66
+ // Test integration connectivity
67
+ async function testIntegrationConnectivity(nodeName: string): Promise<ConnectivityResult> {
68
+ const node = await getNodeConfig(nodeName);
69
+
70
+ // Check credential exists
71
+ if (!node.credentials) {
72
+ return { connected: false, error: 'No credentials configured' };
73
+ }
74
+
75
+ // Test based on integration type
76
+ switch (getIntegrationType(node.type)) {
77
+ case 'slack':
78
+ return await testSlackConnectivity(node.credentials);
79
+ case 'google-sheets':
80
+ return await testGoogleSheetsConnectivity(node.credentials);
81
+ case 'jira':
82
+ return await testJiraConnectivity(node.credentials);
83
+ case 'github':
84
+ return await testGitHubConnectivity(node.credentials);
85
+ default:
86
+ return await testGenericAPIConnectivity(node);
87
+ }
88
+ }
89
+
90
+ // Slack connectivity test
91
+ async function testSlackConnectivity(credentials: any): Promise<ConnectivityResult> {
92
+ try {
93
+ const response = await fetch('https://slack.com/api/auth.test', {
94
+ headers: { 'Authorization': `Bearer ${credentials.accessToken}` }
95
+ });
96
+ const data = await response.json();
97
+
98
+ return {
99
+ connected: data.ok,
100
+ workspace: data.team,
101
+ user: data.user,
102
+ scopes: data.response_metadata?.scopes || []
103
+ };
104
+ } catch (error) {
105
+ return { connected: false, error: error.message };
106
+ }
107
+ }
108
+
109
+ // Google Sheets connectivity test
110
+ async function testGoogleSheetsConnectivity(credentials: any): Promise<ConnectivityResult> {
111
+ try {
112
+ const response = await fetch('https://www.googleapis.com/drive/v3/about?fields=user', {
113
+ headers: { 'Authorization': `Bearer ${credentials.accessToken}` }
114
+ });
115
+
116
+ if (response.status === 401) {
117
+ // Try refresh
118
+ const refreshed = await refreshOAuthToken(credentials);
119
+ if (refreshed) {
120
+ return testGoogleSheetsConnectivity({ ...credentials, accessToken: refreshed });
121
+ }
122
+ return { connected: false, error: 'Token expired, refresh failed' };
123
+ }
124
+
125
+ const data = await response.json();
126
+ return { connected: true, user: data.user };
127
+ } catch (error) {
128
+ return { connected: false, error: error.message };
129
+ }
130
+ }
131
+ ```
132
+
133
+ ---
134
+
135
+ ## API Operation Testing
136
+
137
+ ```typescript
138
+ // Test integration operations
139
+ async function testIntegrationOperations(nodeName: string): Promise<OperationResult[]> {
140
+ const node = await getNodeConfig(nodeName);
141
+ const operations = getNodeOperations(node.type);
142
+ const results: OperationResult[] = [];
143
+
144
+ for (const operation of operations) {
145
+ const testData = generateTestData(node.type, operation);
146
+
147
+ try {
148
+ const startTime = Date.now();
149
+ const response = await executeOperation(node, operation, testData);
150
+
151
+ results.push({
152
+ operation,
153
+ success: true,
154
+ responseTime: Date.now() - startTime,
155
+ responseStatus: response.status,
156
+ dataValid: validateResponseData(response.data, operation)
157
+ });
158
+ } catch (error) {
159
+ results.push({
160
+ operation,
161
+ success: false,
162
+ error: error.message,
163
+ errorType: classifyError(error)
164
+ });
165
+ }
166
+ }
167
+
168
+ return results;
169
+ }
170
+
171
+ // Generate test data for operations
172
+ function generateTestData(nodeType: string, operation: string): any {
173
+ const testDataMap = {
174
+ 'slack': {
175
+ 'postMessage': {
176
+ channel: 'C123456',
177
+ text: 'Test message from n8n integration test'
178
+ },
179
+ 'uploadFile': {
180
+ channels: 'C123456',
181
+ content: 'Test file content',
182
+ filename: 'test.txt'
183
+ }
184
+ },
185
+ 'google-sheets': {
186
+ 'appendData': {
187
+ spreadsheetId: 'test-spreadsheet-id',
188
+ range: 'Sheet1!A:Z',
189
+ values: [['Test', 'Data', new Date().toISOString()]]
190
+ },
191
+ 'readRows': {
192
+ spreadsheetId: 'test-spreadsheet-id',
193
+ range: 'Sheet1!A1:Z10'
194
+ }
195
+ },
196
+ 'jira': {
197
+ 'createIssue': {
198
+ project: 'TEST',
199
+ issueType: 'Task',
200
+ summary: 'Test issue from n8n',
201
+ description: 'Created by integration test'
202
+ },
203
+ 'updateIssue': {
204
+ issueKey: 'TEST-1',
205
+ fields: { summary: 'Updated by n8n test' }
206
+ }
207
+ }
208
+ };
209
+
210
+ return testDataMap[nodeType]?.[operation] || {};
211
+ }
212
+ ```
213
+
214
+ ---
215
+
216
+ ## Authentication Testing
217
+
218
+ ### OAuth2 Flow Testing
219
+
220
+ ```typescript
221
+ // Test OAuth2 authentication
222
+ async function testOAuth2Authentication(credentials: any): Promise<OAuth2Result> {
223
+ const result: OAuth2Result = {
224
+ tokenValid: false,
225
+ refreshWorking: false,
226
+ scopes: [],
227
+ expiresIn: 0
228
+ };
229
+
230
+ // Test current token
231
+ const tokenTest = await testAccessToken(credentials.accessToken);
232
+ result.tokenValid = tokenTest.valid;
233
+ result.scopes = tokenTest.scopes;
234
+
235
+ // Check expiration
236
+ if (credentials.expiresAt) {
237
+ result.expiresIn = new Date(credentials.expiresAt).getTime() - Date.now();
238
+ result.expiresSoon = result.expiresIn < 3600000; // Less than 1 hour
239
+ }
240
+
241
+ // Test refresh token
242
+ if (credentials.refreshToken) {
243
+ try {
244
+ const newToken = await refreshOAuthToken(credentials);
245
+ result.refreshWorking = !!newToken;
246
+ } catch (error) {
247
+ result.refreshError = error.message;
248
+ }
249
+ }
250
+
251
+ return result;
252
+ }
253
+
254
+ // Test required scopes
255
+ async function testRequiredScopes(credentials: any, requiredScopes: string[]): Promise<ScopeResult> {
256
+ const currentScopes = await getTokenScopes(credentials.accessToken);
257
+ const missingScopes = requiredScopes.filter(s => !currentScopes.includes(s));
258
+
259
+ return {
260
+ hasAllScopes: missingScopes.length === 0,
261
+ currentScopes,
262
+ missingScopes,
263
+ recommendation: missingScopes.length > 0
264
+ ? `Re-authorize with scopes: ${missingScopes.join(', ')}`
265
+ : null
266
+ };
267
+ }
268
+ ```
269
+
270
+ ### API Key Testing
271
+
272
+ ```typescript
273
+ // Test API key validity
274
+ async function testAPIKey(integration: string, apiKey: string): Promise<APIKeyResult> {
275
+ const endpoints = {
276
+ 'sendgrid': 'https://api.sendgrid.com/v3/user/profile',
277
+ 'mailchimp': 'https://us1.api.mailchimp.com/3.0/ping',
278
+ 'airtable': 'https://api.airtable.com/v0/meta/whoami'
279
+ };
280
+
281
+ const endpoint = endpoints[integration];
282
+ if (!endpoint) {
283
+ return { valid: false, error: 'Unknown integration' };
284
+ }
285
+
286
+ try {
287
+ const response = await fetch(endpoint, {
288
+ headers: { 'Authorization': `Bearer ${apiKey}` }
289
+ });
290
+
291
+ return {
292
+ valid: response.status === 200,
293
+ status: response.status,
294
+ rateLimit: extractRateLimitInfo(response.headers)
295
+ };
296
+ } catch (error) {
297
+ return { valid: false, error: error.message };
298
+ }
299
+ }
300
+ ```
301
+
302
+ ---
303
+
304
+ ## Rate Limit Testing
305
+
306
+ ```typescript
307
+ // Test rate limit handling
308
+ async function testRateLimits(nodeName: string, requestCount: number): Promise<RateLimitResult> {
309
+ const results: RequestResult[] = [];
310
+ let rateLimitHit = false;
311
+ let retryAfter = 0;
312
+
313
+ for (let i = 0; i < requestCount; i++) {
314
+ const startTime = Date.now();
315
+ const response = await makeRequest(nodeName);
316
+
317
+ results.push({
318
+ requestNumber: i + 1,
319
+ status: response.status,
320
+ responseTime: Date.now() - startTime,
321
+ rateLimitRemaining: response.headers['x-ratelimit-remaining'],
322
+ rateLimitLimit: response.headers['x-ratelimit-limit']
323
+ });
324
+
325
+ if (response.status === 429) {
326
+ rateLimitHit = true;
327
+ retryAfter = parseInt(response.headers['retry-after'] || '60');
328
+ break;
329
+ }
330
+
331
+ // Small delay between requests
332
+ await sleep(100);
333
+ }
334
+
335
+ return {
336
+ requestsMade: results.length,
337
+ rateLimitHit,
338
+ retryAfter,
339
+ results,
340
+ recommendation: rateLimitHit
341
+ ? `Implement exponential backoff, retry after ${retryAfter}s`
342
+ : 'Rate limit not reached, consider increasing request count for thorough testing'
343
+ };
344
+ }
345
+
346
+ // Extract rate limit info from headers
347
+ function extractRateLimitInfo(headers: Headers): RateLimitInfo {
348
+ return {
349
+ limit: headers.get('x-ratelimit-limit'),
350
+ remaining: headers.get('x-ratelimit-remaining'),
351
+ reset: headers.get('x-ratelimit-reset'),
352
+ retryAfter: headers.get('retry-after')
353
+ };
354
+ }
355
+ ```
356
+
357
+ ---
358
+
359
+ ## Error Handling Testing
360
+
361
+ ```typescript
362
+ // Test error scenarios
363
+ async function testErrorScenarios(nodeName: string): Promise<ErrorTestResult[]> {
364
+ const scenarios = [
365
+ { name: 'Invalid credentials', modify: { credentials: null } },
366
+ { name: 'Invalid endpoint', modify: { url: 'https://invalid.example.com' } },
367
+ { name: 'Timeout', modify: { timeout: 1 } },
368
+ { name: 'Invalid data', modify: { data: { invalid: true } } },
369
+ { name: 'Not found', modify: { resourceId: 'nonexistent-123' } },
370
+ { name: 'Permission denied', modify: { scope: 'read-only' } }
371
+ ];
372
+
373
+ const results: ErrorTestResult[] = [];
374
+
375
+ for (const scenario of scenarios) {
376
+ try {
377
+ const response = await executeWithModification(nodeName, scenario.modify);
378
+
379
+ results.push({
380
+ scenario: scenario.name,
381
+ errorHandled: response.status >= 400,
382
+ errorCode: response.status,
383
+ errorMessage: response.data?.error?.message,
384
+ retried: response.metadata?.retryCount > 0
385
+ });
386
+ } catch (error) {
387
+ results.push({
388
+ scenario: scenario.name,
389
+ errorHandled: true,
390
+ exceptionThrown: true,
391
+ errorType: error.constructor.name,
392
+ errorMessage: error.message
393
+ });
394
+ }
395
+ }
396
+
397
+ return results;
398
+ }
399
+
400
+ // Classify error types
401
+ function classifyError(error: any): string {
402
+ if (error.status === 401 || error.status === 403) return 'authentication';
403
+ if (error.status === 404) return 'not-found';
404
+ if (error.status === 429) return 'rate-limit';
405
+ if (error.status >= 500) return 'server-error';
406
+ if (error.code === 'ETIMEDOUT') return 'timeout';
407
+ if (error.code === 'ECONNREFUSED') return 'connection';
408
+ return 'unknown';
409
+ }
410
+ ```
411
+
412
+ ---
413
+
414
+ ## Integration-Specific Patterns
415
+
416
+ ### Slack Integration
417
+
418
+ ```typescript
419
+ const slackTestPatterns = {
420
+ // Test message posting
421
+ testPostMessage: async (credentials) => {
422
+ return await fetch('https://slack.com/api/chat.postMessage', {
423
+ method: 'POST',
424
+ headers: {
425
+ 'Authorization': `Bearer ${credentials.accessToken}`,
426
+ 'Content-Type': 'application/json'
427
+ },
428
+ body: JSON.stringify({
429
+ channel: 'C123456',
430
+ text: 'Integration test message'
431
+ })
432
+ });
433
+ },
434
+
435
+ // Test file upload
436
+ testFileUpload: async (credentials) => {
437
+ const formData = new FormData();
438
+ formData.append('channels', 'C123456');
439
+ formData.append('content', 'Test file content');
440
+ formData.append('filename', 'test.txt');
441
+
442
+ return await fetch('https://slack.com/api/files.upload', {
443
+ method: 'POST',
444
+ headers: { 'Authorization': `Bearer ${credentials.accessToken}` },
445
+ body: formData
446
+ });
447
+ },
448
+
449
+ // Validate required scopes
450
+ requiredScopes: ['chat:write', 'files:write', 'channels:read']
451
+ };
452
+ ```
453
+
454
+ ### Google Sheets Integration
455
+
456
+ ```typescript
457
+ const googleSheetsTestPatterns = {
458
+ // Test read operation
459
+ testReadRows: async (credentials, spreadsheetId) => {
460
+ return await fetch(
461
+ `https://sheets.googleapis.com/v4/spreadsheets/${spreadsheetId}/values/Sheet1!A1:Z10`,
462
+ { headers: { 'Authorization': `Bearer ${credentials.accessToken}` } }
463
+ );
464
+ },
465
+
466
+ // Test append operation
467
+ testAppendRow: async (credentials, spreadsheetId, values) => {
468
+ return await fetch(
469
+ `https://sheets.googleapis.com/v4/spreadsheets/${spreadsheetId}/values/Sheet1!A:Z:append?valueInputOption=USER_ENTERED`,
470
+ {
471
+ method: 'POST',
472
+ headers: {
473
+ 'Authorization': `Bearer ${credentials.accessToken}`,
474
+ 'Content-Type': 'application/json'
475
+ },
476
+ body: JSON.stringify({ values: [values] })
477
+ }
478
+ );
479
+ },
480
+
481
+ // Required scopes
482
+ requiredScopes: ['https://www.googleapis.com/auth/spreadsheets']
483
+ };
484
+ ```
485
+
486
+ ---
487
+
488
+ ## Test Report Template
489
+
490
+ ```markdown
491
+ # Integration Test Report
492
+
493
+ ## Summary
494
+ | Integration | Status | Auth | Operations | Errors |
495
+ |-------------|--------|------|------------|--------|
496
+ | Slack | PASS | OK | 4/4 | 0 |
497
+ | Google Sheets | WARN | Expiring | 3/3 | 0 |
498
+ | Jira | FAIL | OK | 2/4 | 2 |
499
+
500
+ ## Authentication Status
501
+ - Slack: OAuth2 valid, expires in 28 days
502
+ - Google Sheets: OAuth2 expires in 2 hours - REFRESH RECOMMENDED
503
+ - Jira: API Key valid
504
+
505
+ ## Rate Limit Status
506
+ | Integration | Limit | Used | Remaining |
507
+ |-------------|-------|------|-----------|
508
+ | Slack | 50/min | 12 | 38 |
509
+ | Google Sheets | 100/min | 45 | 55 |
510
+ | Jira | 100/min | 8 | 92 |
511
+
512
+ ## Failed Operations
513
+ ### Jira: Transition Issue
514
+ - Error: Invalid transition for current state
515
+ - Fix: Check workflow transitions in Jira
516
+
517
+ ## Recommendations
518
+ 1. Refresh Google Sheets OAuth token before expiration
519
+ 2. Fix Jira workflow transition logic
520
+ ```
521
+
522
+ ---
523
+
524
+ ## Related Skills
525
+ - [n8n-workflow-testing-fundamentals](../n8n-workflow-testing-fundamentals/)
526
+ - [n8n-security-testing](../n8n-security-testing/)
527
+ - [api-testing-patterns](../api-testing-patterns/)
528
+
529
+ ---
530
+
531
+ ## Remember
532
+
533
+ **n8n integrates with 400+ services**, each with unique authentication, rate limits, and API quirks. Testing requires:
534
+ - Connectivity verification
535
+ - Authentication validation (OAuth refresh, API key expiry)
536
+ - Operation testing with realistic data
537
+ - Rate limit awareness
538
+ - Error handling verification
539
+
540
+ **With Agents:** Use n8n-integration-test for comprehensive integration testing. Coordinate with n8n-workflow-executor to test integrations in context.