package domain import ( "testing" "time" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gitlab.com/unboundsoftware/eventsourced/eventsourced" ) func TestOrganizationAdded_UpdateOrganization(t *testing.T) { event := &OrganizationAdded{ BaseEvent: eventsourced.BaseEvent{ EventTime: eventsourced.EventTime{ Time: time.Now(), }, }, Name: "Test Organization", Initiator: "user@example.com", } org := &Organization{ BaseAggregate: eventsourced.BaseAggregateFromString("org-123"), } event.UpdateOrganization(org) assert.Equal(t, "Test Organization", org.Name) assert.Equal(t, []string{"user@example.com"}, org.Users) assert.Equal(t, "user@example.com", org.CreatedBy) assert.Equal(t, "user@example.com", org.ChangedBy) assert.Equal(t, event.When(), org.CreatedAt) assert.Equal(t, event.When(), org.ChangedAt) } func TestUserAddedToOrganization_UpdateOrganization(t *testing.T) { event := &UserAddedToOrganization{ BaseEvent: eventsourced.BaseEvent{ EventTime: eventsourced.EventTime{ Time: time.Now(), }, }, UserId: "new-user@example.com", Initiator: "admin@example.com", } org := &Organization{ BaseAggregate: eventsourced.BaseAggregateFromString("org-123"), Users: []string{"existing-user@example.com"}, } event.UpdateOrganization(org) assert.Len(t, org.Users, 2) assert.Contains(t, org.Users, "existing-user@example.com") assert.Contains(t, org.Users, "new-user@example.com") assert.Equal(t, "admin@example.com", org.ChangedBy) assert.Equal(t, event.When(), org.ChangedAt) } func TestUserAddedToOrganization_UpdateOrganization_DuplicateUser(t *testing.T) { event := &UserAddedToOrganization{ BaseEvent: eventsourced.BaseEvent{ EventTime: eventsourced.EventTime{ Time: time.Now(), }, }, UserId: "existing-user@example.com", Initiator: "admin@example.com", } org := &Organization{ BaseAggregate: eventsourced.BaseAggregateFromString("org-123"), Users: []string{"existing-user@example.com"}, ChangedBy: "previous-admin@example.com", } originalChangedBy := org.ChangedBy originalChangedAt := org.ChangedAt event.UpdateOrganization(org) // User should not be added twice assert.Len(t, org.Users, 1) assert.Equal(t, "existing-user@example.com", org.Users[0]) // ChangedBy and ChangedAt should NOT be updated when user already exists (idempotent) assert.Equal(t, originalChangedBy, org.ChangedBy) assert.Equal(t, originalChangedAt, org.ChangedAt) } func TestAPIKeyRemoved_UpdateOrganization(t *testing.T) { event := &APIKeyRemoved{ BaseEvent: eventsourced.BaseEvent{ EventTime: eventsourced.EventTime{ Time: time.Now(), }, }, KeyName: "production-key", Initiator: "admin@example.com", } org := &Organization{ BaseAggregate: eventsourced.BaseAggregateFromString("org-123"), APIKeys: []APIKey{ {Name: "dev-key", Key: "hashed-key-1"}, {Name: "production-key", Key: "hashed-key-2"}, {Name: "staging-key", Key: "hashed-key-3"}, }, } event.UpdateOrganization(org) assert.Len(t, org.APIKeys, 2) assert.Equal(t, "dev-key", org.APIKeys[0].Name) assert.Equal(t, "staging-key", org.APIKeys[1].Name) assert.Equal(t, "admin@example.com", org.ChangedBy) assert.Equal(t, event.When(), org.ChangedAt) } func TestAPIKeyRemoved_UpdateOrganization_KeyNotFound(t *testing.T) { event := &APIKeyRemoved{ BaseEvent: eventsourced.BaseEvent{ EventTime: eventsourced.EventTime{ Time: time.Now(), }, }, KeyName: "non-existent-key", Initiator: "admin@example.com", } org := &Organization{ BaseAggregate: eventsourced.BaseAggregateFromString("org-123"), APIKeys: []APIKey{ {Name: "dev-key", Key: "hashed-key-1"}, {Name: "production-key", Key: "hashed-key-2"}, }, } event.UpdateOrganization(org) // No keys should be removed assert.Len(t, org.APIKeys, 2) assert.Equal(t, "dev-key", org.APIKeys[0].Name) assert.Equal(t, "production-key", org.APIKeys[1].Name) // But metadata should still be updated assert.Equal(t, "admin@example.com", org.ChangedBy) assert.Equal(t, event.When(), org.ChangedAt) } func TestAPIKeyRemoved_UpdateOrganization_OnlyKey(t *testing.T) { event := &APIKeyRemoved{ BaseEvent: eventsourced.BaseEvent{ EventTime: eventsourced.EventTime{ Time: time.Now(), }, }, KeyName: "only-key", Initiator: "admin@example.com", } org := &Organization{ BaseAggregate: eventsourced.BaseAggregateFromString("org-123"), APIKeys: []APIKey{ {Name: "only-key", Key: "hashed-key"}, }, } event.UpdateOrganization(org) // All keys should be removed assert.Len(t, org.APIKeys, 0) assert.Equal(t, "admin@example.com", org.ChangedBy) assert.Equal(t, event.When(), org.ChangedAt) } func TestOrganizationRemoved_UpdateOrganization(t *testing.T) { event := &OrganizationRemoved{ BaseEvent: eventsourced.BaseEvent{ EventTime: eventsourced.EventTime{ Time: time.Now(), }, }, Initiator: "admin@example.com", } org := &Organization{ BaseAggregate: eventsourced.BaseAggregateFromString("org-123"), Name: "Test Organization", Users: []string{"user1@example.com", "user2@example.com"}, APIKeys: []APIKey{ {Name: "key1", Key: "hashed-key-1"}, }, CreatedBy: "creator@example.com", CreatedAt: time.Now().Add(-24 * time.Hour), } event.UpdateOrganization(org) // Organization data remains (soft delete), but metadata is updated assert.Equal(t, "Test Organization", org.Name) assert.Len(t, org.Users, 2) assert.Len(t, org.APIKeys, 1) // Metadata should be updated to reflect removal assert.Equal(t, "admin@example.com", org.ChangedBy) assert.Equal(t, event.When(), org.ChangedAt) } func TestAPIKeyAdded_EnrichFromAggregate(t *testing.T) { orgId := "org-123" aggregate := &Organization{ BaseAggregate: eventsourced.BaseAggregateFromString(orgId), } event := &APIKeyAdded{ Name: "test-key", Key: "hashed-key", Refs: []string{"main"}, Read: true, Publish: false, Initiator: "user@example.com", } event.EnrichFromAggregate(aggregate) assert.Equal(t, orgId, event.OrganizationId) } func TestSubGraphUpdated_Event(t *testing.T) { // Verify SubGraphUpdated event structure url := "http://service.example.com" wsUrl := "ws://service.example.com" event := &SubGraphUpdated{ OrganizationId: "org-123", Ref: "main", Service: "users-service", Url: &url, WSUrl: &wsUrl, Sdl: "type Query { user: User }", Initiator: "system", } require.NotNil(t, event) assert.Equal(t, "org-123", event.OrganizationId) assert.Equal(t, "main", event.Ref) assert.Equal(t, "users-service", event.Service) assert.Equal(t, url, *event.Url) assert.Equal(t, wsUrl, *event.WSUrl) assert.Equal(t, "type Query { user: User }", event.Sdl) assert.Equal(t, "system", event.Initiator) }