schemas / check (push) Skipped
schemas / vulnerabilities (push) Skipped
schemas / check-release (push) Skipped
schemas / build (push) Skipped
pre-commit / pre-commit (push) Skipped
schemas / vulnerabilities (pull_request) Successful in 58s
schemas / check-release (pull_request) Successful in 59s
schemas / check (pull_request) Successful in 1m58s
pre-commit / pre-commit (pull_request) Successful in 2m54s
schemas / build (pull_request) Successful in 6m9s
schemas / deploy-prod (pull_request) Skipped
Move eventsourced modules from gitlab.com/unboundsoftware to codeberg.org/eventsourced. The Codeberg amqp publisher is built on go-messaging-amqp, so the service switches from sparetimecoders/goamqp as well: - routing keys are mapped on the eventsourced publisher (newEventPublisher) - cache consumers are typed handlers; Cache.Update drops the goamqp shape - publishes detach from the request context (uncancelledPublisher) - closeEvents is buffered and the receiver also watches rootCtx - WithPrefetchLimit dropped (no-op, 20 is the default) - amqp091-go v1.15.0 (GO-2026-6372) - renovate groups codeberg.org/messaging with eventsourced Only transient consumer queues are used, so no queue cutover is needed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Dpb7Y47dPz246oY9bCzh7k
255 lines
6.7 KiB
Go
255 lines
6.7 KiB
Go
package domain
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
|
|
"codeberg.org/eventsourced/eventsourced"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
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)
|
|
}
|