/n8n-expression-testing
n8n expression syntax validation, context-aware testing, common pitfalls detection, and performance optimization. Use when validating n8n expressions and data transformations.
$ npx -y skills add proffesor-for-testing/agentic-qe --skill n8n-expression-testing --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/n8n-expression-testing
Context preview
The summary Claude sees to decide when to auto-load this skill.
n8n expression syntax validation, context-aware testing, common pitfalls detection, and performance optimization. Use when validating n8n expressions and data transformations.
SKILL.md
n8n-expression-testing.SKILL.mdname: n8n-expression-testing
description: "n8n expression syntax validation, context-aware testing, common pitfalls detection, and performance optimization. Use when validating n8n expressions and data transformations."
category: n8n-testing
priority: high
tokenEstimate: 1000
agents: [n8n-expression-validator]
implementation_status: production
optimization_version: 1.0
last_optimized: 2025-12-15
dependencies: []
quick_reference_card: true
tags: [n8n, expressions, javascript, data-transformation, validation]
trust_tier: 3
validation:
schema_path: schemas/output.json
validator_path: scripts/validate-config.json
eval_path: evals/n8n-expression-testing.yaml
n8n Expression Testing
<default_to_action> When testing n8n expressions: 1. VALIDATE syntax before execution 2. TEST with multiple context scenarios 3. CHECK for null/undefined handling 4. VERIFY type safety 5. SCAN for security vulnerabilities
**Quick Expression Checklist:**
- Valid JavaScript syntax
- Context variables properly referenced ($json, $node)
- Null-safe access patterns (?., ??)
- No dangerous functions (eval, Function)
- Efficient for large data sets
**Common Pitfalls:**
- Accessing nested properties without null checks
- Type coercion issues
- Missing fallback values
- Inefficient array operations
</default_to_action>
Quick Reference Card
n8n Expression Syntax
| Pattern | Example | Description | |---------|---------|-------------| | Basic access | `{{ $json.field }}` | Access JSON field | | Nested access | `{{ $json.user.email }}` | Access nested property | | Array access | `{{ $json.items[0] }}` | Access array element | | Node reference | `{{ $node["Name"].json.id }}` | Access other node's data | | Method call | `{{ $json.name.toLowerCase() }}` | Call string method | | Conditional | `{{ $json.x ? "yes" : "no" }}` | Ternary expression |
Context Variables
| Variable | Description | Example | |----------|-------------|---------| | `$json` | Current item data | `{{ $json.email }}` | | `$node["Name"]` | Other node's data | `{{ $node["HTTP"].json.body }}` | | `$items()` | Multiple items | `{{ $items("Node", 0, 0).json }}` | | `$now` | Current timestamp | `{{ $now.toISO() }}` | | `$today` | Today's date | `{{ $today }}` | | `$runIndex` | Run iteration | `{{ $runIndex }}` | | `$workflow` | Workflow info | `{{ $workflow.name }}` |
---
Expression Syntax Patterns
Safe Data Access
// BAD: Can fail if nested objects are null
{{ $json.user.profile.email }}
// GOOD: Optional chaining with fallback
{{ $json.user?.profile?.email ?? '' }}
// BAD: Array access without bounds check
{{ $json.items[0].name }}
// GOOD: Safe array access
{{ $json.items?.[0]?.name ?? 'No items' }}Type Conversions
// String to Number
{{ parseInt($json.quantity, 10) }}
{{ parseFloat($json.price) }}
{{ Number($json.value) }}
// Number to String
{{ String($json.id) }}
{{ $json.amount.toString() }}
{{ $json.count.toFixed(2) }}
// Date handling
{{ new Date($json.timestamp).toISOString() }}
{{ DateTime.fromISO($json.date).toFormat('yyyy-MM-dd') }}
// Boolean conversion
{{ Boolean($json.active) }}
{{ $json.enabled === 'true' }}String Operations
// Case conversion
{{ $json.name.toLowerCase() }}
{{ $json.name.toUpperCase() }}
{{ $json.name.charAt(0).toUpperCase() + $json.name.slice(1) }}
// String manipulation
{{ $json.text.trim() }}
{{ $json.text.replace(/\s+/g, ' ') }}
{{ $json.text.substring(0, 100) }}
// Template strings
{{ `Hello, ${$json.firstName} ${$json.lastName}!` }}
{{ `Order #${$json.orderId} - ${$json.status}` }}Array Operations
// Mapping
{{ $json.items.map(item => item.name) }}
{{ $json.items.map(item => ({ id: item.id, total: item.price * item.qty })) }}
// Filtering
{{ $json.items.filter(item => item.active) }}
{{ $json.items.filter(item => item.price > 100) }}
// Reducing
{{ $json.items.reduce((sum, item) => sum + item.price, 0) }}
{{ $json.items.reduce((acc, item) => ({ ...acc, [item.id]: item }), {}) }}
// Finding
{{ $json.items.find(item => item.id === $json.targetId) }}
{{ $json.items.findIndex(item => item.name === 'target') }}
// Joining
{{ $json.tags.join(', ') }}
{{ $json.items.map(i => i.name).join(' | ') }}---
Validation Patterns
// Validate expression syntax
function validateExpressionSyntax(expression: string): ValidationResult {
// Remove n8n template markers
const code = expression.replace(/\{\{|\}\}/g, '').trim();
try {
// Check if valid JavaScript
new Function(`return (${code})`);
return { valid: true };
} catch (error) {
return {
valid: false,
error: error.message,
suggestion: suggestFix(error.message, code)
};
}
}
// Validate context variables
function validateContextVariables(expression: string): string[] {
const contextVars = ['$json', '$node', '$items', '$now', '$today', '$runIndex', '$workflow'];
const usedVars = [];
const invalidVars = [];
// Find all $ prefixed variables
const varPattern = /\$\w+/g;
let match;
while ((match = varPattern.exec(expression)) !== null) {
const varName = match[0];
if (contextVars.some(cv => varName.startsWith(cv))) {
usedVars.push(varName);
} else {
invalidVars.push(varName);
}
}
return { usedVars, invalidVars };
}
// Test expression with sample data
function testExpression(expression: string, context: any): TestResult {
const code = expression.replace(/\{\{|\}\}/g, '').trim();
try {
// Create function with context
const fn = new Function('$json', '$node', '$items', '$now', '$today',
`return (${code})`);
const result = fn(
context.$json || {},
context.$node || {},
context.$items || (() => ({})),
context.$now || new Date(),
context.$today || new Date()
);
return { success: true, result };
} catch (error) {
return { success: false, error: error.message };
}
}---
Read more
name: n8n-expression-testing description: "n8n expression syntax validation, context-aware testing, common pitfalls detection, and performance optimization. Use when validating n8n expressions and data transformations." category: n8n-testing priority: high tokenEstimate: 1000 agents: [n8n-expression-validator] implementation_status: production optimization_version: 1.0 last_optimized: 2025-12-15 dependencies: [] quick_reference_card: true tags: [n8n, expressions, javascript, data-transformation, validation] trust_tier: 3 validation: schema_path: schemas/output.json validator_path: scripts/validate-config.json eval_path: evals/n8n-expression-testing.yaml
n8n Expression Testing
<default_to_action> When testing n8n expressions: 1. VALIDATE syntax before execution 2. TEST with multiple context scenarios 3. CHECK for null/undefined handling 4. VERIFY type safety 5. SCAN for security vulnerabilities
**Quick Expression Checklist:**
- Valid JavaScript syntax
- Context variables properly referenced ($json, $node)
- Null-safe access patterns (?., ??)
- No dangerous functions (eval, Function)
- Efficient for large data sets
**Common Pitfalls:**
- Accessing nested properties without null checks
- Type coercion issues
- Missing fallback values
- Inefficient array operations
</default_to_action>
Quick Reference Card
n8n Expression Syntax
| Pattern | Example | Description | |---------|---------|-------------| | Basic access | `{{ $json.field }}` | Access JSON field | | Nested access | `{{ $json.user.email }}` | Access nested property | | Array access | `{{ $json.items[0] }}` | Access array element | | Node reference | `{{ $node["Name"].json.id }}` | Access other node's data | | Method call | `{{ $json.name.toLowerCase() }}` | Call string method | | Conditional | `{{ $json.x ? "yes" : "no" }}` | Ternary expression |
Context Variables
| Variable | Description | Example | |----------|-------------|---------| | `$json` | Current item data | `{{ $json.email }}` | | `$node["Name"]` | Other node's data | `{{ $node["HTTP"].json.body }}` | | `$items()` | Multiple items | `{{ $items("Node", 0, 0).json }}` | | `$now` | Current timestamp | `{{ $now.toISO() }}` | | `$today` | Today's date | `{{ $today }}` | | `$runIndex` | Run iteration | `{{ $runIndex }}` | | `$workflow` | Workflow info | `{{ $workflow.name }}` |
---
Expression Syntax Patterns
Safe Data Access
// BAD: Can fail if nested objects are null
{{ $json.user.profile.email }}
// GOOD: Optional chaining with fallback
{{ $json.user?.profile?.email ?? '' }}
// BAD: Array access without bounds check
{{ $json.items[0].name }}
// GOOD: Safe array access
{{ $json.items?.[0]?.name ?? 'No items' }}Type Conversions
// String to Number
{{ parseInt($json.quantity, 10) }}
{{ parseFloat($json.price) }}
{{ Number($json.value) }}
// Number to String
{{ String($json.id) }}
{{ $json.amount.toString() }}
{{ $json.count.toFixed(2) }}
// Date handling
{{ new Date($json.timestamp).toISOString() }}
{{ DateTime.fromISO($json.date).toFormat('yyyy-MM-dd') }}
// Boolean conversion
{{ Boolean($json.active) }}
{{ $json.enabled === 'true' }}String Operations
// Case conversion
{{ $json.name.toLowerCase() }}
{{ $json.name.toUpperCase() }}
{{ $json.name.charAt(0).toUpperCase() + $json.name.slice(1) }}
// String manipulation
{{ $json.text.trim() }}
{{ $json.text.replace(/\s+/g, ' ') }}
{{ $json.text.substring(0, 100) }}
// Template strings
{{ `Hello, ${$json.firstName} ${$json.lastName}!` }}
{{ `Order #${$json.orderId} - ${$json.status}` }}Array Operations
// Mapping
{{ $json.items.map(item => item.name) }}
{{ $json.items.map(item => ({ id: item.id, total: item.price * item.qty })) }}
// Filtering
{{ $json.items.filter(item => item.active) }}
{{ $json.items.filter(item => item.price > 100) }}
// Reducing
{{ $json.items.reduce((sum, item) => sum + item.price, 0) }}
{{ $json.items.reduce((acc, item) => ({ ...acc, [item.id]: item }), {}) }}
// Finding
{{ $json.items.find(item => item.id === $json.targetId) }}
{{ $json.items.findIndex(item => item.name === 'target') }}
// Joining
{{ $json.tags.join(', ') }}
{{ $json.items.map(i => i.name).join(' | ') }}---
Validation Patterns
// Validate expression syntax
function validateExpressionSyntax(expression: string): ValidationResult {
// Remove n8n template markers
const code = expression.replace(/\{\{|\}\}/g, '').trim();
try {
// Check if valid JavaScript
new Function(`return (${code})`);
return { valid: true };
} catch (error) {
return {
valid: false,
error: error.message,
suggestion: suggestFix(error.message, code)
};
}
}
// Validate context variables
function validateContextVariables(expression: string): string[] {
const contextVars = ['$json', '$node', '$items', '$now', '$today', '$runIndex', '$workflow'];
const usedVars = [];
const invalidVars = [];
// Find all $ prefixed variables
const varPattern = /\$\w+/g;
let match;
while ((match = varPattern.exec(expression)) !== null) {
const varName = match[0];
if (contextVars.some(cv => varName.startsWith(cv))) {
usedVars.push(varName);
} else {
invalidVars.push(varName);
}
}
return { usedVars, invalidVars };
}
// Test expression with sample data
function testExpression(expression: string, context: any): TestResult {
const code = expression.replace(/\{\{|\}\}/g, '').trim();
try {
// Create function with context
const fn = new Function('$json', '$node', '$items', '$now', '$today',
`return (${code})`);
const result = fn(
context.$json || {},
context.$node || {},
context.$items || (() => ({})),
context.$now || new Date(),
context.$today || new Date()
);
return { success: true, result };
} catch (error) {
return { success: false, error: error.message };
}
}---
AI-powered quality engineering agents that generate tests, find coverage gaps, detect flaky tests, and learn your codebase patterns — across 11 coding agent platforms.
Repo: proffesor-for-testing/agentic-qe
Other skills on agentic-qe.
- /a11y-ally
Use when running comprehensive WCAG accessibility audits with axe-core + pa11y + Lighthouse, generating context-aware remediation, or testing video accessibility. Supports 3-tier browser cascade with graceful degradation.
Open skill - /accessibility-testing
WCAG 2.2 compliance testing, screen reader validation, and inclusive design verification. Use when ensuring legal compliance (ADA, Section 508), testing for disabilities, or building accessible applications for 1 billion disabled users globally.
Open skill - /agentdb-advanced
Master advanced AgentDB features including QUIC synchronization, multi-database management, custom distance metrics, hybrid search, and distributed systems integration. Use when building distributed AI systems, multi-agent coordination, or advanced vector search applications.
Open skill - /agentdb-learning
Create and train AI learning plugins with AgentDB's 9 reinforcement learning algorithms. Includes Decision Transformer, Q-Learning, SARSA, Actor-Critic, and more. Use when building self-learning agents, implementing RL, or optimizing agent behavior through experience.
Open skill - /agentdb-memory-patterns
Implement persistent memory patterns for AI agents using AgentDB. Includes session memory, long-term storage, pattern learning, and context management. Use when building stateful agents, chat systems, or intelligent assistants.
Open skill - /agentdb-optimization
Optimize AgentDB performance with quantization (4-32x memory reduction), HNSW indexing (150x faster search), caching, and batch operations. Use when optimizing memory usage, improving search speed, or scaling to millions of vectors.
Open skill

