Skip to content
Testing
Skill

/n8n-expression-testing

n8n expression syntax validation, context-aware testing, common pitfalls detection, and performance optimization. Use when validating n8n expressions and data transformations.

From plugin
agentic-qe
436200 skills169 agents149 commands
Install
$ npx -y skills add proffesor-for-testing/agentic-qe --skill n8n-expression-testing --agent claude-code

How 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.md
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 };
  }
}

---

Read more
Ships withagentic-qe

AI-powered quality engineering agents that generate tests, find coverage gaps, detect flaky tests, and learn your codebase patterns — across 11 coding agent platforms.

Get the whole plugin

Other skills on agentic-qe.