# End-to-End Integration Testing

**Status**: 🔄 In Progress - Tier 3 (62% Complete)  
**Last Updated**: 2026-01-24  
**Purpose**: Comprehensive integration testing across all 5 Attune services

> **🆕 API Client Migration**: Tests now use auto-generated OpenAPI client for improved type safety and maintainability. See [`MIGRATION_TO_GENERATED_CLIENT.md`](MIGRATION_TO_GENERATED_CLIENT.md) for details.

**Test Coverage:**
- ✅ **Tier 1**: Complete (8 scenarios, 33 tests) - Core automation flows
- ✅ **Tier 2**: Complete (13 scenarios, 37 tests) - Orchestration & data flow
- 🔄 **Tier 3**: 62% Complete (13/21 scenarios, 40 tests) - Advanced features & edge cases

---

## Overview

This directory contains end-to-end integration tests that verify the complete Attune automation platform works correctly when all services are running together.

### API Client

Tests use an **auto-generated Python client** created from the Attune API's OpenAPI specification:
- **Generated Client**: `tests/generated_client/` - 71 endpoints, 200+ Pydantic models
- **Wrapper Client**: `tests/helpers/client_wrapper.py` - Backward-compatible interface
- **Benefits**: Type safety, automatic schema sync, reduced maintenance

For migration details and usage examples, see [`MIGRATION_TO_GENERATED_CLIENT.md`](MIGRATION_TO_GENERATED_CLIENT.md).

### Test Scope

**Services Under Test:**
1. **API Service** (`attune-api`) - REST API gateway
2. **Executor Service** (`attune-executor`) - Orchestration & scheduling
3. **Worker Service** (`attune-worker`) - Action execution
4. **Sensor Service** (`attune-sensor`) - Event monitoring
5. **Notifier Service** (`attune-notifier`) - Real-time notifications

**External Dependencies:**
- PostgreSQL (database)
- RabbitMQ (message queue)
- Redis (optional cache)

---

## Test Organization

Tests are organized into three tiers based on priority and complexity:

### **Tier 1: Core Automation Flows** ✅ COMPLETE
Essential MVP functionality - timer, webhook, workflow, datastore, multi-tenancy, failure handling.
- **Location**: `tests/e2e/tier1/`
- **Count**: 8 scenarios, 33 test functions
- **Duration**: ~4 minutes total

### **Tier 2: Orchestration & Data Flow** ✅ COMPLETE  
Advanced orchestration - nested workflows, datastore writes, criteria, inquiries, retry policies.
- **Location**: `tests/e2e/tier2/`
- **Count**: 13 scenarios, 37 test functions
- **Duration**: ~6 minutes total

### **Tier 3: Advanced Features & Edge Cases** 🔄 IN PROGRESS (62%)
Security, edge cases, notifications, container runner, log limits, crash recovery.
- **Location**: `tests/e2e/tier3/`
- **Count**: 13/21 scenarios complete, 40 test functions
- **Duration**: ~8 minutes (when complete)

**Completed T3 Scenarios:**
- T3.1: Date Timer with Past Date (3 tests) ⏱️
- T3.2: Timer Cancellation (3 tests) ⏱️
- T3.3: Multiple Concurrent Timers (3 tests) ⏱️
- T3.4: Webhook with Multiple Rules (2 tests) 🔗
- T3.5: Webhook with Rule Criteria Filtering (4 tests) 🎯
- T3.10: RBAC Permission Checks (4 tests) 🔒
- T3.11: System vs User Packs (4 tests) 🔒
- T3.13: Invalid Action Parameters (4 tests) ⚠️
- T3.14: Execution Completion Notifications (4 tests) 🔔
- T3.15: Inquiry Creation Notifications (4 tests) 🔔
- T3.17: Container Runner Execution (4 tests) 🐳
- T3.18: HTTP Runner Execution (4 tests) 🌐
- T3.20: Secret Injection Security (4 tests) 🔐
- T3.21: Action Log Size Limits (4 tests) 📝

**Remaining T3 Scenarios:**
- T3.6: Sensor-generated custom events
- T3.7: Complex workflow orchestration
- T3.8: Chained webhook triggers
- T3.9: Multi-step approval workflow
- T3.12: Worker crash recovery
- T3.16: Rule trigger notifications
- T3.19: Dependency conflict isolation

---

## Running Tests

### Quick Start

```bash
# Run all tests
./tests/run_e2e_tests.sh

# Run specific tier
pytest tests/e2e/tier1/
pytest tests/e2e/tier2/
pytest tests/e2e/tier3/

# Run by marker
pytest -m "tier1"
pytest -m "tier3 and notifications"
pytest -m "container"
```

### Prerequisites

