Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore(server): Increase domain package unit test coverage (integrationapi part 2) #1307

Merged
merged 12 commits into from
Nov 29, 2024
2 changes: 1 addition & 1 deletion server/pkg/id/id.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ var RequestIDFromRef = idx.FromRef[Request]

type View struct{}

func (View) Type() string { return "request" }
func (View) Type() string { return "view" }

type ViewID = idx.ID[View]
type ViewIDList = idx.List[View]
Expand Down
12 changes: 12 additions & 0 deletions server/pkg/id/id_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,16 @@ func TestAsset_Type(t *testing.T) {

r := Resource{}
assert.Equal(t, "resource", r.Type())

v := View{}
assert.Equal(t, "view", v.Type())

tag := Tag{}
assert.Equal(t, "tag", tag.Type())

g := Group{}
assert.Equal(t, "group", g.Type())

ig := ItemGroup{}
assert.Equal(t, "item_group", ig.Type())
}
11 changes: 11 additions & 0 deletions server/pkg/id/key_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,14 @@ func TestKey_Clone(t *testing.T) {
assert.Equal(t, k, c)
assert.NotSame(t, k, c)
}

func TestKey_NewKeyFromPtr(t *testing.T) {

str := "test-key"
wantKey := Key{
key: lo.FromPtr(&str),
}
result := NewKeyFromPtr(&str)
assert.NotNil(t, result, "Result should not be nil")
assert.Equal(t, &wantKey, result, "Key value should match the input string")
}
168 changes: 168 additions & 0 deletions server/pkg/integrationapi/event_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package integrationapi

import (
"testing"
"time"

"github.com/reearth/reearth-cms/server/pkg/asset"
"github.com/reearth/reearth-cms/server/pkg/event"
"github.com/reearth/reearth-cms/server/pkg/id"
"github.com/reearth/reearth-cms/server/pkg/operator"
"github.com/reearth/reearth-cms/server/pkg/project"
"github.com/reearth/reearthx/account/accountdomain"
"github.com/reearth/reearthx/account/accountdomain/user"
"github.com/stretchr/testify/assert"
)

func Test_NewOperator(t *testing.T) {

uid := accountdomain.NewUserID()
integrationID := id.NewIntegrationID()
opUser := operator.OperatorFromUser(uid)
opIntegration := operator.OperatorFromIntegration(integrationID)
opMachine := operator.OperatorFromMachine()
tests := []struct {
name string
input operator.Operator
want Operator
}{
{
name: "success user operator",
input: opUser,
want: Operator{
User: &OperatorUser{
ID: uid.String(),
},
},
},
{
name: "success integration operator",
input: opIntegration,
want: Operator{
Integration: &OperatorIntegration{
ID: integrationID.String(),
},
},
},
{
name: "success machine operator",
input: opMachine,
want: Operator{
Machine: &OperatorMachine{},
},
},
{
name: "success unknown operator",
input: operator.Operator{},
want: Operator{},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
t.Parallel()
result := NewOperator(test.input)
assert.Equal(t, result, test.want)
})

}
}

func TestNewEventWith(t *testing.T) {
mockTime := time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)
u := user.New().NewID().Email("[email protected]").Name("John").MustBuild()
a := asset.New().NewID().Project(project.NewID()).Size(100).NewUUID().
CreatedByUser(u.ID()).Thread(id.NewThreadID()).MustBuild()
eID1 := event.NewID()
prj := event.Project{
ID: "testID",
Alias: "testAlias",
}

