-
-
Notifications
You must be signed in to change notification settings - Fork 2k
Description
Problem
Issue #431 (description field causing API errors) wasn't caught by our existing test suite. After analysis, we identified several critical gaps in our integration test coverage that allowed this bug to slip through.
Root Causes
1. Missing GET-then-UPDATE Round-Trip Pattern
Our integration tests cherry-pick fields instead of testing the common spread operator pattern:
What we test:
const current = await client.getWorkflow(id);
await updateWorkflow(id, {
name: current.name,
nodes: current.nodes,
connections: current.connections
});What we DON'T test (but users commonly do):
const current = await client.getWorkflow(id);
await updateWorkflow(id, {
...current, // Spread includes ALL fields including description
name: 'New Name'
});2. n8n API Asymmetric Contract Not Tested
The n8n API has quirks we don't explicitly test:
- GET returns
descriptionfield ✅ - PUT/PATCH rejects
descriptionfield ❌ - PUT/PATCH requires
settingsfield ✅ - But empty
settings: {}is rejected ❌
3. Missing Minimal Payload Tests
No tests verify updates with absolute minimum required fields (name, nodes, connections only).
4. API Constraints Not Explicitly Validated
We test our cleaning logic but don't explicitly test that the API rejects/requires specific fields.
Proposed Solution
Add comprehensive integration tests for common real-world patterns:
Test Suite 1: GET-UPDATE Round Trip
describe('GET-UPDATE Round Trip', () => {
it('should handle workflow returned from GET in UPDATE', async () => {
const workflow = await client.getWorkflow(id);
// Should clean description and other read-only fields
await client.updateWorkflow(id, workflow);
});
it('should handle workflow with spread operator', async () => {
const workflow = await client.getWorkflow(id);
await client.updateWorkflow(id, {
...workflow,
name: 'Updated Name'
});
});
it('should handle partial updates with spread', async () => {
const workflow = await client.getWorkflow(id);
await client.updateWorkflow(id, {
...workflow,
settings: {
...workflow.settings,
timezone: 'UTC'
}
});
});
});Test Suite 2: n8n API Constraint Testing
describe('n8n API Constraints', () => {
it('should handle description field (read-only in updates)', async () => {
const workflow = await client.getWorkflow(id);
// Verify description is present in GET
expect(workflow.description).toBeDefined();
// Update with description should work (auto-cleaned)
await client.updateWorkflow(id, {
...workflow,
description: 'New description'
});
});
it('should provide settings when not explicitly provided', async () => {
const workflow = await client.getWorkflow(id);
// Update without settings should auto-add minimal defaults
await client.updateWorkflow(id, {
name: workflow.name,
nodes: workflow.nodes,
connections: workflow.connections
// No settings provided
});
});
it('should handle all read-only fields gracefully', async () => {
const workflow = await client.getWorkflow(id);
// Include all read-only fields - should be auto-cleaned
await client.updateWorkflow(id, {
...workflow,
createdAt: 'invalid',
updatedAt: 'invalid',
versionId: 'invalid',
active: true,
// All should be filtered out
});
});
});Test Suite 3: Minimal Payload Testing
describe('Minimal Updates', () => {
it('should update with only required fields', async () => {
const current = await client.getWorkflow(id);
await client.updateWorkflow(id, {
name: current.name,
nodes: current.nodes,
connections: current.connections
// Absolute minimum - settings added automatically
});
});
it('should update with minimal changes', async () => {
const current = await client.getWorkflow(id);
await client.updateWorkflow(id, {
name: 'New Name',
nodes: current.nodes,
connections: current.connections
});
});
});Test Suite 4: Edge Cases
describe('Edge Cases', () => {
it('should handle workflow with only filtered-out settings', async () => {
await client.updateWorkflow(id, {
name: 'Test',
nodes: [...],
connections: {},
settings: {
callerPolicy: 'value', // Will be filtered out
// Should add minimal defaults when all filtered
}
});
});
it('should preserve valid settings while filtering unsafe ones', async () => {
await client.updateWorkflow(id, {
name: 'Test',
nodes: [...],
connections: {},
settings: {
executionOrder: 'v1', // Valid - keep
callerPolicy: 'value', // Invalid - filter
timezone: 'UTC' // Valid - keep
}
});
});
});Acceptance Criteria
- Add GET-UPDATE round-trip tests (3 tests)
- Add n8n API constraint tests (3 tests)
- Add minimal payload tests (2 tests)
- Add edge case tests (2 tests)
- All new tests pass in CI
- Document n8n API quirks in test comments
- Update test documentation/README
Additional Notes
These tests would have caught:
- Issue Codex Update Partial Workflow repeated Failure #431 (description field error)
- The follow-up issue (missing settings requirement)
- Future API contract changes
Estimated effort: 2-3 hours
Related Issues
- Codex Update Partial Workflow repeated Failure #431 - Description field causing API errors
- PR fix: resolve empty settings validation error in workflow updates (#431) #432 - Fix for issue Codex Update Partial Workflow repeated Failure #431
Conceived by Romuald Członkowski - https://www.aiadvisors.pl/en