robson-core 0.1.0

Rust async agent orchestrator for automated development workflows
Documentation
use robson_core::process_event::Model as ProcessEvent;

async fn setup_db() -> sea_orm::DatabaseConnection {
    let db = robson_core::connect(":memory:").await.unwrap();
    robson_core::run_migrations(&db).await.unwrap();
    db
}

// ── ProcessEvent::find_undelivered ────────────────────────────────────────────

#[tokio::test]
async fn test_find_undelivered_returns_newly_inserted_event() {
    let db = setup_db().await;

    ProcessEvent::insert(&db, 0, "completed", "task done")
        .await
        .unwrap();

    let rows = ProcessEvent::find_undelivered(&db).await.unwrap();
    assert_eq!(rows.len(), 1);
    assert_eq!(rows[0].content, "task done");
    assert!(rows[0].delivered_at.is_none());
}

#[tokio::test]
async fn test_find_undelivered_excludes_already_delivered_events() {
    let db = setup_db().await;

    ProcessEvent::insert(&db, 0, "completed", "msg1")
        .await
        .unwrap();
    ProcessEvent::insert(&db, 0, "completed", "msg2")
        .await
        .unwrap();

    let rows = ProcessEvent::find_undelivered(&db).await.unwrap();
    let id_to_deliver = rows[0].id;

    ProcessEvent::mark_delivered(&db, id_to_deliver)
        .await
        .unwrap();

    let remaining = ProcessEvent::find_undelivered(&db).await.unwrap();
    assert_eq!(remaining.len(), 1);
    assert_eq!(remaining[0].content, "msg2");
}

#[tokio::test]
async fn test_find_undelivered_returns_empty_when_all_delivered() {
    let db = setup_db().await;

    ProcessEvent::insert(&db, 0, "completed", "only one")
        .await
        .unwrap();
    let rows = ProcessEvent::find_undelivered(&db).await.unwrap();
    ProcessEvent::mark_delivered(&db, rows[0].id).await.unwrap();

    let remaining = ProcessEvent::find_undelivered(&db).await.unwrap();
    assert!(remaining.is_empty());
}

// ── ProcessEvent::mark_delivered ─────────────────────────────────────────────

#[tokio::test]
async fn test_mark_delivered_sets_nonzero_timestamp() {
    let db = setup_db().await;

    ProcessEvent::insert(&db, 0, "completed", "hello")
        .await
        .unwrap();
    let rows = ProcessEvent::find_undelivered(&db).await.unwrap();
    let id = rows[0].id;

    ProcessEvent::mark_delivered(&db, id).await.unwrap();

    // Reload and verify delivered_at is set to a positive Unix epoch
    let all = ProcessEvent::find_by_conversation(&db, 0).await.unwrap();
    let event = all.iter().find(|r| r.id == id).unwrap();
    assert!(event.delivered_at.is_some());
    assert!(event.delivered_at.unwrap() > 0);
}

#[tokio::test]
async fn test_mark_delivered_does_not_affect_other_events() {
    let db = setup_db().await;

    ProcessEvent::insert(&db, 0, "completed", "first")
        .await
        .unwrap();
    ProcessEvent::insert(&db, 0, "completed", "second")
        .await
        .unwrap();

    let rows = ProcessEvent::find_undelivered(&db).await.unwrap();
    let first_id = rows[0].id;

    ProcessEvent::mark_delivered(&db, first_id).await.unwrap();

    let undelivered = ProcessEvent::find_undelivered(&db).await.unwrap();
    assert_eq!(undelivered.len(), 1);
    assert_eq!(undelivered[0].content, "second");
}

// ── UTF-8 / i18n ─────────────────────────────────────────────────────────────

#[tokio::test]
async fn test_process_event_content_supports_unicode() {
    let db = setup_db().await;

    let unicode_content = "タスク完了 — Tarea completada — مهمة مكتملة";
    ProcessEvent::insert(&db, 0, "completed", unicode_content)
        .await
        .unwrap();

    let rows = ProcessEvent::find_undelivered(&db).await.unwrap();
    assert_eq!(rows[0].content, unicode_content);
}