167 lines
4.1 KiB
Go
167 lines
4.1 KiB
Go
|
|
package actor
|
||
|
|
|
||
|
|
import (
|
||
|
|
"fmt"
|
||
|
|
"strings"
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
v1 "git.tipsy.codes/charles/webstory/pkg/api/webstory/v1"
|
||
|
|
"google.golang.org/protobuf/types/known/timestamppb"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestActorTranslator_FromAPI(t *testing.T) {
|
||
|
|
now := time.Now()
|
||
|
|
tests := []struct {
|
||
|
|
name string
|
||
|
|
apiActor *v1.Actor
|
||
|
|
expectErr bool
|
||
|
|
errMsg string
|
||
|
|
checkFunc func(*DBActor) error
|
||
|
|
}{
|
||
|
|
{
|
||
|
|
name: "nil actor returns error",
|
||
|
|
apiActor: nil,
|
||
|
|
expectErr: true,
|
||
|
|
errMsg: "api actor cannot be nil",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "minimal valid actor creates translator correctly",
|
||
|
|
apiActor: &v1.Actor{
|
||
|
|
ActorId: "actor1",
|
||
|
|
NameValue: "Player",
|
||
|
|
},
|
||
|
|
expectErr: false,
|
||
|
|
checkFunc: func(a *DBActor) error {
|
||
|
|
if a.ActorID != "actor1" {
|
||
|
|
return fmt.Errorf("expected ActorID actor1, got %s", a.ActorID)
|
||
|
|
}
|
||
|
|
if a.NameValue != "Player" {
|
||
|
|
return fmt.Errorf("expected NameValue Player, got %s", a.NameValue)
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "actor with all fields converts correctly",
|
||
|
|
apiActor: &v1.Actor{
|
||
|
|
Name: "stories/my-actor-1",
|
||
|
|
ActorId: "my-actor-1",
|
||
|
|
NameValue: "The Hero",
|
||
|
|
Role: "protagonist",
|
||
|
|
Notes: "Main character",
|
||
|
|
CreateTime: timestamppb.New(now),
|
||
|
|
UpdateTime: timestamppb.New(now),
|
||
|
|
Etag: "etag-123",
|
||
|
|
},
|
||
|
|
expectErr: false,
|
||
|
|
checkFunc: func(a *DBActor) error {
|
||
|
|
if a.ActorID != "my-actor-1" {
|
||
|
|
return fmt.Errorf("expected ActorID my-actor-1, got %s", a.ActorID)
|
||
|
|
}
|
||
|
|
if a.NameValue != "The Hero" {
|
||
|
|
return fmt.Errorf("expected NameValue The Hero, got %s", a.NameValue)
|
||
|
|
}
|
||
|
|
if a.Role != "protagonist" {
|
||
|
|
return fmt.Errorf("expected Role protagonist, got %s", a.Role)
|
||
|
|
}
|
||
|
|
if a.Notes != "Main character" {
|
||
|
|
return fmt.Errorf("expected Notes Main character, got %s", a.Notes)
|
||
|
|
}
|
||
|
|
if a.Etag != "etag-123" {
|
||
|
|
return fmt.Errorf("expected Etag etag-123, got %s", a.Etag)
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "empty notes converted to empty string",
|
||
|
|
apiActor: &v1.Actor{
|
||
|
|
ActorId: "actor2",
|
||
|
|
NameValue: "NPC",
|
||
|
|
Notes: "",
|
||
|
|
},
|
||
|
|
expectErr: false,
|
||
|
|
checkFunc: func(a *DBActor) error {
|
||
|
|
if a.Notes != "" {
|
||
|
|
return fmt.Errorf("expected empty Notes, got %s", a.Notes)
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
},
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "missing name_value returns error",
|
||
|
|
apiActor: &v1.Actor{
|
||
|
|
ActorId: "actor4",
|
||
|
|
},
|
||
|
|
expectErr: true,
|
||
|
|
errMsg: "name_value is required",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "invalid actor_id_short returns error",
|
||
|
|
apiActor: &v1.Actor{
|
||
|
|
NameValue: "Test",
|
||
|
|
},
|
||
|
|
expectErr: true,
|
||
|
|
errMsg: "invalid actor_id format: must be 4-63 characters, matching pattern /[a-z][0-9-][0-9]$/",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "invalid actor_id_uppercase returns error",
|
||
|
|
apiActor: &v1.Actor{
|
||
|
|
ActorId: "Actor2",
|
||
|
|
},
|
||
|
|
expectErr: true,
|
||
|
|
errMsg: "invalid actor_id format: must be 4-63 characters, matching pattern /[a-z][0-9-][0-9]$/",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "invalid actor_id_starts_with_number returns error",
|
||
|
|
apiActor: &v1.Actor{
|
||
|
|
ActorId: "1actor",
|
||
|
|
},
|
||
|
|
expectErr: true,
|
||
|
|
errMsg: "invalid actor_id format: must be 4-63 characters, matching pattern /[a-z][0-9-][0-9]$/",
|
||
|
|
},
|
||
|
|
{
|
||
|
|
name: "valid actor_id_with_hyphens_and_numbers",
|
||
|
|
apiActor: &v1.Actor{
|
||
|
|
NameValue: "Test Actor",
|
||
|
|
ActorId: "my-awesome-actor-123",
|
||
|
|
},
|
||
|
|
expectErr: false,
|
||
|
|
checkFunc: func(a *DBActor) error {
|
||
|
|
if a.ActorID != "my-awesome-actor-123" {
|
||
|
|
return fmt.Errorf("expected ActorID my-awesome-actor-123, got %s", a.ActorID)
|
||
|
|
}
|
||
|
|
return nil
|
||
|
|
},
|
||
|
|
},
|
||
|
|
}
|
||
|
|
|
||
|
|
for _, tt := range tests {
|
||
|
|
t.Run(tt.name, func(t *testing.T) {
|
||
|
|
translator := NewActorTranslator()
|
||
|
|
got, err := translator.FromAPI(tt.apiActor)
|
||
|
|
|
||
|
|
if tt.expectErr {
|
||
|
|
if err == nil {
|
||
|
|
t.Fatalf("expected error but got nil")
|
||
|
|
}
|
||
|
|
if tt.errMsg != "" && !strings.Contains(err.Error(), tt.errMsg) {
|
||
|
|
t.Errorf("expected error message to contain %q, got %q", tt.errMsg, err.Error())
|
||
|
|
}
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("unexpected error: %v", err)
|
||
|
|
}
|
||
|
|
|
||
|
|
if tt.checkFunc != nil {
|
||
|
|
if err := tt.checkFunc(got); err != nil {
|
||
|
|
t.Errorf("checkFunc failed: %v", err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
})
|
||
|
|
}
|
||
|
|
}
|