n8n-tdd-framework
v0.13.0
Published
A Test-Driven Development framework for n8n workflows
Maintainers
Readme
n8n-tdd-framework
A Test-Driven Development framework for n8n workflows.
Installation
npm install n8n-tdd-frameworkFeatures
- Create, read, update, and delete n8n workflows
- Manage n8n credentials securely
- Import and export workflows to/from files
- Template-based workflow creation
- Declarative workflow testing
- Comprehensive coverage tracking and reporting
- Docker management for n8n instances
- CI/CD integration
Usage
Basic Usage
import { WorkflowManager } from 'n8n-tdd-framework';
// Create a workflow manager
const manager = new WorkflowManager();
// Connect to n8n
await manager.connect();
// List all workflows
const workflows = await manager.listWorkflows();
console.log(`Found ${workflows.length} workflow(s)`);
// Create a workflow
const workflow = await manager.createWorkflow({
name: 'My Workflow',
nodes: [],
connections: {}
});
// Execute a workflow
const result = await manager.executeWorkflow(workflow.id);
// Disconnect from n8n
await manager.disconnect();Workflow Templates
import { WorkflowManager } from 'n8n-tdd-framework';
const manager = new WorkflowManager({
templatesDir: './templates'
});
// Create a workflow from a template
const workflow = await manager.createWorkflowFromTemplate(
'http_request',
'My HTTP Workflow'
);
// Save a workflow as a template
await manager.saveWorkflowTemplate('my_template', workflow);
// List available templates
const templates = manager.listWorkflowTemplates();Credential Management
All credentials in the framework are managed through environment variables for enhanced security. This ensures sensitive information is never hardcoded in your application.
import { WorkflowManager } from 'n8n-tdd-framework';
// Create a workflow manager
const manager = new WorkflowManager();
// Connect to n8n
await manager.connect();
// List credential types
const credentialTypes = await manager.listCredentialTypes();
console.log(`Available credential types: ${credentialTypes.length}`);
// List all credentials from environment variables
const envCredentials = manager.listCredentialsFromEnv();
console.log(`Found ${envCredentials.length} credential(s) in environment variables`);
// Create a credential from environment variables
// This will look for environment variables with the prefix N8N_CREDENTIAL_API_*
const credential = await manager.createCredentialFromEnv('API');
console.log(`Created credential with ID: ${credential.id}`);
// Check if a credential exists in environment variables
if (manager.hasCredentialInEnv('DATABASE')) {
// Create the credential
const dbCredential = await manager.createCredentialFromEnv('DATABASE');
}
// Get a credential by ID
const retrievedCredential = await manager.getCredential(credential.id!);
// Update a credential
await manager.updateCredential(credential.id!, {
name: 'Updated API Credential'
});
// Delete a credential
await manager.deleteCredential(credential.id!);
// Disconnect from n8n
await manager.disconnect();Defining Credentials in Environment Variables
To define credentials in environment variables, use the following format:
# Basic HTTP Auth Credential
N8N_CREDENTIAL_API_TYPE=httpBasicAuth
N8N_CREDENTIAL_API_USERNAME=myusername
N8N_CREDENTIAL_API_PASSWORD=mypassword
# OAuth2 Credential
N8N_CREDENTIAL_OAUTH_TYPE=oAuth2Api
N8N_CREDENTIAL_OAUTH_CLIENT_ID=myclientid
N8N_CREDENTIAL_OAUTH_CLIENT_SECRET=myclientsecretThe format is N8N_CREDENTIAL_<NAME>_<PROPERTY>, where:
<NAME>is the credential name (e.g., API, OAUTH, DATABASE)<PROPERTY>is the property name (e.g., TYPE, USERNAME, PASSWORD)
The TYPE property is required and must match a valid n8n credential type.
Referencing Environment Variables in Credential Data
You can also reference other environment variables in credential data:
// Create a credential with environment variable references
const credential: Credential = {
name: 'My API Credential',
type: 'httpBasicAuth',
data: {
username: '${API_USERNAME}',
password: '${API_PASSWORD}'
}
};
// The environment variables will be resolved when creating the credential
const createdCredential = await manager.createCredential(credential);This allows you to reference sensitive information stored in environment variables without hardcoding them in your application.
Declarative Testing
import { DeclarativeTestRunner } from 'n8n-tdd-framework';
// Create a test runner
const runner = new DeclarativeTestRunner({
templatesDir: './templates',
testsDir: './tests'
});
// Run tests from a file
const results = await runner.runTestsFromFile('./tests/my-test.json');
console.log(`Tests: ${results.passed}/${results.total} passed`);
// Run all tests in a directory
const allResults = await runner.runTestsFromDirectory('./tests');Example test file (JSON):
[
{
"name": "HTTP Request Test",
"workflows": [
{
"templateName": "http_request",
"name": "Test HTTP Workflow",
"isPrimary": true
}
],
"credentials": [
{
"name": "API",
"usedByWorkflow": "Test HTTP Workflow",
"usedByNode": "HTTP Request"
},
{
"name": "OAUTH",
"usedByWorkflow": "Test HTTP Workflow",
"usedByNode": "OAuth Request"
}
],
"input": {
"url": "https://example.com"
},
"assertions": [
{
"description": "Response should be successful",
"assertion": "result && result.success === true"
},
{
"description": "Response should contain data",
"assertion": "result && result.data && typeof result.data === 'object'"
}
]
}
]In this example, the credentials API and OAUTH will be loaded from environment variables. The framework will look for environment variables with the prefixes N8N_CREDENTIAL_API_* and N8N_CREDENTIAL_OAUTH_* to create these credentials.
Make sure to define these credentials in your .env file before running the tests:
# API Credential
N8N_CREDENTIAL_API_TYPE=httpBasicAuth
N8N_CREDENTIAL_API_USERNAME=testuser
N8N_CREDENTIAL_API_PASSWORD=testpass
# OAuth Credential
N8N_CREDENTIAL_OAUTH_TYPE=oAuth2Api
N8N_CREDENTIAL_OAUTH_CLIENT_ID=clientid
N8N_CREDENTIAL_OAUTH_CLIENT_SECRET=clientsecretDocker Management
The framework provides Docker management for n8n instances:
import { createDockerManager, DockerContainerConfig } from 'n8n-tdd-framework';
// Configure Docker container
const config: DockerContainerConfig = {
containerName: 'n8n',
image: 'n8nio/n8n',
port: 5678,
apiKey: 'your-api-key',
dataDir: './n8n_data',
env: {
N8N_DIAGNOSTICS_ENABLED: 'false',
N8N_ENFORCE_SETTINGS_FILE_PERMISSIONS: 'false'
},
volumes: [
'./custom-nodes:/home/node/.n8n/custom-nodes'
]
};
// Create Docker manager
const dockerManager = createDockerManager(config);
// Start n8n container
await dockerManager.start();
// Check container status
const status = await dockerManager.status();
console.log(`Container running: ${status.running}`);
console.log(`API accessible: ${status.apiAccessible}`);
// Stop n8n container
await dockerManager.stop();Coverage Tracking
The framework provides comprehensive coverage tracking for n8n workflows:
import {
DeclarativeTestRunner,
CoverageTracker,
CoverageOptions
} from 'n8n-tdd-framework';
// Create a coverage tracker
const coverageOptions: CoverageOptions = {
enabled: true,
format: 'all', // 'console', 'json', 'html', or 'all'
outputDir: './coverage',
thresholds: {
nodes: 80,
connections: 70,
branches: 60
},
dashboard: {
enabled: true,
outputDir: './public'
}
};
const coverageTracker = new CoverageTracker(coverageOptions);
// Create a test runner with coverage tracking
const runner = new DeclarativeTestRunner({
templatesDir: './templates',
testsDir: './tests',
coverageTracker
});
// Run tests with coverage
const results = await runner.runTestsFromFile('./tests/my-test.json');
// Generate coverage report
coverageTracker.generateReport();
// Check if coverage meets thresholds
const coverageData = coverageTracker.getCoverageData();
console.log(`Node Coverage: ${coverageData.summary.overallNodeCoverage.toFixed(2)}%`);
console.log(`Connection Coverage: ${coverageData.summary.overallConnectionCoverage.toFixed(2)}%`);
console.log(`Branch Coverage: ${coverageData.summary.overallBranchCoverage.toFixed(2)}%`);CLI Usage
The framework includes a CLI for managing workflows:
# Install globally
npm install -g n8n-tdd-framework
# List all workflows
n8n-tdd list
# Create a workflow from a template
n8n-tdd create "My Workflow" http_request
# Execute a workflow
n8n-tdd execute workflow-id
# Run tests
n8n-tdd test ./tests/my-test.json
# Coverage commands
n8n-tdd coverage:check # Check coverage thresholds
n8n-tdd coverage:dashboard # Generate coverage dashboard
n8n-tdd coverage:clean # Clean up coverage files
# Docker commands
n8n-tdd docker:start # Start n8n Docker container
n8n-tdd docker:stop # Stop n8n Docker container
n8n-tdd docker:restart # Restart n8n Docker container
n8n-tdd docker:status # Get n8n Docker container status
n8n-tdd docker:help # Show Docker helpConfiguration
The framework can be configured using:
Environment variables:
N8N_API_URL: URL of the n8n APIN8N_API_KEY: API key for authenticationN8N_TEMPLATES_DIR: Directory for workflow templatesN8N_TESTS_DIR: Directory for test filesN8N_COVERAGE_ENABLED: Enable coverage tracking (true/false)N8N_COVERAGE_FORMAT: Coverage report format (console/json/html/all)N8N_COVERAGE_OUTPUT_DIR: Directory for coverage reportsN8N_CONTAINER_NAME: Docker container nameN8N_IMAGE: Docker image for n8nN8N_PORT: Port to expose n8n on
Configuration file (
n8n-tdd-config.json):{ "apiUrl": "http://localhost:5678/api/v1", "templatesDir": "./templates", "testsDir": "./tests", "coverage": { "enabled": true, "format": "all", "outputDir": "./coverage", "thresholds": { "nodes": 80, "connections": 70, "branches": 60 } }, "docker": { "containerName": "n8n", "image": "n8nio/n8n", "port": 5678, "dataDir": "./n8n_data" } }Constructor options:
const manager = new WorkflowManager({ apiUrl: "http://localhost:5678/api/v1", apiKey: "your-api-key", templatesDir: "./templates" });
API Reference
WorkflowManager
The WorkflowManager class provides methods for managing n8n workflows and credentials:
connect(): Connect to the n8n APIdisconnect(): Disconnect from the n8n API
Workflow Management:
listWorkflows(active?: boolean): List all workflowsgetWorkflow(id: string): Get a workflow by IDcreateWorkflow(workflow: Workflow): Create a new workflowupdateWorkflow(id: string, workflow: Partial<Workflow>): Update a workflowdeleteWorkflow(id: string): Delete a workflowactivateWorkflow(id: string): Activate a workflowdeactivateWorkflow(id: string): Deactivate a workflowexecuteWorkflow(id: string, data?: any): Execute a workflowsaveWorkflowToFile(id: string, filename?: string): Save a workflow to a fileloadWorkflowFromFile(filePath: string): Load a workflow from a fileimportWorkflow(filePath: string): Import a workflow from a fileexportAllWorkflows(outputDir?: string): Export all workflows to filessaveWorkflowTemplate(name: string, workflow: Workflow): Save a workflow as a templateloadWorkflowTemplate(name: string): Load a workflow templatecreateWorkflowFromTemplate(templateName: string, workflowName: string, settings?: Record<string, any>): Create a workflow from a templatelistWorkflowTemplates(): List all workflow templates
Credential Management:
listCredentialTypes(): List all credential typeslistCredentials(): List all credentialsgetCredential(id: string): Get a credential by IDcreateCredential(credential: Credential): Create a new credential (environment variables are always resolved)updateCredential(id: string, credential: Partial<Credential>): Update a credential (environment variables are always resolved)deleteCredential(id: string): Delete a credentialcreateCredentialFromEnv(name: string, options?: { envPrefix?: string; envPath?: string }): Create a credential from environment variableslistCredentialsFromEnv(options?: { envPrefix?: string; envPath?: string }): List all credentials from environment variablesgetCredentialFromEnv(name: string, options?: { envPrefix?: string; envPath?: string }): Get a credential from environment variableshasCredentialInEnv(name: string, options?: { envPrefix?: string; envPath?: string }): Check if a credential exists in environment variables
DockerManager
The DockerManager interface provides methods for managing n8n Docker containers:
start(): Start n8n containerstop(): Stop and remove n8n containerrestart(): Restart n8n containerstatus(): Get n8n container statusisRunning(): Check if n8n is running and accessiblewaitForHealth(timeout?: number): Wait for n8n to be healthy
DeclarativeTestRunner
The DeclarativeTestRunner class provides methods for running declarative tests:
runTest(testCase: TestCase): Run a single test caserunTests(testCases: TestCase[]): Run multiple test casesrunTestsFromFile(filePath: string): Run tests from a filerunTestsFromDirectory(dirPath?: string): Run tests from a directory
CoverageTracker
The CoverageTracker class provides methods for tracking and reporting coverage:
addTestResult(testResult: TestResultWithCoverage): Add a test result with coverageaddTestResults(testResults: TestResultWithCoverage[]): Add multiple test results with coveragemerge(tracker: CoverageTracker): Merge coverage data from another trackergetCoverageData(): Get coverage datagenerateReport(): Generate coverage reportsaveCoverageData(): Save coverage data to file
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
ISC