1. **Start all services**:
   ```bash
   docker-compose up -d postgres rabbitmq redis
   cargo run --bin attune-api &
   cargo run --bin attune-executor &
   cargo run --bin attune-worker &
   cargo run --bin attune-sensor &
   cargo run --bin attune-notifier &
   ```

2. **Install test dependencies**:
   ```bash
   cd tests
   pip install -r requirements.txt
   ```

3. **Verify services are healthy**:
   ```bash
   curl http://localhost:8080/health
   ```

---

## Example Test Scenarios

### Scenario 1: Basic Timer Automation
**Duration**: ~30 seconds  
**Flow**: Timer → Event → Rule → Enforcement → Execution → Completion

**Steps:**
1. Create a pack via API
2. Create a timer trigger (fires every 10 seconds)
3. Create a simple echo action
4. Create a rule linking trigger to action
5. Sensor detects timer and generates event
6. Rule evaluates and creates enforcement
7. Executor schedules execution
8. Worker executes action
9. Verify execution completed successfully

**Success Criteria:**
- ✅ Event created within 10 seconds
- ✅ Enforcement created with correct rule_id
- ✅ Execution scheduled with correct action_ref
- ✅ Execution status progresses: requested → scheduled → running → succeeded
- ✅ Worker logs action output
- ✅ Completion notification sent back to executor
- ✅ No errors in any service logs

---

### Scenario 2: Workflow Execution
**Duration**: ~45 seconds  
**Flow**: Manual trigger → Workflow with 3 tasks → All tasks complete

**Steps:**
1. Create a workflow with sequential tasks:
   - Task 1: Echo "Starting workflow"
   - Task 2: Wait 2 seconds
   - Task 3: Echo "Workflow complete"
2. Trigger workflow execution via API
3. Monitor task execution order
4. Verify task outputs and variables

**Success Criteria:**
- ✅ Workflow execution created
- ✅ Tasks execute in correct order (sequential)
- ✅ Task 1 completes before Task 2 starts
- ✅ Task 2 completes before Task 3 starts
- ✅ Workflow variables propagate correctly
- ✅ Workflow status becomes 'succeeded'
- ✅ All task outputs captured

---

### Scenario 3: FIFO Queue Ordering
**Duration**: ~20 seconds  
**Flow**: Multiple executions with concurrency limit

**Steps:**
1. Create action with concurrency policy (max=1)
2. Submit 5 execution requests rapidly
3. Monitor execution order
4. Verify FIFO ordering maintained

**Success Criteria:**
- ✅ Executions enqueued in submission order
- ✅ Only 1 execution runs at a time
- ✅ Next execution starts after previous completes
- ✅ Queue stats accurate (queue_length, active_count)
- ✅ All 5 executions complete successfully
- ✅ Order preserved: exec1 → exec2 → exec3 → exec4 → exec5

---

### Scenario 4: Secret Management
**Duration**: ~15 seconds  
**Flow**: Action uses secrets securely

**Steps:**
1. Create a secret/key via API
2. Create action that uses the secret
3. Execute action
4. Verify secret injected via stdin (not env vars)
5. Check process environment doesn't contain secret

**Success Criteria:**
- ✅ Secret created and stored encrypted
- ✅ Worker retrieves secret for execution
- ✅ Secret passed via stdin to action
- ✅ Secret NOT in process environment
- ✅ Secret NOT in execution logs
- ✅ Action can access secret via get_secret() helper

---

### Scenario 5: Human-in-the-Loop (Inquiry)
**Duration**: ~30 seconds  
**Flow**: Action requests user input → Execution pauses → User responds → Execution resumes

**Steps:**
1. Create action that creates an inquiry
2. Execute action
3. Verify execution pauses with status 'paused'
4. Submit inquiry response via API
5. Verify execution resumes and completes

**Success Criteria:**
- ✅ Inquiry created with correct prompt
- ✅ Execution status changes to 'paused'
- ✅ Inquiry status is 'pending'
- ✅ Response submission updates inquiry
- ✅ Execution resumes after response
- ✅ Action receives response data
- ✅ Execution completes successfully

---

### Scenario 6: Error Handling & Recovery
**Duration**: ~25 seconds  
**Flow**: Action fails → Retry logic → Final failure

**Steps:**
1. Create action that always fails
2. Configure retry policy (max_retries=2)
3. Execute action
4. Monitor retry attempts
5. Verify final failure status

**Success Criteria:**
- ✅ Action fails on first attempt
- ✅ Executor retries execution
- ✅ Action fails on second attempt
- ✅ Executor retries again
- ✅ Action fails on third attempt
- ✅ Execution status becomes 'failed'
- ✅ Retry count accurate (3 total attempts)
- ✅ Error message captured

---

