Skip to main content
Glama
event_controller_test.go8.36 kB
package tui import ( "testing" "time" tea "github.com/charmbracelet/bubbletea" "github.com/standardbeagle/brummer/internal/tui/system" "github.com/standardbeagle/brummer/pkg/events" "github.com/stretchr/testify/assert" ) func TestEventController_SystemMessages(t *testing.T) { // Setup - use real components instead of mocks updateChan := make(chan tea.Msg, 10) eventBus := events.NewEventBus() // Create a full test model with real components model := createTestModelWithDefaults() // Verify we're using the same eventBus t.Logf("Test eventBus: %p", eventBus) t.Logf("Model eventBus: %p", model.eventBus) // Replace model's eventBus with our test eventBus to ensure they're the same model.eventBus = eventBus model.updateChan = updateChan // Re-setup event subscriptions with the new eventBus model.eventController.eventBus = eventBus model.eventController.updateChan = updateChan model.setupEventSubscriptions() // EventController is now initialized as part of the model // Just verify the event flow works // Test system message events tests := []struct { name string level string message string expected string }{ { name: "info_message", level: "info", message: "Test info message", expected: "Test info message", }, { name: "error_message", level: "error", message: "Test error message", expected: "Test error message", }, { name: "warning_message", level: "warn", message: "Test warning message", expected: "Test warning message", }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Publish event using the correct API t.Logf("Publishing system.message event with level=%s, message=%s", tt.level, tt.message) eventBus.Publish(events.Event{ Type: events.EventType("system.message"), Data: map[string]interface{}{ "level": tt.level, "message": tt.message, "context": "Test", }, }) // Wait for message to be processed (increased timeout for goroutine execution) select { case msg := <-updateChan: t.Logf("Received message: %T", msg) sysMsg, ok := msg.(system.SystemMessageMsg) assert.True(t, ok, "Should receive SystemMessageMsg") assert.Equal(t, tt.level, sysMsg.Level) assert.Equal(t, tt.expected, sysMsg.Message) case <-time.After(500 * time.Millisecond): // Check if there are any messages in the channel select { case msg := <-updateChan: t.Logf("Late message received: %T", msg) default: t.Logf("No messages in channel") } t.Fatal("Timeout waiting for system message") } }) } } func TestEventController_ProcessEvents(t *testing.T) { // Setup - use real components instead of mocks updateChan := make(chan tea.Msg, 10) eventBus := events.NewEventBus() // Create a full test model with real components model := createTestModelWithDefaults() model.eventBus = eventBus model.updateChan = updateChan // Re-setup event subscriptions and update channel for event controller model.eventController.eventBus = eventBus model.eventController.updateChan = updateChan model.setupEventSubscriptions() // Test process lifecycle events (using actual event constants) processEvents := []events.EventType{ events.ProcessStarted, events.ProcessExited, events.LogLine, events.ErrorDetected, } for _, event := range processEvents { t.Run(string(event), func(t *testing.T) { // Publish event using the correct API eventBus.Publish(events.Event{ Type: event, Data: map[string]interface{}{ "processId": "test-123", "name": "test-process", }, }) // Wait for update message - different events send different message types select { case msg := <-updateChan: switch event { case events.ProcessStarted, events.ProcessExited: _, ok := msg.(processUpdateMsg) assert.True(t, ok, "Should receive processUpdateMsg for %s", event) case events.LogLine: _, ok := msg.(logUpdateMsg) assert.True(t, ok, "Should receive logUpdateMsg for %s", event) case events.ErrorDetected: _, ok := msg.(errorUpdateMsg) assert.True(t, ok, "Should receive errorUpdateMsg for %s", event) } case <-time.After(100 * time.Millisecond): t.Fatalf("Timeout waiting for update message from %s", event) } }) } } func TestEventController_LogEvents(t *testing.T) { // Setup - use real components instead of mocks updateChan := make(chan tea.Msg, 10) eventBus := events.NewEventBus() // Create a full test model with real components model := createTestModelWithDefaults() model.eventBus = eventBus model.updateChan = updateChan // Re-setup event subscriptions and update channel for event controller model.eventController.eventBus = eventBus model.eventController.updateChan = updateChan model.setupEventSubscriptions() // Test log event eventBus.Publish(events.Event{ Type: events.LogLine, Data: map[string]interface{}{ "processId": "test-456", "message": "Test log message", "isError": false, }, }) // Wait for update select { case msg := <-updateChan: _, ok := msg.(logUpdateMsg) assert.True(t, ok, "Should receive logUpdateMsg") case <-time.After(100 * time.Millisecond): t.Fatal("Timeout waiting for log update") } } func TestEventController_URLDetection(t *testing.T) { // Skip this test - url.detected event type doesn't exist in the current event system // URL detection happens differently in the current implementation t.Skip("URL detection uses a different mechanism - this event type doesn't exist") } func TestEventController_StartupMessage(t *testing.T) { // Setup - use real components instead of mocks updateChan := make(chan tea.Msg, 10) eventBus := events.NewEventBus() // Create a full test model with real components model := createTestModelWithDefaults() model.eventBus = eventBus model.updateChan = updateChan // Re-setup event subscriptions and update channel for event controller model.eventController.eventBus = eventBus model.eventController.updateChan = updateChan model.setupEventSubscriptions() // Send startup message model.eventController.SendStartupMessage() // Wait for message select { case msg := <-updateChan: sysMsg, ok := msg.(system.SystemMessageMsg) assert.True(t, ok, "Should receive SystemMessageMsg") assert.Equal(t, "info", sysMsg.Level) assert.Contains(t, sysMsg.Message, "Brummer started") case <-time.After(100 * time.Millisecond): t.Fatal("Timeout waiting for startup message") } } func TestEventController_EmptyMessage(t *testing.T) { // Setup - use real components instead of mocks updateChan := make(chan tea.Msg, 10) eventBus := events.NewEventBus() // Create a full test model with real components model := createTestModelWithDefaults() model.eventBus = eventBus model.updateChan = updateChan // Re-setup event subscriptions and update channel for event controller model.eventController.eventBus = eventBus model.eventController.updateChan = updateChan model.setupEventSubscriptions() // Publish event with empty message (should be ignored) eventBus.Publish(events.Event{ Type: events.EventType("system.message"), Data: map[string]interface{}{ "level": "info", "message": "", }, }) // Should not receive any message select { case <-updateChan: t.Fatal("Should not receive message for empty content") case <-time.After(50 * time.Millisecond): // Expected - no message sent } } func TestEventController_EventFlow(t *testing.T) { // This test verifies that events flow properly through the system // without needing to test internal implementation details // Setup - use real components model := createTestModelWithDefaults() updateChan := make(chan tea.Msg, 10) model.updateChan = updateChan // Also update the event controller's update channel to match model.eventController.updateChan = updateChan // Test that process events flow through the system model.eventBus.Publish(events.Event{ Type: events.EventType("process.started"), Data: map[string]interface{}{ "processId": "test-flow-123", "name": "test-flow", }, }) // Verify we get a process update message msg := waitForMessage[processUpdateMsg](t, updateChan, 100*time.Millisecond) assert.NotNil(t, msg, "Should receive process update message") }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/standardbeagle/brummer'

If you have feedback or need assistance with the MCP directory API, please join our Discord server