mirror of
https://github.com/johndoe6345789/AutoMetabuilder.git
synced 2026-04-24 13:54:59 +00:00
194 lines
5.9 KiB
Python
194 lines
5.9 KiB
Python
"""Tests for n8n workflow schema validation."""
|
|
import pytest
|
|
|
|
from autometabuilder.workflow.n8n_schema import N8NNode, N8NPosition, N8NTrigger, N8NWorkflow
|
|
|
|
|
|
def test_n8n_position_validation():
|
|
"""Test position validation."""
|
|
assert N8NPosition.validate([0, 0])
|
|
assert N8NPosition.validate([100.5, 200.5])
|
|
assert not N8NPosition.validate([0])
|
|
assert not N8NPosition.validate([0, 0, 0])
|
|
assert not N8NPosition.validate("invalid")
|
|
assert not N8NPosition.validate(None)
|
|
|
|
|
|
def test_n8n_node_validation():
|
|
"""Test node validation."""
|
|
valid_node = {
|
|
"id": "node-1",
|
|
"name": "Test Node",
|
|
"type": "core.test",
|
|
"typeVersion": 1,
|
|
"position": [0, 0],
|
|
"parameters": {}
|
|
}
|
|
assert N8NNode.validate(valid_node)
|
|
|
|
# Missing required fields
|
|
assert not N8NNode.validate({})
|
|
assert not N8NNode.validate({"id": "node-1"})
|
|
|
|
# Invalid typeVersion
|
|
invalid_node = valid_node.copy()
|
|
invalid_node["typeVersion"] = 0
|
|
assert not N8NNode.validate(invalid_node)
|
|
|
|
# Invalid position
|
|
invalid_node = valid_node.copy()
|
|
invalid_node["position"] = [0]
|
|
assert not N8NNode.validate(invalid_node)
|
|
|
|
|
|
def test_n8n_workflow_validation():
|
|
"""Test workflow validation."""
|
|
valid_workflow = {
|
|
"name": "Test Workflow",
|
|
"nodes": [
|
|
{
|
|
"id": "node-1",
|
|
"name": "Node 1",
|
|
"type": "core.test",
|
|
"typeVersion": 1,
|
|
"position": [0, 0]
|
|
}
|
|
],
|
|
"connections": {}
|
|
}
|
|
assert N8NWorkflow.validate(valid_workflow)
|
|
|
|
# Missing required fields
|
|
assert not N8NWorkflow.validate({})
|
|
assert not N8NWorkflow.validate({"name": "Test"})
|
|
|
|
# Empty nodes array is invalid
|
|
invalid_workflow = valid_workflow.copy()
|
|
invalid_workflow["nodes"] = []
|
|
assert not N8NWorkflow.validate(invalid_workflow)
|
|
|
|
# Invalid node
|
|
invalid_workflow = valid_workflow.copy()
|
|
invalid_workflow["nodes"] = [{"id": "bad"}]
|
|
assert not N8NWorkflow.validate(invalid_workflow)
|
|
|
|
|
|
def test_n8n_trigger_validation():
|
|
"""Test trigger validation."""
|
|
valid_trigger = {
|
|
"nodeId": "webhook-node-1",
|
|
"kind": "webhook",
|
|
"enabled": True,
|
|
"meta": {
|
|
"path": "/api/webhook",
|
|
"method": "POST"
|
|
}
|
|
}
|
|
assert N8NTrigger.validate(valid_trigger)
|
|
|
|
# Minimal valid trigger
|
|
minimal_trigger = {
|
|
"nodeId": "schedule-node",
|
|
"kind": "schedule"
|
|
}
|
|
assert N8NTrigger.validate(minimal_trigger)
|
|
|
|
# Test all valid kinds
|
|
for kind in ["webhook", "schedule", "queue", "email", "poll", "manual", "other"]:
|
|
trigger = {"nodeId": "node-1", "kind": kind}
|
|
assert N8NTrigger.validate(trigger)
|
|
|
|
# Missing required fields
|
|
assert not N8NTrigger.validate({})
|
|
assert not N8NTrigger.validate({"nodeId": "node-1"})
|
|
assert not N8NTrigger.validate({"kind": "webhook"})
|
|
|
|
# Invalid nodeId
|
|
invalid_trigger = valid_trigger.copy()
|
|
invalid_trigger["nodeId"] = ""
|
|
assert not N8NTrigger.validate(invalid_trigger)
|
|
|
|
invalid_trigger = valid_trigger.copy()
|
|
invalid_trigger["nodeId"] = 123
|
|
assert not N8NTrigger.validate(invalid_trigger)
|
|
|
|
# Invalid kind
|
|
invalid_trigger = valid_trigger.copy()
|
|
invalid_trigger["kind"] = "invalid_kind"
|
|
assert not N8NTrigger.validate(invalid_trigger)
|
|
|
|
# Invalid enabled
|
|
invalid_trigger = valid_trigger.copy()
|
|
invalid_trigger["enabled"] = "true"
|
|
assert not N8NTrigger.validate(invalid_trigger)
|
|
|
|
# Invalid meta
|
|
invalid_trigger = valid_trigger.copy()
|
|
invalid_trigger["meta"] = "not a dict"
|
|
assert not N8NTrigger.validate(invalid_trigger)
|
|
|
|
|
|
def test_n8n_workflow_with_triggers():
|
|
"""Test workflow validation with triggers array."""
|
|
valid_workflow_with_triggers = {
|
|
"name": "Webhook Workflow",
|
|
"nodes": [
|
|
{
|
|
"id": "webhook-1",
|
|
"name": "Webhook Trigger",
|
|
"type": "n8n-nodes-base.webhook",
|
|
"typeVersion": 1,
|
|
"position": [0, 0]
|
|
},
|
|
{
|
|
"id": "process-1",
|
|
"name": "Process Data",
|
|
"type": "n8n-nodes-base.function",
|
|
"typeVersion": 1,
|
|
"position": [300, 0]
|
|
}
|
|
],
|
|
"connections": {},
|
|
"triggers": [
|
|
{
|
|
"nodeId": "webhook-1",
|
|
"kind": "webhook",
|
|
"enabled": True,
|
|
"meta": {
|
|
"path": "/api/webhook",
|
|
"method": "POST"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
assert N8NWorkflow.validate(valid_workflow_with_triggers)
|
|
|
|
# Empty triggers array is valid
|
|
workflow_empty_triggers = valid_workflow_with_triggers.copy()
|
|
workflow_empty_triggers["triggers"] = []
|
|
assert N8NWorkflow.validate(workflow_empty_triggers)
|
|
|
|
# Workflow without triggers is valid (optional field)
|
|
workflow_no_triggers = valid_workflow_with_triggers.copy()
|
|
del workflow_no_triggers["triggers"]
|
|
assert N8NWorkflow.validate(workflow_no_triggers)
|
|
|
|
# Invalid triggers array (not a list)
|
|
invalid_workflow = valid_workflow_with_triggers.copy()
|
|
invalid_workflow["triggers"] = "not a list"
|
|
assert not N8NWorkflow.validate(invalid_workflow)
|
|
|
|
# Invalid trigger in array
|
|
invalid_workflow = valid_workflow_with_triggers.copy()
|
|
invalid_workflow["triggers"] = [{"nodeId": "node-1"}] # missing kind
|
|
assert not N8NWorkflow.validate(invalid_workflow)
|
|
|
|
# Multiple triggers
|
|
workflow_multiple_triggers = valid_workflow_with_triggers.copy()
|
|
workflow_multiple_triggers["triggers"] = [
|
|
{"nodeId": "webhook-1", "kind": "webhook"},
|
|
{"nodeId": "schedule-1", "kind": "schedule"},
|
|
{"nodeId": "email-1", "kind": "email", "enabled": False}
|
|
]
|
|
assert N8NWorkflow.validate(workflow_multiple_triggers)
|