### Scenario 7: Real-Time Notifications
**Duration**: ~20 seconds  
**Flow**: Execution state changes → Notifications sent → WebSocket clients receive updates

**Steps:**
1. Connect WebSocket client to notifier
2. Create and execute action
3. Monitor notifications for state changes
4. Verify notification delivery

**Success Criteria:**
- ✅ WebSocket connection established
- ✅ Notification on execution created
- ✅ Notification on execution scheduled
- ✅ Notification on execution running
- ✅ Notification on execution succeeded
- ✅ All notifications contain correct entity_id
- ✅ Notifications delivered in real-time (<100ms)

---

### Scenario 8: Dependency Isolation
**Duration**: ~40 seconds  
**Flow**: Two packs with conflicting dependencies execute correctly

**Steps:**
1. Create Pack A with Python dependency: requests==2.25.0
2. Create Pack B with Python dependency: requests==2.28.0
3. Create actions in both packs
4. Execute both actions
5. Verify correct dependency versions used

**Success Criteria:**
- ✅ Pack A venv created with requests 2.25.0
- ✅ Pack B venv created with requests 2.28.0
- ✅ Pack A action uses correct venv
- ✅ Pack B action uses correct venv
- ✅ Both executions succeed
- ✅ No dependency conflicts

---

## Test Infrastructure

### Prerequisites

**Required Services:**
```bash
# PostgreSQL
docker run -d --name postgres \
  -e POSTGRES_PASSWORD=postgres \
  -p 5432:5432 \
  postgres:14

# RabbitMQ
docker run -d --name rabbitmq \
  -p 5672:5672 \
  -p 15672:15672 \
  rabbitmq:3-management

# Optional: Redis
docker run -d --name redis \
  -p 6379:6379 \
  redis:7
```

**Database Setup:**
```bash
# Create test database
createdb attune_e2e

# Run migrations
export DATABASE_URL="postgresql://postgres:postgres@localhost:5432/attune_e2e"
sqlx migrate run
```

### Service Configuration

**Config File**: `config.e2e.yaml`
```yaml
environment: test
packs_base_dir: ./tests/fixtures/packs

database:
  url: "postgresql://postgres:postgres@localhost:5432/attune_e2e"
  max_connections: 5

message_queue:
  url: "amqp://guest:guest@localhost:5672/%2F"
  
security:
  jwt_secret: "test-secret-for-e2e-testing-only"
  
server:
  host: "127.0.0.1"
  port: 18080  # Different port for E2E tests

worker:
  runtimes:
    - name: "python3"
      type: "python"
      python_path: "/usr/bin/python3"
    - name: "shell"
      type: "shell"
      shell_path: "/bin/bash"

executor:
  default_execution_timeout: 300
  
sensor:
  poll_interval_seconds: 5
  timer_precision_seconds: 1
```

---

## Running Tests

### Option 1: Manual Service Start

**Terminal 1 - API:**
```bash
cd crates/api
ATTUNE__CONFIG_FILE=../../config.e2e.yaml cargo run
```

**Terminal 2 - Executor:**
```bash
cd crates/executor
ATTUNE__CONFIG_FILE=../../config.e2e.yaml cargo run
```

**Terminal 3 - Worker:**
```bash
cd crates/worker
ATTUNE__CONFIG_FILE=../../config.e2e.yaml cargo run
```

**Terminal 4 - Sensor:**
```bash
cd crates/sensor
ATTUNE__CONFIG_FILE=../../config.e2e.yaml cargo run
```

**Terminal 5 - Notifier:**
```bash
cd crates/notifier
ATTUNE__CONFIG_FILE=../../config.e2e.yaml cargo run
```

**Terminal 6 - Run Tests:**
```bash
cd tests
cargo test --test e2e_*
```

---

### Option 2: Automated Test Runner (TODO)

```bash
# Start all services in background
./tests/scripts/start-services.sh

# Run tests
./tests/scripts/run-e2e-tests.sh

# Stop services
./tests/scripts/stop-services.sh
```

---

### Option 3: Docker Compose (TODO)

```bash
# Start all services
docker-compose -f docker-compose.e2e.yaml up -d

# Run tests
docker-compose -f docker-compose.e2e.yaml run --rm test

# Cleanup
docker-compose -f docker-compose.e2e.yaml down
```

---

## Test Implementation

### Test Structure

