Files
2026-05-08 01:59:04 +02:00

5.7 KiB

Dirigent Protocol Tests

This directory contains comprehensive tests for the Dirigent protocol and OpenCode adapter.

Test Files

protocol_tests.rs

Core protocol translation tests that verify OpenCode events are correctly translated to Dirigent protocol events.

Coverage:

  • Session creation and updates
  • User and assistant messages
  • Message parts (text, thinking, tool)
  • Event stream parsing
  • Protocol serialization/deserialization

Run: cargo test --test protocol_tests

deduplication_tests.rs

Tests for the stateful adapter's deduplication logic, ensuring no duplicate messages or parts appear in the UI.

Coverage:

  • Duplicate MessageStarted filtering
  • Duplicate MessageCompleted filtering
  • Part completion signal (delta: null) filtering
  • Different part types not being filtered
  • Streaming part updates working correctly
  • Full tit-tat conversation flow
  • Adapter state independence

Run: cargo test --test deduplication_tests

session_list_tests.rs

Tests for parsing OpenCode session list responses.

Coverage:

  • Session list array parsing
  • Empty session list handling
  • Single session deserialization
  • Optional fields handling
  • Timestamp parsing validation

Run: cargo test --test session_list_tests

Fixtures

fixtures/sample_events.jsonl

Sample OpenCode SSE events in JSONL format (one event per line). Used for parsing validation and event stream testing.

fixtures/opencode_session_response.json

Real OpenCode session list response. Used for session deserialization tests.

Source: Copied from /docs/building/opencode_session_response.json

Running All Tests

# Run all protocol tests
cargo test --package dirigent_protocol

# Run with output
cargo test --package dirigent_protocol -- --nocapture

# Run specific test
cargo test --package dirigent_protocol test_tit_tat_flow

# Run tests matching pattern
cargo test --package dirigent_protocol duplicate

Adding New Tests

For OpenCode Event Translation

Add to protocol_tests.rs:

#[test]
fn test_translate_new_feature() {
    let adapter = OpenCodeAdapter::new();

    // Create OpenCode event
    let oc_event = oc::Event::YourEvent { ... };

    // Translate
    let result = adapter.translate_event(oc_event);

    // Assert
    assert!(result.is_ok());
    match result.unwrap() {
        Event::YourDirigentEvent(data) => {
            assert_eq!(data.field, expected_value);
        }
        _ => panic!("Expected YourDirigentEvent"),
    }
}

For Deduplication Logic

Add to deduplication_tests.rs:

#[test]
fn test_new_deduplication_rule() {
    let adapter = OpenCodeAdapter::new();

    // Send first event
    let result1 = adapter.translate_event(first_event);
    assert!(result1.is_ok());

    // Send duplicate event
    let result2 = adapter.translate_event(duplicate_event);
    assert!(result2.is_err());
    assert!(matches!(result2.unwrap_err(), TranslationError::Duplicate));
}

For New Fixtures

  1. Place fixture file in tests/fixtures/
  2. Use include_str! to load it:
    let fixture = include_str!("fixtures/your_file.json");
    

Test Principles

Stateful Adapter Pattern

⚠️ IMPORTANT: The adapter maintains state, so:

// ✅ CORRECT: One adapter for entire event stream
let adapter = OpenCodeAdapter::new();
for event in events {
    adapter.translate_event(event);
}

// ❌ WRONG: New adapter each time (loses state!)
for event in events {
    let adapter = OpenCodeAdapter::new();
    adapter.translate_event(event);
}

Testing Duplicates

When testing deduplication:

  1. Send the first event → should succeed
  2. Send the duplicate event → should fail with TranslationError::Duplicate
  3. Always use the SAME adapter instance

Real-World Fixtures

Fixtures should come from actual OpenCode API responses when possible:

  • Captures real-world edge cases
  • Ensures compatibility with API changes
  • Documents actual behavior

CI Integration

These tests run automatically on:

  • Every commit (via cargo test)
  • Pull requests
  • Before releases

Status: All tests should pass before merging.

Coverage Report

# Install tarpaulin for coverage
cargo install cargo-tarpaulin

# Generate coverage report
cargo tarpaulin --package dirigent_protocol --out Html

Test Statistics

Last Updated: 2025-11-01

  • Total Tests: 24
  • Deduplication Tests: 7
  • Session Tests: 5
  • Protocol Tests: 12
  • All Passing:

Troubleshooting

Test Fails with "argument #1 of type &OpenCodeAdapter is missing"

Problem: You're calling OpenCodeAdapter::translate_event(event) as a static method.

Solution: Create an adapter instance first:

let adapter = OpenCodeAdapter::new();
let result = adapter.translate_event(event);

Test Fails with "pattern does not mention field part_id"

Problem: The MessagePartAdded event now includes a part_id field.

Solution: Update your pattern match:

// Before
Event::MessagePartAdded { message_id, part, delta } => { ... }

// After
Event::MessagePartAdded { message_id, part_id: _, part, delta } => { ... }

Deduplication Test Unexpectedly Passes

Problem: You're creating a new adapter for each event.

Solution: Create ONE adapter and reuse it:

let adapter = OpenCodeAdapter::new();
adapter.translate_event(event1); // First time
adapter.translate_event(event1); // Should be duplicate!