package repository_test import ( "context" "database/sql" "fmt" "testing" "time" "gitea.badhouseplants.net/softplayer/softplayer-backend/internal/repository" "github.com/google/uuid" "github.com/stretchr/testify/assert" ) func newTestUniqueEmail(prefix string) string { if prefix == "" { prefix = "test" } return fmt.Sprintf( "%s-%d-%s@example.com", prefix, time.Now().UnixMilli(), uuid.NewString(), ) } func accountForProject(ctx context.Context) (string, error) { account := &repository.AccountData{ UUID: uuid.NewString(), Email: newTestUniqueEmail("projects"), PasswordHash: "dummy", Name: "John", Surname: "Doe", } if err := repository.CreateAccount(ctx, newTestDBConnection(ctx), account); err != nil { return "", err } return account.UUID, nil } func TestIntegrationProjectsCreate_Success(t *testing.T) { createdBy, err := accountForProject(t.Context()) assert.NoError(t, err) project := &repository.ProjectData{ UUID: uuid.NewString(), Name: "test-1", Slug: uuid.NewString(), Description: "Test Project Number 1", CreatedBy: createdBy, CreatedAt: time.Now(), ClosedAt: sql.NullTime{Time: time.Now()}, Blocked: false, UpdatedAt: time.Now(), UpdatedBy: createdBy, } assert.NoError(t, repository.CreateProject(t.Context(), newTestDBConnection(t.Context()), project)) } func TestIntegrationProjectsCreate_CheckFailed(t *testing.T) { createdBy, err := accountForProject(t.Context()) assert.NoError(t, err) project := &repository.ProjectData{ UUID: uuid.NewString(), Name: "test-2", Slug: "test_2", Description: "Test Project Number 1", CreatedBy: createdBy, CreatedAt: time.Now(), ClosedAt: sql.NullTime{Time: time.Now()}, Blocked: false, UpdatedAt: time.Now(), UpdatedBy: createdBy, } assert.Error(t, repository.CreateProject(t.Context(), newTestDBConnection(t.Context()), project), repository.ErrCheckNotPassed) } func TestIntegrationProjectsCreate_AlreadyExistsFail(t *testing.T) { createdBy, err := accountForProject(t.Context()) assert.NoError(t, err) project := &repository.ProjectData{ UUID: uuid.NewString(), Name: "test-3", Slug: uuid.NewString(), Description: "Test Project Number 1", CreatedBy: createdBy, CreatedAt: time.Now(), ClosedAt: sql.NullTime{Time: time.Now()}, Blocked: false, UpdatedAt: time.Now(), UpdatedBy: createdBy, } assert.NoError(t, repository.CreateProject(t.Context(), newTestDBConnection(t.Context()), project)) assert.Error(t, repository.CreateProject(t.Context(), newTestDBConnection(t.Context()), project), repository.ErrAlreadyExists) } func TestIntegrationProjectsCreateAndGet_Success(t *testing.T) { createdBy, err := accountForProject(t.Context()) assert.NoError(t, err) project := &repository.ProjectData{ UUID: uuid.NewString(), Name: "test-4", Slug: uuid.NewString(), Description: "Test Project Number 1", CreatedBy: createdBy, CreatedAt: time.Now(), Blocked: false, UpdatedAt: time.Now(), UpdatedBy: createdBy, } assert.NoError(t, repository.CreateProject(t.Context(), newTestDBConnection(t.Context()), project)) data, err := repository.GetProjectByID(t.Context(), newTestDBConnection(t.Context()), project.UUID) assert.NoError(t, err) assert.Equal(t, project.Name, data.Name) assert.Equal(t, project.Slug, data.Slug) assert.Equal(t, project.Description, data.Description) assert.Equal(t, project.CreatedBy, data.CreatedBy) assert.Equal(t, project.ClosedAt.Time.Truncate(time.Second), data.ClosedAt.Time.Truncate(time.Second)) assert.Equal(t, project.CreatedAt.Truncate(time.Second), data.CreatedAt.Truncate(time.Second)) } func TestIntegrationProjectsCreateAndGet_NotFound(t *testing.T) { data, err := repository.GetProjectByID(t.Context(), newTestDBConnection(t.Context()), uuid.NewString()) assert.ErrorIs(t, err, repository.ErrNotFound) assert.Nil(t, data) } func TestIntegrationProjectsCreateUpdateAndGet_Success(t *testing.T) { createdBy, err := accountForProject(t.Context()) assert.NoError(t, err) project := &repository.ProjectData{ UUID: uuid.NewString(), Name: "test-5", Slug: uuid.NewString(), Description: "Test Project Number 1", CreatedBy: createdBy, CreatedAt: time.Now(), Blocked: false, UpdatedAt: time.Now(), UpdatedBy: createdBy, } assert.NoError(t, repository.CreateProject(t.Context(), newTestDBConnection(t.Context()), project)) data, err := repository.GetProjectByID(t.Context(), newTestDBConnection(t.Context()), project.UUID) assert.NoError(t, err) assert.Equal(t, project.Name, data.Name) assert.Equal(t, project.Slug, data.Slug) assert.Equal(t, project.Description, data.Description) assert.Equal(t, project.CreatedBy, data.CreatedBy) assert.Equal(t, project.ClosedAt.Time.Truncate(time.Second), data.ClosedAt.Time.Truncate(time.Second)) assert.Equal(t, project.CreatedAt.Truncate(time.Second), data.CreatedAt.Truncate(time.Second)) project.UpdatedBy = uuid.NewString() project.UpdatedAt = time.Now() project.Description = "Updated description" project.Name = "update name" assert.NoError(t, repository.UpdateProject(t.Context(), newTestDBConnection(t.Context()), project)) data, err = repository.GetProjectByID(t.Context(), newTestDBConnection(t.Context()), project.UUID) assert.NoError(t, err) assert.Equal(t, project.Name, data.Name) assert.Equal(t, project.Slug, data.Slug) assert.Equal(t, project.Description, data.Description) } func TestIntegrationProjectsCreateAndGetOwner_Success(t *testing.T) { createdBy, err := accountForProject(t.Context()) assert.NoError(t, err) project := &repository.ProjectData{ UUID: uuid.NewString(), Name: "test-6", Slug: uuid.NewString(), Description: "Test Project Number 1", CreatedBy: createdBy, CreatedAt: time.Now(), ClosedAt: sql.NullTime{Time: time.Now()}, Blocked: false, UpdatedAt: time.Now(), UpdatedBy: createdBy, } assert.NoError(t, repository.CreateProject(t.Context(), newTestDBConnection(t.Context()), project)) userID, err := repository.GetProjectOwner(t.Context(), newTestDBConnection(t.Context()), project.UUID) assert.NoError(t, err) assert.Equal(t, project.CreatedBy, userID) } func TestIntegrationListProjectsWorkflow(t *testing.T) { createdBy1, err := accountForProject(t.Context()) assert.NoError(t, err) project1 := &repository.ProjectData{ UUID: uuid.NewString(), Name: "List 1", Slug: uuid.NewString(), Description: "Test Project Number 1", CreatedBy: createdBy1, CreatedAt: time.Now(), ClosedAt: sql.NullTime{Time: time.Now()}, Blocked: false, UpdatedAt: time.Now(), UpdatedBy: createdBy1, } assert.NoError(t, repository.CreateProject(t.Context(), newTestDBConnection(t.Context()), project1)) project2 := &repository.ProjectData{ UUID: uuid.NewString(), Name: "List 2", Slug: uuid.NewString(), Description: "Test Project Number 1", CreatedBy: createdBy1, CreatedAt: time.Now(), ClosedAt: sql.NullTime{Time: time.Now()}, Blocked: false, UpdatedAt: time.Now(), UpdatedBy: createdBy1, } assert.NoError(t, repository.CreateProject(t.Context(), newTestDBConnection(t.Context()), project2)) createdBy2, err := accountForProject(t.Context()) assert.NoError(t, err) project3 := &repository.ProjectData{ UUID: uuid.NewString(), Name: "List 3", Slug: uuid.NewString(), Description: "Test Project Number 1", CreatedBy: createdBy2, CreatedAt: time.Now(), ClosedAt: sql.NullTime{Time: time.Now()}, Blocked: false, UpdatedAt: time.Now(), UpdatedBy: createdBy2, } assert.NoError(t, repository.CreateProject(t.Context(), newTestDBConnection(t.Context()), project3)) projects, err := repository.ListProjects(t.Context(), newTestDBConnection(t.Context()), createdBy1) assert.NoError(t, err) assert.Len(t, projects, 2) projects, err = repository.ListProjects(t.Context(), newTestDBConnection(t.Context()), createdBy2) assert.NoError(t, err) assert.Len(t, projects, 1) }