ev := event.New[any]().ID(eID1).Timestamp(mockTime).Type(event.AssetCreate).Operator(operator.OperatorFromUser(u.ID())).Object(a).Project(&prj).MustBuild()
ev1 := event.New[any]().ID(eID1).Timestamp(mockTime).Type(event.Type("test")).Operator(operator.OperatorFromUser(u.ID())).Object("test").Project(&prj).MustBuild()
d1, _ := New(ev, "test", func(a *asset.Asset) string {
return "test.com"
})
d2, _ := New(ev.Object(), "test", func(a *asset.Asset) string {
return "test.com"
})
type args struct {
event *event.Event[any]
override any
v string
urlResolver asset.URLResolver
}
tests := []struct {
name string
args args
want Event
wantErr error
}{
{
name: "success",
args: args{
event: ev,
override: ev,
v: "test",
urlResolver: func(a *asset.Asset) string {
return "test.com"
},
},
want: Event{
ID: ev.ID().String(),
Type: string(ev.Type()),
Timestamp: ev.Timestamp(),
Data: d1,
Project: &ProjectIdAlias{
ID: ev.Project().ID,
Alias: ev.Project().Alias,
},
Operator: NewOperator(ev.Operator()),
},
wantErr: nil,
},
{
name: "success when override is nil",
args: args{
event: ev,
override: nil,
v: "test",
urlResolver: func(a *asset.Asset) string {
return "test.com"
},
},
want: Event{
ID: ev.ID().String(),
Type: string(ev.Type()),
Timestamp: ev.Timestamp(),
Data: d2,
Project: &ProjectIdAlias{
ID: ev.Project().ID,
Alias: ev.Project().Alias,
},
Operator: NewOperator(ev.Operator()),
},
wantErr: nil,
},
{
name: "error new returns error",
args: args{
event: ev,
override: ev1,
v: "",
urlResolver: nil,
},
want: Event{},
wantErr: ErrUnsupportedEntity,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
t.Parallel()

result, err := NewEventWith(test.args.event, test.args.override, test.args.v, test.args.urlResolver)
assert.Equal(t, result, test.want)
assert.Equal(t, err, test.wantErr)
})
}
}
144 changes: 144 additions & 0 deletions server/pkg/integrationapi/schema_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package integrationapi

import (
"testing"
"time"

"github.com/reearth/reearth-cms/server/pkg/id"
"github.com/reearth/reearth-cms/server/pkg/item"
"github.com/reearth/reearth-cms/server/pkg/model"
"github.com/reearth/reearth-cms/server/pkg/schema"
"github.com/reearth/reearth-cms/server/pkg/value"
"github.com/reearth/reearthx/account/accountdomain"
"github.com/reearth/reearthx/util"
"github.com/samber/lo"
"github.com/stretchr/testify/assert"
)

func TestNewModel(t *testing.T) {
type args struct {
m *model.Model
sp *schema.Package
lastModified time.Time
}
mockTime := time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)
pID := id.NewProjectID()
sf1 := schema.NewField(schema.NewText(nil).TypeProperty()).NewID().RandomKey().MustBuild()
sf2 := schema.NewField(lo.Must1(schema.NewInteger(nil, nil)).TypeProperty()).NewID().RandomKey().MustBuild()
s1 := schema.New().NewID().Project(pID).Workspace(accountdomain.NewWorkspaceID()).Fields([]*schema.Field{sf1, sf2}).MustBuild()
s2 := schema.New().NewID().Project(pID).Workspace(accountdomain.NewWorkspaceID()).Fields([]*schema.Field{sf1, sf2}).TitleField(sf1.ID().Ref()).MustBuild()
schemaPackage1 := schema.NewPackage(s1, nil, nil, nil)
schemaPackage2 := schema.NewPackage(s2, nil, nil, nil)
model1 := model.New().ID(id.NewModelID()).Metadata(s1.ID().Ref()).Project(pID).Schema(s1.ID()).Key(id.NewKey("mmm123")).UpdatedAt(mockTime).MustBuild()
model2 := model.New().ID(id.NewModelID()).Metadata(s2.ID().Ref()).Project(pID).Schema(s2.ID()).Key(id.NewKey("mmm123")).UpdatedAt(mockTime).MustBuild()

tests := []struct {
name string
args args
want Model
}{
{
name: "success",
args: args{
m: model1,
sp: schemaPackage1,
lastModified: mockTime,
},
want: Model{
Id: model1.ID().Ref(),
Key: util.ToPtrIfNotEmpty(model1.Key().String()),
Name: util.ToPtrIfNotEmpty(model1.Name()),
Description: util.ToPtrIfNotEmpty(model1.Description()),
Public: util.ToPtrIfNotEmpty(model1.Public()),
ProjectId: model1.Project().Ref(),
SchemaId: model1.Schema().Ref(),
Schema: util.ToPtrIfNotEmpty(NewSchema(schemaPackage1.Schema())),
MetadataSchemaId: model1.Metadata().Ref(),
MetadataSchema: util.ToPtrIfNotEmpty(NewSchema(schemaPackage1.MetaSchema())),
CreatedAt: lo.ToPtr(model1.ID().Timestamp()),
UpdatedAt: lo.ToPtr(model1.UpdatedAt()),
LastModified: util.ToPtrIfNotEmpty(mockTime),
},
},
{
name: "success with item field in schema",
args: args{
m: model2,
sp: schemaPackage2,
lastModified: mockTime,
},
want: Model{
Id: model2.ID().Ref(),
Key: util.ToPtrIfNotEmpty(model2.Key().String()),
Name: util.ToPtrIfNotEmpty(model2.Name()),
Description: util.ToPtrIfNotEmpty(model2.Description()),
Public: util.ToPtrIfNotEmpty(model2.Public()),
ProjectId: model2.Project().Ref(),
SchemaId: model2.Schema().Ref(),
Schema: util.ToPtrIfNotEmpty(NewSchema(schemaPackage2.Schema())),
MetadataSchemaId: model2.Metadata().Ref(),
MetadataSchema: util.ToPtrIfNotEmpty(NewSchema(schemaPackage2.MetaSchema())),
CreatedAt: lo.ToPtr(model2.ID().Timestamp()),
UpdatedAt: lo.ToPtr(model2.UpdatedAt()),
LastModified: util.ToPtrIfNotEmpty(mockTime),
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
result := NewModel(tt.args.m, tt.args.sp, tt.args.lastModified)
assert.Equal(t, tt.want, result)
})
}
}

