Complete implementation of Phase 1 foundation for n8n API integration tests. Establishes core utilities, fixtures, and infrastructure for testing all 17 n8n API handlers against real n8n instance. Changes: - Add integration test environment configuration to .env.example - Create comprehensive test utilities infrastructure: * credentials.ts: Environment-aware credential management (local .env vs CI secrets) * n8n-client.ts: Singleton API client wrapper with health checks * test-context.ts: Resource tracking and automatic cleanup * cleanup-helpers.ts: Multi-level cleanup strategies (orphaned, age-based, tag-based) * fixtures.ts: 6 pre-built workflow templates (webhook, HTTP, multi-node, error handling, AI, expressions) * factories.ts: Dynamic node/workflow builders with 15+ factory functions * webhook-workflows.ts: Webhook workflow configs and setup instructions - Add npm scripts: * test:integration:n8n: Run n8n API integration tests * test:cleanup:orphans: Clean up orphaned test resources - Create cleanup script for CI/manual use Documentation: - Add comprehensive integration testing plan (550 lines) - Add Phase 1 completion summary with lessons learned Key Features: - Automatic credential detection (CI vs local) - Multi-level cleanup (test, suite, CI, orphan) - 6 workflow fixtures covering common scenarios - 15+ factory functions for dynamic test data - Support for 4 HTTP methods (GET, POST, PUT, DELETE) via pre-activated webhook workflows - TypeScript-first with full type safety - Comprehensive error handling with helpful messages Total: ~1,520 lines of production-ready code + 650 lines of documentation Ready for Phase 2: Workflow creation tests 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
27 KiB
Comprehensive Integration Testing Plan
Overview
Transform the test suite to test all 17 n8n API handlers against a real n8n instance instead of mocks. This plan ensures 100% coverage of every tool, operation, and parameter combination to prevent bugs like the P0 workflow creation issue from slipping through.
Critical Requirements
-
Credentials:
- Local development: Read from
.envfile - CI/GitHub Actions: Use GitHub secrets (
N8N_URL,N8N_API_KEY)
- Local development: Read from
-
Pre-activated Webhook Workflows:
- n8n API doesn't support workflow activation via API
- Need pre-created, activated workflows for webhook testing
- Store workflow IDs in
.env:N8N_TEST_WEBHOOK_GET_ID- Webhook with GET methodN8N_TEST_WEBHOOK_POST_ID- Webhook with POST methodN8N_TEST_WEBHOOK_PUT_ID- Webhook with PUT methodN8N_TEST_WEBHOOK_DELETE_ID- Webhook with DELETE method
-
100% Coverage Goal: Test EVERY tool, EVERY operation, EVERY parameter combination
Complete Test Coverage Matrix
Total Test Scenarios: ~150+
Workflow Management (10 handlers)
1. handleCreateWorkflow - 10+ scenarios
- Create workflow with base nodes (webhook, httpRequest, set)
- Create workflow with langchain nodes (agent, aiChain)
- Invalid node types (error handling)
- Complex multi-node workflows
- Complex connection patterns
- P0 Bug Verification: SHORT vs FULL node type handling
- Missing required parameters
- Duplicate node names
- Invalid connection references
- Settings variations
2. handleGetWorkflow - 3 scenarios
- Successful retrieval
- Not found (invalid ID)
- Malformed ID
3. handleGetWorkflowDetails - 4 scenarios
- Basic workflow
- Workflow with metadata
- Workflow with version history
- Workflow with execution stats
4. handleGetWorkflowStructure - 2 scenarios
- Simple workflow
- Complex workflow (verify no parameter data)
5. handleGetWorkflowMinimal - 2 scenarios
- Active workflow
- Inactive workflow
6. handleUpdateWorkflow - 8+ scenarios
- Full workflow replacement
- Update nodes
- Update connections
- Update settings
- Update tags
- Validation errors
- Concurrent update conflicts
- Large workflow updates
7. handleUpdatePartialWorkflow - 30+ scenarios (15 operations × 2 paths)
Node Operations (12 scenarios):
addNode: Success, duplicate name, invalid type, missing positionremoveNode: By ID, by name, not found, with connection cleanupupdateNode: By ID, by name, invalid updates, nested parameter updatesmoveNode: Valid position, boundary positionsenableNode: Success, already enableddisableNode: Success, already disabled
Connection Operations (10 scenarios):
addConnection: Default ports, custom ports, invalid nodesremoveConnection: Success, not found, with ignoreErrorsupdateConnection: Change ports, change indicescleanStaleConnections: Dry run, actual cleanupreplaceConnections: Full replacement, validation
Metadata Operations (8 scenarios):
updateSettings: Timezone, execution order, error workflowupdateName: Valid, duplicate, emptyaddTag: New tag, existing tagremoveTag: Existing, non-existing
8. handleDeleteWorkflow - 3 scenarios
- Successful deletion
- Not found
- Verify cleanup (workflow actually deleted)
9. handleListWorkflows - 12+ scenarios
- No filters (all workflows)
- Filter by active status (true/false)
- Filter by tags (single, multiple)
- Filter by projectId (enterprise feature)
- Pagination: first page, next page, last page
- Pagination: cursor handling
- Exclude pinned data
- Limit variations (1, 50, 100)
- Empty results
- Sort order verification
10. handleValidateWorkflow - 16 scenarios (4 profiles × 4 validation types)
Validation Profiles:
strict: All validations enabled, strictest rulesruntime: Production-ready validationai-friendly: Relaxed rules for AI-generated workflowsminimal: Basic structure validation only
Validation Types (for each profile):
- All validations enabled (default)
- Nodes only (
validateNodes: true, others false) - Connections only (
validateConnections: true, others false) - Expressions only (
validateExpressions: true, others false)
11. handleAutofixWorkflow - 20+ scenarios
Fix Types (5):
expression-format: Fix{{}}syntax issuestypeversion-correction: Fix outdated typeVersionerror-output-config: Fix error output configurationnode-type-correction: Fix incorrect node typeswebhook-missing-path: Add missing webhook paths
Confidence Levels (3):
high: Only apply high-confidence fixesmedium: Apply high + medium confidence fixeslow: Apply all fixes
Test Matrix:
- Each fix type with preview mode (
applyFixes: false) - Each fix type with apply mode (
applyFixes: true) - Confidence threshold filtering
maxFixesparameter limiting- Multiple fix types in single workflow
- No fixes available scenario
Execution Management (4 handlers)
12. handleTriggerWebhookWorkflow - 16+ scenarios
HTTP Methods (4):
- GET: Query parameters, no data
- POST: JSON body, form data, headers
- PUT: Update data, custom headers
- DELETE: Query parameters, headers
Scenarios per method:
- Basic trigger (no data)
- With request data
- With custom headers
- Wait for response (true/false)
- Workflow not found
- Invalid webhook URL
13. handleGetExecution - 20+ scenarios
Execution Modes (4):
preview: Structure & counts only (no data)summary: 2 samples per node (default)filtered: Custom limits and node filtersfull: Complete execution data
Scenarios per mode:
- Successful execution
- Failed execution
- Running execution
- With input data (
includeInputData: true) - Node filters (
nodeNames: ['Node1', 'Node2']) - Item limits (
itemsLimit: 0, 2, 5, -1) - Not found
14. handleListExecutions - 10+ scenarios
- No filters (all executions)
- Filter by workflowId
- Filter by status (success, error, waiting)
- Filter by projectId
- Pagination: first page, next page, last page
- Include execution data (
includeData: true/false) - Limit variations (1, 50, 100)
- Empty results
15. handleDeleteExecution - 3 scenarios
- Successful deletion
- Not found
- Verify cleanup
System/Utility (3 handlers)
16. handleHealthCheck - 2 scenarios
- API available
- Feature availability check
17. handleListAvailableTools - 1 scenario
- List all tools
18. handleDiagnostic - 3 scenarios
- Basic diagnostic
- Verbose mode (
verbose: true) - Configuration display
Implementation Phases
Phase 1: Foundation (Branch: feat/integration-tests-foundation)
1.1 Environment Configuration
Update .env.example:
# ========================================
# INTEGRATION TESTING CONFIGURATION
# ========================================
# n8n API Configuration for Integration Tests
N8N_API_URL=http://localhost:5678
N8N_API_KEY=your-api-key-here
# Pre-activated Webhook Workflows for Testing
# Create these workflows manually in n8n and activate them
# Each workflow should have a single Webhook node with the specified HTTP method
N8N_TEST_WEBHOOK_GET_ID= # Webhook with GET method
N8N_TEST_WEBHOOK_POST_ID= # Webhook with POST method
N8N_TEST_WEBHOOK_PUT_ID= # Webhook with PUT method
N8N_TEST_WEBHOOK_DELETE_ID= # Webhook with DELETE method
# Test Configuration
N8N_TEST_CLEANUP_ENABLED=true # Enable automatic cleanup
N8N_TEST_TAG=mcp-integration-test # Tag for test workflows
N8N_TEST_NAME_PREFIX=[MCP-TEST] # Name prefix for test workflows
GitHub Secrets (for CI):
N8N_URL: n8n instance URLN8N_API_KEY: n8n API keyN8N_TEST_WEBHOOK_GET_ID: Pre-activated GET webhook workflow IDN8N_TEST_WEBHOOK_POST_ID: Pre-activated POST webhook workflow IDN8N_TEST_WEBHOOK_PUT_ID: Pre-activated PUT webhook workflow IDN8N_TEST_WEBHOOK_DELETE_ID: Pre-activated DELETE webhook workflow ID
1.2 Directory Structure
tests/integration/n8n-api/
├── workflows/
│ ├── create-workflow.test.ts (10+ scenarios)
│ ├── get-workflow.test.ts (3 scenarios)
│ ├── get-workflow-details.test.ts (4 scenarios)
│ ├── get-workflow-structure.test.ts (2 scenarios)
│ ├── get-workflow-minimal.test.ts (2 scenarios)
│ ├── update-workflow.test.ts (8+ scenarios)
│ ├── update-partial-workflow.test.ts (30+ scenarios - 15 operations)
│ ├── delete-workflow.test.ts (3 scenarios)
│ ├── list-workflows.test.ts (12+ scenarios)
│ ├── validate-workflow.test.ts (16 scenarios - 4 profiles × 4 types)
│ └── autofix-workflow.test.ts (20+ scenarios - 5 types × modes)
├── executions/
│ ├── trigger-webhook.test.ts (16+ scenarios - 4 methods)
│ ├── get-execution.test.ts (20+ scenarios - 4 modes)
│ ├── list-executions.test.ts (10+ scenarios)
│ └── delete-execution.test.ts (3 scenarios)
├── system/
│ ├── health-check.test.ts (2 scenarios)
│ ├── list-tools.test.ts (1 scenario)
│ └── diagnostic.test.ts (3 scenarios)
└── utils/
├── credentials.ts # Environment-aware credential loader
├── n8n-client.ts # Pre-configured API client
├── cleanup-helpers.ts # Multi-level cleanup
├── test-context.ts # Resource tracking
├── fixtures.ts # Reusable workflow templates
├── factories.ts # Test data generators
└── webhook-workflows.ts # Webhook workflow configurations
1.3 Core Utilities
credentials.ts - Environment-aware credential loader:
import dotenv from 'dotenv';
dotenv.config();
export interface N8nTestCredentials {
url: string;
apiKey: string;
webhookWorkflows: {
get: string;
post: string;
put: string;
delete: string;
};
cleanup: {
enabled: boolean;
tag: string;
namePrefix: string;
};
}
export function getN8nCredentials(): N8nTestCredentials {
if (process.env.CI) {
// CI: Use GitHub secrets
return {
url: process.env.N8N_URL!,
apiKey: process.env.N8N_API_KEY!,
webhookWorkflows: {
get: process.env.N8N_TEST_WEBHOOK_GET_ID!,
post: process.env.N8N_TEST_WEBHOOK_POST_ID!,
put: process.env.N8N_TEST_WEBHOOK_PUT_ID!,
delete: process.env.N8N_TEST_WEBHOOK_DELETE_ID!
},
cleanup: {
enabled: true,
tag: 'mcp-integration-test',
namePrefix: '[MCP-TEST]'
}
};
} else {
// Local: Use .env file
return {
url: process.env.N8N_API_URL!,
apiKey: process.env.N8N_API_KEY!,
webhookWorkflows: {
get: process.env.N8N_TEST_WEBHOOK_GET_ID || '',
post: process.env.N8N_TEST_WEBHOOK_POST_ID || '',
put: process.env.N8N_TEST_WEBHOOK_PUT_ID || '',
delete: process.env.N8N_TEST_WEBHOOK_DELETE_ID || ''
},
cleanup: {
enabled: process.env.N8N_TEST_CLEANUP_ENABLED !== 'false',
tag: process.env.N8N_TEST_TAG || 'mcp-integration-test',
namePrefix: process.env.N8N_TEST_NAME_PREFIX || '[MCP-TEST]'
}
};
}
}
export function validateCredentials(creds: N8nTestCredentials): void {
if (!creds.url) throw new Error('N8N_API_URL is required');
if (!creds.apiKey) throw new Error('N8N_API_KEY is required');
}
export function validateWebhookWorkflows(creds: N8nTestCredentials): void {
const missing: string[] = [];
if (!creds.webhookWorkflows.get) missing.push('GET');
if (!creds.webhookWorkflows.post) missing.push('POST');
if (!creds.webhookWorkflows.put) missing.push('PUT');
if (!creds.webhookWorkflows.delete) missing.push('DELETE');
if (missing.length > 0) {
throw new Error(
`Missing webhook workflow IDs for HTTP methods: ${missing.join(', ')}\n` +
`Please create and activate webhook workflows, then set:\n` +
missing.map(m => ` N8N_TEST_WEBHOOK_${m}_ID`).join('\n')
);
}
}
n8n-client.ts - Pre-configured API client wrapper:
import { N8nApiClient } from '../../../src/services/n8n-api-client';
import { getN8nCredentials } from './credentials';
let client: N8nApiClient | null = null;
export function getTestN8nClient(): N8nApiClient {
if (!client) {
const creds = getN8nCredentials();
client = new N8nApiClient(creds.url, creds.apiKey);
}
return client;
}
export function resetTestN8nClient(): void {
client = null;
}
test-context.ts - Resource tracking for cleanup:
import { getN8nCredentials } from './credentials';
export interface TestContext {
workflowIds: string[];
executionIds: string[];
cleanup: () => Promise<void>;
}
export function createTestContext(): TestContext {
const context: TestContext = {
workflowIds: [],
executionIds: [],
cleanup: async () => {
const creds = getN8nCredentials();
if (!creds.cleanup.enabled) return;
const client = getTestN8nClient();
// Delete executions first
for (const id of context.executionIds) {
try {
await client.deleteExecution(id);
} catch (error) {
console.warn(`Failed to delete execution ${id}:`, error);
}
}
// Then delete workflows
for (const id of context.workflowIds) {
try {
await client.deleteWorkflow(id);
} catch (error) {
console.warn(`Failed to delete workflow ${id}:`, error);
}
}
context.workflowIds = [];
context.executionIds = [];
}
};
return context;
}
cleanup-helpers.ts - Multi-level cleanup strategies:
import { N8nApiClient } from '../../../src/services/n8n-api-client';
import { getN8nCredentials, getTestN8nClient } from './credentials';
/**
* Clean up orphaned test workflows
* Run this periodically in CI to clean up failed test runs
*/
export async function cleanupOrphanedWorkflows(): Promise<void> {
const creds = getN8nCredentials();
const client = getTestN8nClient();
let allWorkflows: any[] = [];
let cursor: string | undefined;
// Fetch all workflows with pagination
do {
const response = await client.listWorkflows({ cursor, limit: 100 });
allWorkflows.push(...response.data);
cursor = response.nextCursor;
} while (cursor);
// Find test workflows
const testWorkflows = allWorkflows.filter(w =>
w.tags?.includes(creds.cleanup.tag) ||
w.name?.startsWith(creds.cleanup.namePrefix)
);
console.log(`Found ${testWorkflows.length} orphaned test workflows`);
// Delete them
for (const workflow of testWorkflows) {
try {
await client.deleteWorkflow(workflow.id);
console.log(`Deleted orphaned workflow: ${workflow.name} (${workflow.id})`);
} catch (error) {
console.warn(`Failed to delete workflow ${workflow.id}:`, error);
}
}
}
/**
* Clean up old executions (older than 24 hours)
*/
export async function cleanupOldExecutions(): Promise<void> {
const client = getTestN8nClient();
let allExecutions: any[] = [];
let cursor: string | undefined;
// Fetch all executions
do {
const response = await client.listExecutions({ cursor, limit: 100 });
allExecutions.push(...response.data);
cursor = response.nextCursor;
} while (cursor);
const oneDayAgo = Date.now() - 24 * 60 * 60 * 1000;
const oldExecutions = allExecutions.filter(e =>
new Date(e.startedAt).getTime() < oneDayAgo
);
console.log(`Found ${oldExecutions.length} old executions`);
for (const execution of oldExecutions) {
try {
await client.deleteExecution(execution.id);
} catch (error) {
console.warn(`Failed to delete execution ${execution.id}:`, error);
}
}
}
fixtures.ts - Reusable workflow templates:
import { Workflow } from '../../../src/types/n8n-api';
export const SIMPLE_WEBHOOK_WORKFLOW: Partial<Workflow> = {
name: '[MCP-TEST] Simple Webhook',
nodes: [
{
id: 'webhook-1',
name: 'Webhook',
type: 'n8n-nodes-base.webhook',
typeVersion: 2,
position: [250, 300],
parameters: {
httpMethod: 'GET',
path: 'test-webhook'
}
}
],
connections: {}
};
export const SIMPLE_HTTP_WORKFLOW: Partial<Workflow> = {
name: '[MCP-TEST] Simple HTTP Request',
nodes: [
{
id: 'webhook-1',
name: 'Webhook',
type: 'n8n-nodes-base.webhook',
typeVersion: 2,
position: [250, 300],
parameters: {
httpMethod: 'GET',
path: 'trigger'
}
},
{
id: 'http-1',
name: 'HTTP Request',
type: 'n8n-nodes-base.httpRequest',
typeVersion: 4.2,
position: [450, 300],
parameters: {
url: 'https://httpbin.org/get',
method: 'GET'
}
}
],
connections: {
Webhook: {
main: [[{ node: 'HTTP Request', type: 'main', index: 0 }]]
}
}
};
// Add more fixtures for complex workflows
webhook-workflows.ts - Webhook workflow setup guide:
/**
* Guide for setting up webhook workflows manually in n8n
*
* These workflows must be created manually and activated because
* n8n API doesn't support workflow activation.
*
* For each HTTP method, create a workflow with:
* 1. Single Webhook node
* 2. Configured for the specific HTTP method
* 3. Unique webhook path
* 4. Activated in n8n UI
* 5. Workflow ID added to .env
*/
export const WEBHOOK_WORKFLOW_CONFIGS = {
GET: {
name: '[MCP-TEST] Webhook GET',
description: 'Pre-activated webhook for GET method testing',
nodes: [
{
name: 'Webhook',
type: 'n8n-nodes-base.webhook',
typeVersion: 2,
parameters: {
httpMethod: 'GET',
path: 'mcp-test-get',
responseMode: 'lastNode'
}
}
]
},
POST: {
name: '[MCP-TEST] Webhook POST',
description: 'Pre-activated webhook for POST method testing',
nodes: [
{
name: 'Webhook',
type: 'n8n-nodes-base.webhook',
typeVersion: 2,
parameters: {
httpMethod: 'POST',
path: 'mcp-test-post',
responseMode: 'lastNode'
}
}
]
},
PUT: {
name: '[MCP-TEST] Webhook PUT',
description: 'Pre-activated webhook for PUT method testing',
nodes: [
{
name: 'Webhook',
type: 'n8n-nodes-base.webhook',
typeVersion: 2,
parameters: {
httpMethod: 'PUT',
path: 'mcp-test-put',
responseMode: 'lastNode'
}
}
]
},
DELETE: {
name: '[MCP-TEST] Webhook DELETE',
description: 'Pre-activated webhook for DELETE method testing',
nodes: [
{
name: 'Webhook',
type: 'n8n-nodes-base.webhook',
typeVersion: 2,
parameters: {
httpMethod: 'DELETE',
path: 'mcp-test-delete',
responseMode: 'lastNode'
}
}
]
}
};
export function printSetupInstructions(): void {
console.log(`
╔════════════════════════════════════════════════════════════════╗
║ WEBHOOK WORKFLOW SETUP REQUIRED ║
╠════════════════════════════════════════════════════════════════╣
║ ║
║ Integration tests require 4 pre-activated webhook workflows: ║
║ ║
║ 1. Create workflows manually in n8n UI ║
║ 2. Use the configurations shown below ║
║ 3. ACTIVATE each workflow in n8n UI ║
║ 4. Copy workflow IDs to .env file ║
║ ║
╚════════════════════════════════════════════════════════════════╝
Required workflows:
`);
Object.entries(WEBHOOK_WORKFLOW_CONFIGS).forEach(([method, config]) => {
console.log(`
${method} Method:
Name: ${config.name}
Path: ${config.nodes[0].parameters.path}
.env variable: N8N_TEST_WEBHOOK_${method}_ID
`);
});
}
Phase 2: Workflow Creation Tests (P0)
Branch: feat/integration-tests-workflow-creation
File: tests/integration/n8n-api/workflows/create-workflow.test.ts
10+ Test Scenarios:
- Create workflow with base webhook node (verify P0 bug fix)
- Create workflow with base HTTP request node
- Create workflow with langchain agent node
- Create complex multi-node workflow
- Create workflow with complex connections
- Error: Invalid node type
- Error: Missing required parameters
- Error: Duplicate node names
- Error: Invalid connection references
- Create workflow with custom settings
Phase 3: Workflow Retrieval Tests (P1)
Branch: feat/integration-tests-workflow-retrieval
Files:
get-workflow.test.ts(3 scenarios)get-workflow-details.test.ts(4 scenarios)get-workflow-structure.test.ts(2 scenarios)get-workflow-minimal.test.ts(2 scenarios)
Phase 4: Workflow Update Tests (P1)
Branch: feat/integration-tests-workflow-updates
Files:
update-workflow.test.ts(8+ scenarios)update-partial-workflow.test.ts(30+ scenarios covering all 15 operations)
Phase 5: Workflow Management Tests (P2)
Branch: feat/integration-tests-workflow-management
Files:
delete-workflow.test.ts(3 scenarios)list-workflows.test.ts(12+ scenarios with all filters and pagination)
Phase 6: Validation & Autofix Tests (P2)
Branch: feat/integration-tests-validation
Files:
validate-workflow.test.ts(16 scenarios: 4 profiles × 4 validation types)autofix-workflow.test.ts(20+ scenarios: 5 fix types × confidence levels)
Phase 7: Execution Management Tests (P2)
Branch: feat/integration-tests-executions
Files:
trigger-webhook.test.ts(16+ scenarios: 4 HTTP methods × variations)get-execution.test.ts(20+ scenarios: 4 modes × filters)list-executions.test.ts(10+ scenarios)delete-execution.test.ts(3 scenarios)
Special Considerations for Webhook Testing:
- Use pre-activated workflows from
.env - Each HTTP method uses a different workflow ID
- Test both successful triggers and error cases
- Verify response data for synchronous executions
Phase 8: System Tools Tests (P3)
Branch: feat/integration-tests-system
Files:
health-check.test.ts(2 scenarios)list-tools.test.ts(1 scenario)diagnostic.test.ts(3 scenarios)
Phase 9: CI/CD Integration
Branch: feat/integration-tests-ci
GitHub Actions Workflow (.github/workflows/integration-tests.yml):
name: Integration Tests
on:
pull_request:
push:
branches: [main]
schedule:
- cron: '0 2 * * *' # Daily at 2 AM
workflow_dispatch:
jobs:
integration-tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build project
run: npm run build
- name: Run integration tests
env:
N8N_URL: ${{ secrets.N8N_URL }}
N8N_API_KEY: ${{ secrets.N8N_API_KEY }}
N8N_TEST_WEBHOOK_GET_ID: ${{ secrets.N8N_TEST_WEBHOOK_GET_ID }}
N8N_TEST_WEBHOOK_POST_ID: ${{ secrets.N8N_TEST_WEBHOOK_POST_ID }}
N8N_TEST_WEBHOOK_PUT_ID: ${{ secrets.N8N_TEST_WEBHOOK_PUT_ID }}
N8N_TEST_WEBHOOK_DELETE_ID: ${{ secrets.N8N_TEST_WEBHOOK_DELETE_ID }}
CI: true
run: npm run test:integration
- name: Cleanup orphaned workflows
if: always()
env:
N8N_URL: ${{ secrets.N8N_URL }}
N8N_API_KEY: ${{ secrets.N8N_API_KEY }}
run: npm run test:cleanup:orphans
Add npm scripts to package.json:
{
"scripts": {
"test:integration:n8n": "vitest run tests/integration/n8n-api",
"test:cleanup:orphans": "tsx tests/integration/n8n-api/utils/cleanup-orphans.ts"
}
}
Test Isolation Strategy
Workflow Naming Convention
- Prefix:
[MCP-TEST] - Include test name:
[MCP-TEST] Create Workflow - Base Nodes - Include timestamp for uniqueness:
[MCP-TEST] Test Name ${Date.now()}
Workflow Tagging
- All test workflows tagged with:
mcp-integration-test - Enables bulk cleanup queries
Cleanup Levels
- Test-level: After each test via
afterEachhook - Suite-level: After each test file via
afterAllhook - CI-level: After CI job completes (always run)
- Orphan cleanup: Periodic job to clean up failed test runs
Pre-Test Setup Checklist
Local Development
- ✅ Install n8n locally or use Docker
- ✅ Start n8n instance:
npx n8n start - ✅ Create 4 webhook workflows (GET, POST, PUT, DELETE)
- ✅ Activate all 4 webhook workflows in n8n UI
- ✅ Get workflow IDs from n8n UI
- ✅ Copy
.env.exampleto.env - ✅ Set
N8N_API_URL=http://localhost:5678 - ✅ Generate API key in n8n Settings > API
- ✅ Set
N8N_API_KEY=<your-key> - ✅ Set all 4
N8N_TEST_WEBHOOK_*_IDvariables
CI/GitHub Actions
- ✅ Set up cloud n8n instance (or self-hosted)
- ✅ Create 4 webhook workflows (GET, POST, PUT, DELETE)
- ✅ Activate all 4 webhook workflows
- ✅ Add GitHub secrets:
N8N_URL,N8N_API_KEY - ✅ Add webhook workflow ID secrets (4 total)
Success Criteria
- ✅ All 17 handlers have integration tests
- ✅ All operations/parameters covered (150+ scenarios)
- ✅ Tests run successfully locally and in CI
- ✅ No manual cleanup required (automatic)
- ✅ Test coverage catches P0-level bugs
- ✅ CI runs on every PR and daily
- ✅ Clear error messages when tests fail
- ✅ Documentation for webhook workflow setup
Timeline Estimate
- Phase 1 (Foundation): 2-3 days
- Phase 2 (Workflow Creation): 1 day
- Phase 3 (Retrieval): 1 day
- Phase 4 (Updates): 2-3 days (15 operations)
- Phase 5 (Management): 1 day
- Phase 6 (Validation): 2 days
- Phase 7 (Executions): 2 days
- Phase 8 (System): 1 day
- Phase 9 (CI/CD): 1 day
Total: ~14-18 days
Notes
- Each phase should be developed on a separate branch
- Phases can be parallelized where dependencies allow
- Run local tests frequently to catch issues early
- Document any n8n API quirks discovered during testing