```
tests/
├── README.md                    # This file
├── config.e2e.yaml             # E2E test configuration
├── fixtures/                   # Test data
│   ├── packs/                  # Test packs
│   │   ├── test_pack/
│   │   │   ├── pack.yaml
│   │   │   ├── actions/
│   │   │   │   ├── echo.yaml
│   │   │   │   └── echo.py
│   │   │   └── workflows/
│   │   │       └── simple.yaml
│   └── seed_data.sql          # Initial test data
├── helpers/                    # Test utilities
│   ├── mod.rs
│   ├── api_client.rs          # API client wrapper
│   ├── service_manager.rs     # Start/stop services
│   └── assertions.rs          # Custom assertions
└── integration/               # Test files
    ├── test_timer_automation.rs
    ├── test_workflow_execution.rs
    ├── test_fifo_ordering.rs
    ├── test_secret_management.rs
    ├── test_inquiry_flow.rs
    ├── test_error_handling.rs
    ├── test_notifications.rs
    └── test_dependency_isolation.rs
```

---

## Debugging Failed Tests

### Check Service Logs

```bash
# API logs
tail -f logs/api.log

# Executor logs
tail -f logs/executor.log

# Worker logs
tail -f logs/worker.log

# Sensor logs
tail -f logs/sensor.log

# Notifier logs
tail -f logs/notifier.log
```

### Check Database State

```sql
-- Check executions
SELECT id, action_ref, status, created, updated 
FROM attune.execution 
ORDER BY created DESC 
LIMIT 10;

-- Check events
SELECT id, trigger, payload, created 
FROM attune.event 
ORDER BY created DESC 
LIMIT 10;

-- Check enforcements
SELECT id, rule, event, status, created 
FROM attune.enforcement 
ORDER BY created DESC 
LIMIT 10;

-- Check queue stats
SELECT action_id, queue_length, active_count, max_concurrent
FROM attune.queue_stats;
```

### Check Message Queue

```bash
# RabbitMQ Management UI
open http://localhost:15672
# Login: guest/guest

# Check queues
rabbitmqadmin list queues name messages

# Purge queue (if needed)
rabbitmqadmin purge queue name=executor.enforcement
```

---

## Common Issues

### Issue: Services can't connect to database
**Solution:**
- Verify PostgreSQL is running: `psql -U postgres -c "SELECT 1"`
- Check DATABASE_URL in config
- Ensure migrations ran: `sqlx migrate info`

### Issue: Services can't connect to RabbitMQ
**Solution:**
- Verify RabbitMQ is running: `rabbitmqctl status`
- Check message_queue URL in config
- Verify RabbitMQ user/vhost exists

### Issue: Worker can't execute actions
**Solution:**
- Check Python path in config
- Verify test pack exists: `ls tests/fixtures/packs/test_pack`
- Check worker logs for runtime errors

### Issue: Tests timeout
**Solution:**
- Increase timeout in test
- Check if services are actually running
- Verify message queue messages are being consumed

### Issue: Timer doesn't fire
**Solution:**
- Verify sensor service is running
- Check sensor poll interval in config
- Look for timer trigger in database: `SELECT * FROM attune.trigger WHERE type = 'timer'`

---

## Success Criteria

A successful integration test run should show:

✅ All services start without errors  
✅ Services establish database connections  
✅ Services connect to message queue  
✅ API endpoints respond correctly  
✅ Timer triggers fire on schedule  
✅ Events generate from triggers  
✅ Rules evaluate correctly  
✅ Enforcements create executions  
✅ Executions reach workers  
✅ Workers execute actions successfully  
✅ Results propagate back through system  
✅ Notifications delivered in real-time  
✅ All 8 test scenarios pass  
✅ No errors in service logs  
✅ Clean shutdown of all services  

---

## Next Steps

### Phase 1: Setup (Current)
- [x] Document test plan
- [ ] Create config.e2e.yaml
- [ ] Create test fixtures
- [ ] Set up test infrastructure

### Phase 2: Basic Tests
- [ ] Implement timer automation test
- [ ] Implement workflow execution test
- [ ] Implement FIFO ordering test

### Phase 3: Advanced Tests
- [ ] Implement secret management test
- [ ] Implement inquiry flow test
- [ ] Implement error handling test

### Phase 4: Real-time & Performance
- [ ] Implement notification test
- [ ] Implement dependency isolation test
- [ ] Add performance benchmarks

### Phase 5: Automation
- [ ] Create service start/stop scripts
- [ ] Create automated test runner
- [ ] Set up CI/CD integration

---

## Contributing

When adding new integration tests:

1. **Document the scenario** in this README
2. **Create test fixtures** if needed
3. **Write the test** with clear assertions
4. **Test locally** with all services running
5. **Update CI configuration** if needed

---

## Resources

- [Architecture Documentation](../docs/architecture.md)
- [Service Documentation](../docs/)
- [API Documentation](../docs/api-*.md)
- [Workflow Documentation](../docs/workflow-orchestration.md)
- [Queue Documentation](../docs/queue-architecture.md)

---

**Status**: 🔄 In Progress  
**Current Phase**: Phase 1 - Setup  
**Next Milestone**: First test scenario passing