diff --git a/internal/postgres/tag.go b/internal/postgres/tag.go index 729d57a..4e851e2 100644 --- a/internal/postgres/tag.go +++ b/internal/postgres/tag.go @@ -184,3 +184,97 @@ func DeleteTagAlias(ctx context.Context, db *gorm.DB, tagAliasName models.Anthro return nil } + +func CreateTagGroup(ctx context.Context, db *gorm.DB, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) error { + + if tagGroupName == "" { + return &otterError.EntityValidationFailed{Reason: "tagGroupName cannot be empty"} + } + if tagID == "" { + return &otterError.EntityValidationFailed{Reason: "tagID cannot be empty"} + } + + result := db.WithContext(ctx).Create(&models.TagGroup{ + Name: string(tagGroupName), + TagID: string(tagID), + }) + + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrDuplicatedKey) { + return &otterError.EntityAlreadyExists{} + } + return result.Error + } + + log.WithFields(log.Fields{ + "tag_group_name": tagGroupName, + "tag_group_tag_id": tagID, + }).Trace("database: created tagGroup") + + return nil +} + +func GetAllTagGroup(ctx context.Context, db *gorm.DB) ([]models.TagGroup, error) { + var tagGroups []models.TagGroup + + result := db.WithContext(ctx).Find(&tagGroups) + + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return nil, &otterError.NoDataFound{} + } + return nil, result.Error + } + + log.WithFields(log.Fields{ + "tag_alias_length": len(tagGroups), + }).Trace("database: created tagGroup") + + return tagGroups, nil +} + +func GetAllTagGroupByTag(ctx context.Context, db *gorm.DB, tagID models.AnthroveTagID) ([]models.TagGroup, error) { + var tagGroups []models.TagGroup + + if tagID == "" { + return nil, &otterError.EntityValidationFailed{Reason: "tagID cannot be empty"} + } + + result := db.WithContext(ctx).Where("tag_id = ?", tagID).Find(&tagGroups) + + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return nil, &otterError.NoDataFound{} + } + return nil, result.Error + } + + log.WithFields(log.Fields{ + "tag_alias_length": len(tagGroups), + "tag_alias_tag_id": tagID, + }).Trace("database: get specific tagGroup") + + return tagGroups, nil +} + +func DeleteTagGroup(ctx context.Context, db *gorm.DB, tagGroupName models.AnthroveTagGroupName) error { + + if tagGroupName == "" { + return &otterError.EntityValidationFailed{Reason: "tagGroupName cannot be empty"} + } + + result := db.WithContext(ctx).Delete(&models.TagGroup{Name: string(tagGroupName)}) + + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + return &otterError.NoDataFound{} + } + return result.Error + } + + log.WithFields(log.Fields{ + "tag_alias_name": tagGroupName, + }).Trace("database: deleted tagAlias") + + return nil +} diff --git a/internal/postgres/tag_test.go b/internal/postgres/tag_test.go index 54f8c03..adbc867 100644 --- a/internal/postgres/tag_test.go +++ b/internal/postgres/tag_test.go @@ -596,3 +596,352 @@ func TestDeleteTagAlias(t *testing.T) { }) } } + +func TestCreateTagGroup(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + validTagGroupName01 := models.AnthroveTagGroupName("httyd") + validTagGroupName02 := models.AnthroveTagGroupName("dragon") + + validTagID := models.AnthroveTagID("toothless") + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + err = CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + tagGroupName models.AnthroveTagGroupName + tagID models.AnthroveTagID + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid Data", + args: args{ + ctx: ctx, + db: gormDB, + tagGroupName: validTagGroupName01, + tagID: validTagID, + }, + wantErr: false, + }, + { + name: "Test 2: No TagGroupName", + args: args{ + ctx: ctx, + db: gormDB, + tagGroupName: "", + tagID: validTagID, + }, + wantErr: true, + }, + { + name: "Test 4: No tagID", + args: args{ + ctx: ctx, + db: gormDB, + tagGroupName: validTagGroupName01, + tagID: "", + }, + wantErr: true, + }, + { + name: "Test 5: Duplicate tagID", + args: args{ + ctx: ctx, + db: gormDB, + tagGroupName: validTagGroupName01, + tagID: validTagID, + }, + wantErr: true, + }, + { + name: "Test 6: Invalide tagID", + args: args{ + ctx: ctx, + db: gormDB, + tagGroupName: validTagGroupName02, + tagID: "aaa", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := CreateTagGroup(tt.args.ctx, tt.args.db, tt.args.tagGroupName, tt.args.tagID); (err != nil) != tt.wantErr { + t.Errorf("CreateTagGroup() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func TestGetAllTagGroup(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validTagID := models.AnthroveTagID("toothless") + validTagGroupes := []models.AnthroveTagGroupName{"httyd", "dragon", "scaly"} + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + expectedResult := []models.TagGroup{ + { + Name: string(validTagGroupes[0]), + TagID: string(validTagID), + }, + { + Name: string(validTagGroupes[1]), + TagID: string(validTagID), + }, + { + Name: string(validTagGroupes[2]), + TagID: string(validTagID), + }, + } + + err = CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + for _, tagGroupName := range validTagGroupes { + err = CreateTagGroup(ctx, gormDB, tagGroupName, validTagID) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + } + tests := []struct { + name string + args args + want []models.TagGroup + wantErr bool + }{ + { + name: "Test 1: Get Data", + args: args{ + ctx: ctx, + db: gormDB, + }, + want: expectedResult, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetAllTagGroup(tt.args.ctx, tt.args.db) + if (err != nil) != tt.wantErr { + t.Errorf("GetAllTagGroup() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetAllTagGroup() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestGetAllTagGroupByTag(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validTagID := models.AnthroveTagID("toothless") + validTagGroupes := []models.AnthroveTagGroupName{"httyd", "dragon", "scaly"} + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + expectedResult := []models.TagGroup{ + { + Name: string(validTagGroupes[0]), + TagID: string(validTagID), + }, + { + Name: string(validTagGroupes[1]), + TagID: string(validTagID), + }, + { + Name: string(validTagGroupes[2]), + TagID: string(validTagID), + }, + } + + err = CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + for _, tagGroupName := range validTagGroupes { + err = CreateTagGroup(ctx, gormDB, tagGroupName, validTagID) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + tagID models.AnthroveTagID + } + tests := []struct { + name string + args args + want []models.TagGroup + wantErr bool + }{ + { + name: "Test 1: Valid TagID", + args: args{ + ctx: ctx, + db: gormDB, + tagID: validTagID, + }, + want: expectedResult, + wantErr: false, + }, + { + name: "Test 2: No TagID", + args: args{ + ctx: ctx, + db: gormDB, + tagID: "", + }, + want: nil, + wantErr: true, + }, + { + name: "Test 3: Invalid TagID", + args: args{ + ctx: ctx, + db: gormDB, + tagID: "adads", + }, + want: []models.TagGroup{}, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := GetAllTagGroupByTag(tt.args.ctx, tt.args.db, tt.args.tagID) + if (err != nil) != tt.wantErr { + t.Errorf("GetAllTagGroupByTag() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetAllTagGroupByTag() got = %v, want %v", got, tt.want) + } + }) + } +} + +func TestDeleteTagGroup(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validTagID := models.AnthroveTagID("toothless") + validTagGroupes := []models.AnthroveTagGroupName{"httyd", "dragon", "scaly"} + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + err = CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + for _, tagGroupName := range validTagGroupes { + err = CreateTagGroup(ctx, gormDB, tagGroupName, validTagID) + } + + // Test + type args struct { + ctx context.Context + db *gorm.DB + tagGroupName models.AnthroveTagGroupName + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid AnthroveTagGroupName", + args: args{ + ctx: ctx, + db: gormDB, + tagGroupName: validTagGroupes[0], + }, + wantErr: false, + }, + { + name: "Test 2: Invalid AnthroveTagGroupName", + args: args{ + ctx: ctx, + db: gormDB, + tagGroupName: "asdad", + }, + wantErr: false, + }, + { + name: "Test 3: No AnthroveTagGroupName", + args: args{ + ctx: ctx, + db: gormDB, + tagGroupName: "", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if err := DeleteTagGroup(tt.args.ctx, tt.args.db, tt.args.tagGroupName); (err != nil) != tt.wantErr { + t.Errorf("DeleteTagAlias() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/pkg/database/postgres.go b/pkg/database/postgres.go index 1eb22de..39c7a54 100644 --- a/pkg/database/postgres.go +++ b/pkg/database/postgres.go @@ -181,24 +181,20 @@ func (p *postgresqlConnection) DeleteTagAlias(ctx context.Context, tagAliasName return postgres.DeleteTagAlias(ctx, p.db, tagAliasName) } -func (p *postgresqlConnection) CreateTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) { - //TODO implement me - panic("implement me") +func (p *postgresqlConnection) CreateTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) error { + return postgres.CreateTagGroup(ctx, p.db, tagGroupName, tagID) } func (p *postgresqlConnection) GetAllTagGroup(ctx context.Context) ([]models.TagGroup, error) { - //TODO implement me - panic("implement me") + return postgres.GetAllTagGroup(ctx, p.db) } func (p *postgresqlConnection) GetAllTagGroupByTag(ctx context.Context, tagID models.AnthroveTagID) ([]models.TagGroup, error) { - //TODO implement me - panic("implement me") + return postgres.GetAllTagGroupByTag(ctx, p.db, tagID) } func (p *postgresqlConnection) DeleteTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName) error { - //TODO implement me - panic("implement me") + return postgres.DeleteTagGroup(ctx, p.db, tagGroupName) } // HELPER diff --git a/pkg/database/postgres_test.go b/pkg/database/postgres_test.go index acd0b0e..d53f9e2 100644 --- a/pkg/database/postgres_test.go +++ b/pkg/database/postgres_test.go @@ -2367,3 +2367,352 @@ func Test_postgresqlConnection_DeleteTagAlias(t *testing.T) { }) } } + +//-------------------------- + +func Test_postgresqlConnection_CreateTagGroup(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + + validTagGroupName01 := models.AnthroveTagGroupName("httyd") + validTagGroupName02 := models.AnthroveTagGroupName("dragon") + + validTagID := models.AnthroveTagID("toothless") + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + err = postgres.CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + // Test + type args struct { + ctx context.Context + tagGroupName models.AnthroveTagGroupName + tagID models.AnthroveTagID + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid Data", + args: args{ + ctx: ctx, + tagGroupName: validTagGroupName01, + tagID: validTagID, + }, + wantErr: false, + }, + { + name: "Test 2: No TagGroupName", + args: args{ + ctx: ctx, + tagGroupName: "", + tagID: validTagID, + }, + wantErr: true, + }, + { + name: "Test 4: No tagID", + args: args{ + ctx: ctx, + tagGroupName: validTagGroupName01, + tagID: "", + }, + wantErr: true, + }, + { + name: "Test 5: Duplicate tagID", + args: args{ + ctx: ctx, + tagGroupName: validTagGroupName01, + tagID: validTagID, + }, + wantErr: true, + }, + { + name: "Test 6: Invalide tagID", + args: args{ + ctx: ctx, + tagGroupName: validTagGroupName02, + tagID: "aaa", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + if err := p.CreateTagGroup(tt.args.ctx, tt.args.tagGroupName, tt.args.tagID); (err != nil) != tt.wantErr { + t.Errorf("CreateTagGroup() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} + +func Test_postgresqlConnection_GetAllTagGroup(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validTagID := models.AnthroveTagID("toothless") + validTagGroupes := []models.AnthroveTagGroupName{"httyd", "dragon", "scaly"} + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + expectedResult := []models.TagGroup{ + { + Name: string(validTagGroupes[0]), + TagID: string(validTagID), + }, + { + Name: string(validTagGroupes[1]), + TagID: string(validTagID), + }, + { + Name: string(validTagGroupes[2]), + TagID: string(validTagID), + }, + } + + err = postgres.CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + for _, tagGroupName := range validTagGroupes { + err = postgres.CreateTagGroup(ctx, gormDB, tagGroupName, validTagID) + } + + // Test + type args struct { + ctx context.Context + } + tests := []struct { + name string + args args + want []models.TagGroup + wantErr bool + }{ + { + name: "Test 1: Get Data", + args: args{ctx: ctx}, + want: expectedResult, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + got, err := p.GetAllTagGroup(tt.args.ctx) + if (err != nil) != tt.wantErr { + t.Errorf("GetAllTagGroup() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetAllTagGroup() got = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_postgresqlConnection_GetAllTagGroupByTag(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validTagID := models.AnthroveTagID("toothless") + validTagGroupes := []models.AnthroveTagGroupName{"httyd", "dragon", "scaly"} + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + expectedResult := []models.TagGroup{ + { + Name: string(validTagGroupes[0]), + TagID: string(validTagID), + }, + { + Name: string(validTagGroupes[1]), + TagID: string(validTagID), + }, + { + Name: string(validTagGroupes[2]), + TagID: string(validTagID), + }, + } + + err = postgres.CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + for _, tagGroupName := range validTagGroupes { + err = postgres.CreateTagGroup(ctx, gormDB, tagGroupName, validTagID) + } + + // Test + type args struct { + ctx context.Context + tagID models.AnthroveTagID + } + tests := []struct { + name string + args args + want []models.TagGroup + wantErr bool + }{ + { + name: "Test 1: Valid TagID", + args: args{ + ctx: ctx, + tagID: validTagID, + }, + want: expectedResult, + wantErr: false, + }, + { + name: "Test 2: No TagID", + args: args{ + ctx: ctx, + tagID: "", + }, + want: nil, + wantErr: true, + }, + { + name: "Test 3: Invalid TagID", + args: args{ + ctx: ctx, + tagID: "adads", + }, + want: []models.TagGroup{}, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + got, err := p.GetAllTagGroupByTag(tt.args.ctx, tt.args.tagID) + if (err != nil) != tt.wantErr { + t.Errorf("GetAllTagGroupByTag() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetAllTagGroupByTag() got = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_postgresqlConnection_DeleteTagGroup(t *testing.T) { + // Setup trow away container + ctx := context.Background() + container, gormDB, err := test.StartPostgresContainer(ctx) + if err != nil { + t.Fatalf("Could not start PostgreSQL container: %v", err) + } + defer container.Terminate(ctx) + + // Setup Test + validTagID := models.AnthroveTagID("toothless") + validTagGroupes := []models.AnthroveTagGroupName{"httyd", "dragon", "scaly"} + + validTag := &models.Tag{ + Name: string(validTagID), + Type: models.Character, + } + + err = postgres.CreateTag(ctx, gormDB, validTag) + if err != nil { + t.Fatal(err) + } + + for _, tagGroupName := range validTagGroupes { + err = postgres.CreateTagGroup(ctx, gormDB, tagGroupName, validTagID) + } + + // Test + type args struct { + ctx context.Context + tagGroupName models.AnthroveTagGroupName + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "Test 1: Valid AnthroveTagGroupName", + args: args{ + ctx: ctx, + tagGroupName: validTagGroupes[0], + }, + wantErr: false, + }, + { + name: "Test 2: Invalid AnthroveTagGroupName", + args: args{ + ctx: ctx, + tagGroupName: "asdad", + }, + wantErr: false, + }, + { + name: "Test 3: No AnthroveTagGroupName", + args: args{ + ctx: ctx, + tagGroupName: "", + }, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + p := &postgresqlConnection{ + db: gormDB, + debug: true, + } + if err := p.DeleteTagGroup(tt.args.ctx, tt.args.tagGroupName); (err != nil) != tt.wantErr { + t.Errorf("DeleteTagAlias() error = %v, wantErr %v", err, tt.wantErr) + } + }) + } +} diff --git a/pkg/database/taggroup.go b/pkg/database/taggroup.go index 594cd1e..f25bd68 100644 --- a/pkg/database/taggroup.go +++ b/pkg/database/taggroup.go @@ -7,7 +7,7 @@ import ( ) type TagGroup interface { - CreateTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) + CreateTagGroup(ctx context.Context, tagGroupName models.AnthroveTagGroupName, tagID models.AnthroveTagID) error GetAllTagGroup(ctx context.Context) ([]models.TagGroup, error)