func TestNewItemFieldChanges(t *testing.T) {

fID := id.NewFieldID()
v0 := value.MultipleFrom(value.TypeBool, []*value.Value{
value.New(value.TypeBool, false),
})
v1 := value.MultipleFrom(value.TypeBool, []*value.Value{
value.New(value.TypeBool, true),
})

type args struct {
change item.FieldChanges
}

tests := []struct {
name string
args args
want []FieldChange
}{
{
name: "success",
args: args{
change: item.FieldChanges{
item.FieldChange{
ID: fID,
Type: item.FieldChangeTypeAdd,
CurrentValue: value.MultipleFrom(v1.Type(), []*value.Value{v1.First()}),
PreviousValue: value.MultipleFrom(v0.Type(), []*value.Value{v0.First()}),
},
},
},
want: []FieldChange{
{
ID: fID,
Type: item.FieldChangeTypeAdd,
CurrentValue: v1.Interface(),
PreviousValue: v0.Interface(),
},
},
},
}
for _, test := range tests {
t.Run(string(test.name), func(t *testing.T) {
t.Parallel()
result := NewItemFieldChanges(test.args.change)
assert.Equal(t, test.want, result)
})
}
}
Comment on lines +96 to +144
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance test coverage with additional test cases.

While the test is well-structured, it could benefit from more comprehensive coverage:

  1. Add test cases for other field change types (Update, Remove)
  2. Include tests for different value types (String, Number, etc.)
  3. Add test cases for edge cases (nil values, empty changes)

Example additional test cases:

 tests := []struct {
     name string
     args args
     want []FieldChange
 }{
+    {
+        name: "update change type",
+        args: args{
+            change: item.FieldChanges{
+                item.FieldChange{
+                    ID:            fID,
+                    Type:          item.FieldChangeTypeUpdate,
+                    CurrentValue:  value.New(value.TypeString, "new"),
+                    PreviousValue: value.New(value.TypeString, "old"),
+                },
+            },
+        },
+        want: []FieldChange{
+            {
+                ID:            fID,
+                Type:          item.FieldChangeTypeUpdate,
+                CurrentValue:  "new",
+                PreviousValue: "old",
+            },
+        },
+    },
+    {
+        name: "empty changes",
+        args: args{
+            change: item.FieldChanges{},
+        },
+        want: []FieldChange{},
+    },
     // existing test cases...
 }

Committable suggestion skipped: line range outside the PR's diff.

18 changes: 18 additions & 0 deletions server/pkg/item/builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,3 +219,21 @@ func TestBuilder_IsMetadata(t *testing.T) {
b := New().IsMetadata(true)
assert.Equal(t, true, b.i.isMetadata)
}

func TestBuilder_UpdatedByUser(t *testing.T) {
uId := accountdomain.NewUserID()
uuid := New().UpdatedByUser(&uId)
assert.Equal(t, &uId, uuid.i.updatedByUser)
}

func TestBuilder_UpdatedByIntegration(t *testing.T) {
iid := id.NewIntegrationID()
uuid := New().UpdatedByIntegration(&iid)
assert.Equal(t, &iid, uuid.i.updatedByIntegration)
}

func TestBuilder_OriginalItem(t *testing.T) {
iId := id.NewItemID().Ref()
b := New().OriginalItem(iId)
assert.Equal(t, iId, b.i.originalItem)
}