re-uploading work
This commit is contained in:
797
crates/common/tests/event_repository_tests.rs
Normal file
797
crates/common/tests/event_repository_tests.rs
Normal file
@@ -0,0 +1,797 @@
|
||||
//! Integration tests for Event repository
|
||||
//!
|
||||
//! These tests verify CRUD operations, queries, and constraints
|
||||
//! for the Event repository.
|
||||
|
||||
mod helpers;
|
||||
|
||||
use attune_common::{
|
||||
repositories::{
|
||||
event::{CreateEventInput, EventRepository, UpdateEventInput},
|
||||
Create, Delete, FindById, List, Update,
|
||||
},
|
||||
Error,
|
||||
};
|
||||
use helpers::*;
|
||||
use serde_json::json;
|
||||
|
||||
// ============================================================================
|
||||
// CREATE Tests
|
||||
// ============================================================================
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_event_minimal() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
// Create a trigger for the event
|
||||
let pack = PackFixture::new_unique("event_pack")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let trigger = TriggerFixture::new_unique(Some(pack.id), Some(pack.r#ref.clone()), "webhook")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Create event with minimal fields
|
||||
let input = CreateEventInput {
|
||||
trigger: Some(trigger.id),
|
||||
trigger_ref: trigger.r#ref.clone(),
|
||||
config: None,
|
||||
payload: None,
|
||||
source: None,
|
||||
source_ref: None,
|
||||
rule: None,
|
||||
rule_ref: None,
|
||||
};
|
||||
|
||||
let event = EventRepository::create(&pool, input).await.unwrap();
|
||||
|
||||
assert!(event.id > 0);
|
||||
assert_eq!(event.trigger, Some(trigger.id));
|
||||
assert_eq!(event.trigger_ref, trigger.r#ref);
|
||||
assert_eq!(event.config, None);
|
||||
assert_eq!(event.payload, None);
|
||||
assert_eq!(event.source, None);
|
||||
assert_eq!(event.source_ref, None);
|
||||
assert!(event.created.timestamp() > 0);
|
||||
assert!(event.updated.timestamp() > 0);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_event_with_payload() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
let pack = PackFixture::new_unique("payload_pack")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let trigger = TriggerFixture::new_unique(Some(pack.id), Some(pack.r#ref.clone()), "webhook")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let payload = json!({
|
||||
"webhook_url": "https://example.com/webhook",
|
||||
"method": "POST",
|
||||
"headers": {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
"body": {
|
||||
"message": "Test event"
|
||||
}
|
||||
});
|
||||
|
||||
let input = CreateEventInput {
|
||||
trigger: Some(trigger.id),
|
||||
trigger_ref: trigger.r#ref.clone(),
|
||||
config: None,
|
||||
payload: Some(payload.clone()),
|
||||
source: None,
|
||||
source_ref: None,
|
||||
rule: None,
|
||||
rule_ref: None,
|
||||
};
|
||||
|
||||
let event = EventRepository::create(&pool, input).await.unwrap();
|
||||
|
||||
assert_eq!(event.payload, Some(payload));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_event_with_config() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
let pack = PackFixture::new_unique("config_pack")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let trigger = TriggerFixture::new_unique(Some(pack.id), Some(pack.r#ref.clone()), "timer")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let config = json!({
|
||||
"interval": "5m",
|
||||
"timezone": "UTC"
|
||||
});
|
||||
|
||||
let input = CreateEventInput {
|
||||
trigger: Some(trigger.id),
|
||||
trigger_ref: trigger.r#ref.clone(),
|
||||
config: Some(config.clone()),
|
||||
payload: None,
|
||||
source: None,
|
||||
source_ref: None,
|
||||
rule: None,
|
||||
rule_ref: None,
|
||||
};
|
||||
|
||||
let event = EventRepository::create(&pool, input).await.unwrap();
|
||||
|
||||
assert_eq!(event.config, Some(config));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_event_without_trigger_id() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
// Events can be created without a trigger ID (trigger may have been deleted)
|
||||
let input = CreateEventInput {
|
||||
trigger: None,
|
||||
trigger_ref: "deleted.trigger".to_string(),
|
||||
config: None,
|
||||
payload: Some(json!({"reason": "trigger was deleted"})),
|
||||
source: None,
|
||||
source_ref: None,
|
||||
rule: None,
|
||||
rule_ref: None,
|
||||
};
|
||||
|
||||
let event = EventRepository::create(&pool, input).await.unwrap();
|
||||
|
||||
assert_eq!(event.trigger, None);
|
||||
assert_eq!(event.trigger_ref, "deleted.trigger");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_event_with_source() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
let pack = PackFixture::new_unique("source_pack")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let trigger = TriggerFixture::new_unique(Some(pack.id), Some(pack.r#ref.clone()), "webhook")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Create a sensor to reference as source
|
||||
// Note: We'd need a SensorFixture, but for now we'll just test with NULL source
|
||||
let input = CreateEventInput {
|
||||
trigger: Some(trigger.id),
|
||||
trigger_ref: trigger.r#ref.clone(),
|
||||
config: None,
|
||||
payload: None,
|
||||
source: None,
|
||||
source_ref: Some("test.sensor".to_string()),
|
||||
rule: None,
|
||||
rule_ref: None,
|
||||
};
|
||||
|
||||
let event = EventRepository::create(&pool, input).await.unwrap();
|
||||
|
||||
assert_eq!(event.source, None);
|
||||
assert_eq!(event.source_ref, Some("test.sensor".to_string()));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_create_event_with_invalid_trigger_fails() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
// Try to create event with non-existent trigger ID
|
||||
let input = CreateEventInput {
|
||||
trigger: Some(99999),
|
||||
trigger_ref: "nonexistent.trigger".to_string(),
|
||||
config: None,
|
||||
payload: None,
|
||||
source: None,
|
||||
source_ref: None,
|
||||
rule: None,
|
||||
rule_ref: None,
|
||||
};
|
||||
|
||||
let result = EventRepository::create(&pool, input).await;
|
||||
|
||||
assert!(result.is_err());
|
||||
// Foreign key constraint violation
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// READ Tests
|
||||
// ============================================================================
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_find_event_by_id() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
let pack = PackFixture::new_unique("find_pack")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let trigger = TriggerFixture::new_unique(Some(pack.id), Some(pack.r#ref.clone()), "webhook")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let created_event = EventFixture::new_unique(Some(trigger.id), &trigger.r#ref)
|
||||
.with_payload(json!({"test": "data"}))
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let found = EventRepository::find_by_id(&pool, created_event.id)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert!(found.is_some());
|
||||
let event = found.unwrap();
|
||||
assert_eq!(event.id, created_event.id);
|
||||
assert_eq!(event.trigger, created_event.trigger);
|
||||
assert_eq!(event.trigger_ref, created_event.trigger_ref);
|
||||
assert_eq!(event.payload, created_event.payload);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_find_event_by_id_not_found() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
let result = EventRepository::find_by_id(&pool, 99999).await.unwrap();
|
||||
|
||||
assert!(result.is_none());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_event_by_id() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
let pack = PackFixture::new_unique("get_pack")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let trigger = TriggerFixture::new_unique(Some(pack.id), Some(pack.r#ref.clone()), "webhook")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let created_event = EventFixture::new_unique(Some(trigger.id), &trigger.r#ref)
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let event = EventRepository::get_by_id(&pool, created_event.id)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(event.id, created_event.id);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_get_event_by_id_not_found() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
let result = EventRepository::get_by_id(&pool, 99999).await;
|
||||
|
||||
assert!(result.is_err());
|
||||
assert!(matches!(result.unwrap_err(), Error::NotFound { .. }));
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// LIST Tests
|
||||
// ============================================================================
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_list_events_empty() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
let events = EventRepository::list(&pool).await.unwrap();
|
||||
// May have events from other tests, just verify we can list without error
|
||||
drop(events);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_list_events() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
let pack = PackFixture::new_unique("list_pack")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let trigger = TriggerFixture::new_unique(Some(pack.id), Some(pack.r#ref.clone()), "webhook")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let before_count = EventRepository::list(&pool).await.unwrap().len();
|
||||
|
||||
// Create multiple events
|
||||
let mut created_ids = vec![];
|
||||
for i in 0..3 {
|
||||
let event = EventFixture::new_unique(Some(trigger.id), &trigger.r#ref)
|
||||
.with_payload(json!({"index": i}))
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
created_ids.push(event.id);
|
||||
}
|
||||
|
||||
let events = EventRepository::list(&pool).await.unwrap();
|
||||
|
||||
assert!(events.len() >= before_count + 3);
|
||||
// Verify our events are in the list (should be at the top since ordered by created DESC)
|
||||
let our_events: Vec<_> = events
|
||||
.iter()
|
||||
.filter(|e| created_ids.contains(&e.id))
|
||||
.collect();
|
||||
assert_eq!(our_events.len(), 3);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_list_events_respects_limit() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
let pack = PackFixture::new_unique("limit_pack")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let _trigger = TriggerFixture::new_unique(Some(pack.id), Some(pack.r#ref.clone()), "webhook")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// List operation has a LIMIT of 1000, so it won't retrieve more than that
|
||||
let events = EventRepository::list(&pool).await.unwrap();
|
||||
assert!(events.len() <= 1000);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// UPDATE Tests
|
||||
// ============================================================================
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_update_event_config() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
let pack = PackFixture::new_unique("update_pack")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let trigger = TriggerFixture::new_unique(Some(pack.id), Some(pack.r#ref.clone()), "webhook")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let event = EventFixture::new_unique(Some(trigger.id), &trigger.r#ref)
|
||||
.with_config(json!({"old": "config"}))
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let new_config = json!({"new": "config", "updated": true});
|
||||
let input = UpdateEventInput {
|
||||
config: Some(new_config.clone()),
|
||||
payload: None,
|
||||
};
|
||||
|
||||
let updated = EventRepository::update(&pool, event.id, input)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(updated.id, event.id);
|
||||
assert_eq!(updated.config, Some(new_config));
|
||||
assert!(updated.updated > event.updated);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_update_event_payload() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
let pack = PackFixture::new_unique("payload_update_pack")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let trigger = TriggerFixture::new_unique(Some(pack.id), Some(pack.r#ref.clone()), "webhook")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let event = EventFixture::new_unique(Some(trigger.id), &trigger.r#ref)
|
||||
.with_payload(json!({"initial": "payload"}))
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let new_payload = json!({"updated": "payload", "version": 2});
|
||||
let input = UpdateEventInput {
|
||||
config: None,
|
||||
payload: Some(new_payload.clone()),
|
||||
};
|
||||
|
||||
let updated = EventRepository::update(&pool, event.id, input)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(updated.payload, Some(new_payload));
|
||||
assert!(updated.updated > event.updated);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_update_event_both_fields() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
let pack = PackFixture::new_unique("both_update_pack")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let trigger = TriggerFixture::new_unique(Some(pack.id), Some(pack.r#ref.clone()), "webhook")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let event = EventFixture::new_unique(Some(trigger.id), &trigger.r#ref)
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let new_config = json!({"setting": "value"});
|
||||
let new_payload = json!({"data": "value"});
|
||||
let input = UpdateEventInput {
|
||||
config: Some(new_config.clone()),
|
||||
payload: Some(new_payload.clone()),
|
||||
};
|
||||
|
||||
let updated = EventRepository::update(&pool, event.id, input)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(updated.config, Some(new_config));
|
||||
assert_eq!(updated.payload, Some(new_payload));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_update_event_no_changes() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
let pack = PackFixture::new_unique("nochange_pack")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let trigger = TriggerFixture::new_unique(Some(pack.id), Some(pack.r#ref.clone()), "webhook")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let event = EventFixture::new_unique(Some(trigger.id), &trigger.r#ref)
|
||||
.with_payload(json!({"test": "data"}))
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let input = UpdateEventInput {
|
||||
config: None,
|
||||
payload: None,
|
||||
};
|
||||
|
||||
let result = EventRepository::update(&pool, event.id, input)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Should return existing event without updating
|
||||
assert_eq!(result.id, event.id);
|
||||
assert_eq!(result.payload, event.payload);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_update_event_not_found() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
let input = UpdateEventInput {
|
||||
config: Some(json!({"test": "config"})),
|
||||
payload: None,
|
||||
};
|
||||
|
||||
let result = EventRepository::update(&pool, 99999, input).await;
|
||||
|
||||
// When updating non-existent entity with changes, SQLx returns RowNotFound error
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// DELETE Tests
|
||||
// ============================================================================
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_event() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
let pack = PackFixture::new_unique("delete_pack")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let trigger = TriggerFixture::new_unique(Some(pack.id), Some(pack.r#ref.clone()), "webhook")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let event = EventFixture::new_unique(Some(trigger.id), &trigger.r#ref)
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let deleted = EventRepository::delete(&pool, event.id).await.unwrap();
|
||||
|
||||
assert!(deleted);
|
||||
|
||||
// Verify it's gone
|
||||
let found = EventRepository::find_by_id(&pool, event.id).await.unwrap();
|
||||
assert!(found.is_none());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_event_not_found() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
let deleted = EventRepository::delete(&pool, 99999).await.unwrap();
|
||||
|
||||
assert!(!deleted);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_delete_event_sets_enforcement_event_to_null() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
// Create pack, trigger, action, rule, and event
|
||||
let pack = PackFixture::new_unique("cascade_pack")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let trigger = TriggerFixture::new_unique(Some(pack.id), Some(pack.r#ref.clone()), "webhook")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let action = ActionFixture::new_unique(pack.id, &pack.r#ref, "action")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Create a rule
|
||||
use attune_common::repositories::rule::{CreateRuleInput, RuleRepository};
|
||||
let rule = RuleRepository::create(
|
||||
&pool,
|
||||
CreateRuleInput {
|
||||
r#ref: format!("{}.test_rule", pack.r#ref),
|
||||
pack: pack.id,
|
||||
pack_ref: pack.r#ref.clone(),
|
||||
label: "Test Rule".to_string(),
|
||||
description: "Test".to_string(),
|
||||
action: action.id,
|
||||
action_ref: action.r#ref.clone(),
|
||||
trigger: trigger.id,
|
||||
trigger_ref: trigger.r#ref.clone(),
|
||||
conditions: json!({}),
|
||||
action_params: json!({}),
|
||||
trigger_params: json!({}),
|
||||
enabled: true,
|
||||
is_adhoc: false,
|
||||
},
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let event = EventFixture::new_unique(Some(trigger.id), &trigger.r#ref)
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Create enforcement referencing the event
|
||||
let enforcement = EnforcementFixture::new_unique(Some(rule.id), &rule.r#ref, &trigger.r#ref)
|
||||
.with_event(event.id)
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Delete the event - enforcement.event should be set to NULL (ON DELETE SET NULL)
|
||||
EventRepository::delete(&pool, event.id).await.unwrap();
|
||||
|
||||
// Enforcement should still exist but with NULL event
|
||||
use attune_common::repositories::event::EnforcementRepository;
|
||||
let found_enforcement = EnforcementRepository::find_by_id(&pool, enforcement.id)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(found_enforcement.event, None);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// SPECIALIZED QUERY Tests
|
||||
// ============================================================================
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_find_events_by_trigger() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
let pack = PackFixture::new_unique("trigger_query_pack")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let trigger1 = TriggerFixture::new_unique(Some(pack.id), Some(pack.r#ref.clone()), "webhook")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let trigger2 = TriggerFixture::new_unique(Some(pack.id), Some(pack.r#ref.clone()), "timer")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Create events for trigger1
|
||||
for i in 0..3 {
|
||||
EventFixture::new_unique(Some(trigger1.id), &trigger1.r#ref)
|
||||
.with_payload(json!({"trigger": 1, "index": i}))
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// Create events for trigger2
|
||||
for i in 0..2 {
|
||||
EventFixture::new_unique(Some(trigger2.id), &trigger2.r#ref)
|
||||
.with_payload(json!({"trigger": 2, "index": i}))
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let events = EventRepository::find_by_trigger(&pool, trigger1.id)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(events.len(), 3);
|
||||
for event in &events {
|
||||
assert_eq!(event.trigger, Some(trigger1.id));
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_find_events_by_trigger_ref() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
let pack = PackFixture::new_unique("triggerref_pack")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let trigger = TriggerFixture::new_unique(Some(pack.id), Some(pack.r#ref.clone()), "webhook")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Create events with a unique trigger_ref to avoid conflicts
|
||||
let unique_trigger_ref = trigger.r#ref.clone();
|
||||
for i in 0..3 {
|
||||
EventFixture::new(Some(trigger.id), &unique_trigger_ref)
|
||||
.with_payload(json!({"index": i}))
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
let events = EventRepository::find_by_trigger_ref(&pool, &unique_trigger_ref)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(events.len(), 3);
|
||||
for event in &events {
|
||||
assert_eq!(event.trigger_ref, unique_trigger_ref);
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_find_events_by_trigger_ref_preserves_after_trigger_deletion() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
let pack = PackFixture::new_unique("preserve_pack")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let trigger = TriggerFixture::new_unique(Some(pack.id), Some(pack.r#ref.clone()), "webhook")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let trigger_ref = trigger.r#ref.clone();
|
||||
|
||||
// Create event with the specific trigger_ref
|
||||
let event = EventFixture::new(Some(trigger.id), &trigger_ref)
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Delete the trigger (ON DELETE SET NULL on event.trigger)
|
||||
use attune_common::repositories::{trigger::TriggerRepository, Delete};
|
||||
TriggerRepository::delete(&pool, trigger.id).await.unwrap();
|
||||
|
||||
// Events should still be findable by trigger_ref even though trigger is deleted
|
||||
let events = EventRepository::find_by_trigger_ref(&pool, &trigger_ref)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(events.len(), 1);
|
||||
assert_eq!(events[0].id, event.id);
|
||||
assert_eq!(events[0].trigger, None); // trigger ID set to NULL
|
||||
assert_eq!(events[0].trigger_ref, trigger_ref); // trigger_ref preserved
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// TIMESTAMP Tests
|
||||
// ============================================================================
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_event_timestamps_auto_managed() {
|
||||
let pool = create_test_pool().await.unwrap();
|
||||
|
||||
let pack = PackFixture::new_unique("timestamp_pack")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let trigger = TriggerFixture::new_unique(Some(pack.id), Some(pack.r#ref.clone()), "webhook")
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let event = EventFixture::new_unique(Some(trigger.id), &trigger.r#ref)
|
||||
.create(&pool)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let created_time = event.created;
|
||||
let updated_time = event.updated;
|
||||
|
||||
assert!(created_time.timestamp() > 0);
|
||||
assert_eq!(created_time, updated_time);
|
||||
|
||||
// Update and verify timestamp changed
|
||||
tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
|
||||
|
||||
let input = UpdateEventInput {
|
||||
config: Some(json!({"updated": true})),
|
||||
payload: None,
|
||||
};
|
||||
|
||||
let updated = EventRepository::update(&pool, event.id, input)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(updated.created, created_time); // created unchanged
|
||||
assert!(updated.updated > updated_time); // updated changed
|
||||
}
|
||||
Reference in New Issue
Block a user