From a9d7c5f9725887ab170d00e84c010c982f24e8f8 Mon Sep 17 00:00:00 2001 From: jasonkarel Date: Thu, 7 Nov 2024 14:11:13 +0700 Subject: [PATCH 1/8] chore: Increase domain package unit test coverage --- server/pkg/asset/asset_test.go | 2 + server/pkg/asset/builder_test.go | 6 +- server/pkg/asset/file_test.go | 126 +++++++++++++++++++++++- server/pkg/asset/preview_type_test.go | 12 ++- server/pkg/asset/status_test.go | 4 + server/pkg/asset/upload_builder_test.go | 34 +++++++ server/pkg/asset/upload_test.go | 28 ++++++ 7 files changed, 204 insertions(+), 8 deletions(-) create mode 100644 server/pkg/asset/upload_builder_test.go create mode 100644 server/pkg/asset/upload_test.go diff --git a/server/pkg/asset/asset_test.go b/server/pkg/asset/asset_test.go index 2897a71a03..27a5955ba7 100644 --- a/server/pkg/asset/asset_test.go +++ b/server/pkg/asset/asset_test.go @@ -34,6 +34,7 @@ func TestAsset_Type(t *testing.T) { uuid: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", thread: thid, archiveExtractionStatus: &gotStatus, + flatFiles: false, } assert.Equal(t, aid, got.ID()) @@ -46,6 +47,7 @@ func TestAsset_Type(t *testing.T) { assert.Equal(t, &wantPreviewType, got.PreviewType()) assert.Equal(t, "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", got.UUID()) assert.Equal(t, thid, got.Thread()) + assert.Equal(t, false, got.FlatFiles()) assert.Equal(t, &wantStatus, got.ArchiveExtractionStatus()) } diff --git a/server/pkg/asset/builder_test.go b/server/pkg/asset/builder_test.go index e233921d57..118aef9e7e 100644 --- a/server/pkg/asset/builder_test.go +++ b/server/pkg/asset/builder_test.go @@ -28,6 +28,7 @@ type Input struct { uuid string thread ThreadID archiveExtractionStatus *ArchiveExtractionStatus + flatFiles bool } func TestBuilder_Build(t *testing.T) { @@ -53,6 +54,7 @@ func TestBuilder_Build(t *testing.T) { uuid: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", thread: thid, archiveExtractionStatus: lo.ToPtr(ArchiveExtractionStatusPending), + flatFiles: false, }, want: &Asset{ id: aid, @@ -65,6 +67,7 @@ func TestBuilder_Build(t *testing.T) { uuid: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", thread: thid, archiveExtractionStatus: lo.ToPtr(ArchiveExtractionStatusPending), + flatFiles: false, }, }, { @@ -217,7 +220,8 @@ func TestBuilder_Build(t *testing.T) { Type(tt.input.previewType). UUID(tt.input.uuid). Thread(tt.input.thread). - ArchiveExtractionStatus(tt.input.archiveExtractionStatus) + ArchiveExtractionStatus(tt.input.archiveExtractionStatus). + FlatFiles(tt.input.flatFiles) if !tt.input.createdByUser.IsNil() { ab.CreatedByUser(tt.input.createdByUser) } diff --git a/server/pkg/asset/file_test.go b/server/pkg/asset/file_test.go index 414f3f71c6..1082c1e6e5 100644 --- a/server/pkg/asset/file_test.go +++ b/server/pkg/asset/file_test.go @@ -1,6 +1,7 @@ package asset import ( + "reflect" "testing" "github.com/stretchr/testify/assert" @@ -27,6 +28,13 @@ func TestFile_FileType(t *testing.T) { dir := NewFile().Name("dir").Path("/aaa").Children([]*File{c}).Build() assert.True(t, dir.IsDir()) + + // object is nil test + f = nil + assert.Equal(t, "", f.Name()) + assert.Equal(t, uint64(0), f.Size()) + assert.Equal(t, "", f.ContentType()) + assert.Equal(t, "", f.Path()) } func TestFile_Children(t *testing.T) { @@ -60,14 +68,37 @@ func TestFile_Files(t *testing.T) { }, } - assert.Equal(t, []*File{ + tests := []struct { + name string + files *File + want []*File + }{ { - path: "aaa/a/a.txt", + name: "success", + files: f, + want: []*File{ + { + path: "aaa/a/a.txt", + }, + { + path: "aaa/b.txt", + }, + }, }, { - path: "aaa/b.txt", + name: "file object is empyy", + files: nil, + want: nil, }, - }, f.FlattenChildren()) + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + flatten := tt.files.FlattenChildren() + if !reflect.DeepEqual(flatten, tt.want) { + t.Errorf("expected %v, got %v", tt.want, flatten) + } + }) + } } func TestFile_SetFiles(t *testing.T) { @@ -194,5 +225,90 @@ func Test_FoldFiles(t *testing.T) { } func Test_File_RootPath(t *testing.T) { - assert.Equal(t, "xx/xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/hoge.zip", (&File{path: "hoge.zip"}).RootPath("xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx")) + tests := []struct { + name string + file *File + uuid string + want string + }{ + { + name: "success", + file: &File{path: "hoge.zip"}, + uuid: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + want: "xx/xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/hoge.zip", + }, + { + name: "File object is nil", + file: nil, + uuid: "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + want: "", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := tt.file.RootPath(tt.uuid) + if result != tt.want { + t.Errorf("expected %q, got %q", tt.want, result) + } + }) + } +} + +func Test_Clone(t *testing.T) { + tests := []struct { + name string + file *File + want *File + }{ + { + name: "success", + file: &File{ + name: "test", + size: 1, + contentType: "type", + path: "hoge.zip", + children: []*File{ + {name: "a.txt", path: "/hello/good/a.txt", size: 10, contentType: "text/plain"}, + {name: "b.txt", path: "/hello/good/b.txt", size: 10, contentType: "text/plain"}, + }, + }, + want: &File{ + name: "test", + size: 1, + contentType: "type", + path: "hoge.zip", + children: []*File{ + {name: "a.txt", path: "/hello/good/a.txt", size: 10, contentType: "text/plain"}, + {name: "b.txt", path: "/hello/good/b.txt", size: 10, contentType: "text/plain"}, + }, + }, + }, + { + name: "file is nil", + file: nil, + want: nil, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + cloned := tt.file.Clone() + if !reflect.DeepEqual(cloned, tt.want) { + t.Errorf("expected %v, got %v", tt.want, cloned) + } + }) + } +} + +func Test_FilePath(t *testing.T) { + assert.Equal(t, + []string{ + "/hello/c.txt", + }, + (&File{ + name: "hello.zip", path: "/hello.zip", size: 100, contentType: "application/zip", + files: []*File{ + {name: "c.txt", path: "/hello/c.txt", size: 20, contentType: "text/plain"}, + }, + }).FilePaths(), + ) } diff --git a/server/pkg/asset/preview_type_test.go b/server/pkg/asset/preview_type_test.go index c7705d3df2..6aa4cec849 100644 --- a/server/pkg/asset/preview_type_test.go +++ b/server/pkg/asset/preview_type_test.go @@ -212,7 +212,7 @@ func TestPreviewType_DetectPreviewType(t *testing.T) { f1 := file.File{ Name: "image.png", ContentType: "image/png", - } + } want1 := PreviewTypeImage got1 := DetectPreviewType(&f1) assert.Equal(t, want1, *got1) @@ -220,7 +220,7 @@ func TestPreviewType_DetectPreviewType(t *testing.T) { f2 := file.File{ Name: "file.geojson", ContentType: "application/json", - } + } want2 := PreviewTypeGeo got2 := DetectPreviewType(&f2) assert.Equal(t, want2, *got2) @@ -278,6 +278,10 @@ func TestPreviewType_PreviewTypeFromExtension(t *testing.T) { want6 := PreviewTypeGeoMvt got6 := PreviewTypeFromExtension(ext6) assert.Equal(t, want6, got6) + + want7 := PreviewTypeUnknown + got7 := PreviewTypeFromExtension("") + assert.Equal(t, want7, got7) } func TestPreviewType_String(t *testing.T) { @@ -316,3 +320,7 @@ func TestPreviewType_StringRef(t *testing.T) { }) } } + +func TestPreviewType_Prev(t *testing.T) { + assert.Equal(t, func() *PreviewType { pt := PreviewType("image"); return &pt }(), PreviewTypeImage.Ref()) +} diff --git a/server/pkg/asset/status_test.go b/server/pkg/asset/status_test.go index 7a6bf316db..7b6eac53d9 100644 --- a/server/pkg/asset/status_test.go +++ b/server/pkg/asset/status_test.go @@ -75,6 +75,10 @@ func TestStatus_StatusFromRef(t *testing.T) { res = ArchiveExtractionStatusFromRef(s) assert.Equal(t, &f, res) + s = lo.ToPtr("test") + res = ArchiveExtractionStatusFromRef(s) + assert.Nil(t, res) + s = nil res = ArchiveExtractionStatusFromRef(s) assert.Nil(t, res) diff --git a/server/pkg/asset/upload_builder_test.go b/server/pkg/asset/upload_builder_test.go new file mode 100644 index 0000000000..930ba45709 --- /dev/null +++ b/server/pkg/asset/upload_builder_test.go @@ -0,0 +1,34 @@ +package asset + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestUploadBuilder_NewUpload(t *testing.T) { + ub := &UploadBuilder{ + u: &Upload{}, + } + assert.Equal(t, ub, NewUpload()) + + projectID := NewProjectID() + ubWithData := &UploadBuilder{ + u: &Upload{ + uuid: "1", + project: projectID, + fileName: "file.test", + contentLength: int64(1), + expiresAt: time.Now(), + }, + } + + timeNow := time.Now + assert.Equal(t, ubWithData, ubWithData.UUID("1")) + assert.Equal(t, ubWithData, ubWithData.Project(projectID)) + assert.Equal(t, ubWithData, ubWithData.FileName("file.test")) + assert.Equal(t, ubWithData, ubWithData.ContentLength(int64(1))) + assert.Equal(t, ubWithData, ubWithData.ExpiresAt(timeNow())) + assert.Equal(t, ubWithData.u, ubWithData.Build()) +} diff --git a/server/pkg/asset/upload_test.go b/server/pkg/asset/upload_test.go new file mode 100644 index 0000000000..1f8471b559 --- /dev/null +++ b/server/pkg/asset/upload_test.go @@ -0,0 +1,28 @@ +package asset + +import ( + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestUpload_Upload(t *testing.T) { + + projectID := NewProjectID() + timeNow := time.Now() + uploadWithData := &Upload{ + uuid: "1", + project: projectID, + fileName: "file.test", + contentLength: int64(1), + expiresAt: timeNow, + } + + assert.Equal(t, "1", uploadWithData.UUID()) + assert.Equal(t, projectID, uploadWithData.Project()) + assert.Equal(t, "file.test", uploadWithData.FileName()) + assert.Equal(t, int64(1), uploadWithData.ContentLength()) + assert.Equal(t, false, uploadWithData.Expired(timeNow)) + assert.Equal(t, timeNow, uploadWithData.ExpiresAt()) +} From e8585d97c8b0c89008a1958695f6e382b38f9fbd Mon Sep 17 00:00:00 2001 From: jasonkarel Date: Tue, 12 Nov 2024 12:50:44 +0700 Subject: [PATCH 2/8] add inteegrationapi UT --- server/pkg/asset/upload_builder_test.go | 5 +- server/pkg/integrationapi/asset_test.go | 184 +++++ server/pkg/integrationapi/comment_test.go | 61 ++ server/pkg/integrationapi/condition_test.go | 708 ++++++++++++++++++ server/pkg/integrationapi/item_export_test.go | 143 ++++ server/pkg/integrationapi/project_test.go | 41 + 6 files changed, 1139 insertions(+), 3 deletions(-) create mode 100644 server/pkg/integrationapi/comment_test.go create mode 100644 server/pkg/integrationapi/condition_test.go create mode 100644 server/pkg/integrationapi/item_export_test.go create mode 100644 server/pkg/integrationapi/project_test.go diff --git a/server/pkg/asset/upload_builder_test.go b/server/pkg/asset/upload_builder_test.go index 930ba45709..342ffffbf2 100644 --- a/server/pkg/asset/upload_builder_test.go +++ b/server/pkg/asset/upload_builder_test.go @@ -23,12 +23,11 @@ func TestUploadBuilder_NewUpload(t *testing.T) { expiresAt: time.Now(), }, } - - timeNow := time.Now + fixedTime := time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC) assert.Equal(t, ubWithData, ubWithData.UUID("1")) assert.Equal(t, ubWithData, ubWithData.Project(projectID)) assert.Equal(t, ubWithData, ubWithData.FileName("file.test")) assert.Equal(t, ubWithData, ubWithData.ContentLength(int64(1))) - assert.Equal(t, ubWithData, ubWithData.ExpiresAt(timeNow())) + assert.Equal(t, ubWithData, ubWithData.ExpiresAt(fixedTime)) assert.Equal(t, ubWithData.u, ubWithData.Build()) } diff --git a/server/pkg/integrationapi/asset_test.go b/server/pkg/integrationapi/asset_test.go index 1198903635..6ef5918db4 100644 --- a/server/pkg/integrationapi/asset_test.go +++ b/server/pkg/integrationapi/asset_test.go @@ -1,9 +1,14 @@ package integrationapi import ( + "reflect" "testing" + "time" "github.com/reearth/reearth-cms/server/pkg/asset" + "github.com/reearth/reearth-cms/server/pkg/id" + "github.com/reearth/reearth-cms/server/pkg/project" + "github.com/reearth/reearthx/account/accountdomain/user" "github.com/samber/lo" "github.com/stretchr/testify/assert" ) @@ -46,4 +51,183 @@ func TestToAssetFile(t *testing.T) { ContentType: lo.ToPtr(""), } assert.Equal(t, e, a) + + assert.Nil(t, ToAssetFile(nil, true)) +} + +func Test_NewAsset(t *testing.T) { + timeNow := time.Now() + name := "aaa" + path := "a/aaa" + uid := user.NewID() + pid := project.NewID() + a := asset.New().NewID().Project(pid).Size(100).NewUUID(). + CreatedByUser(uid).Thread(id.NewThreadID()).CreatedAt(timeNow).MustBuild() + + f1 := asset.NewFile().Name(name).Path(path).ContentType("s").Size(10).Build() + + tests := []struct { + name string + a *asset.Asset + f *asset.File + url string + all bool + want *Asset + }{ + { + name: "success", + a: a, + f: f1, + url: "www.", + all: true, + want: &Asset{ + Name: lo.ToPtr("aaa"), + Id: a.ID(), + Url: "www.", + CreatedAt: timeNow, + File: &File{ + Name: lo.ToPtr("aaa"), + Path: lo.ToPtr("/a/aaa"), + ContentType: lo.ToPtr("s"), + Size: lo.ToPtr(float32(10)), + }, + ContentType: lo.ToPtr("s"), + TotalSize: lo.ToPtr(float32(100)), + PreviewType: lo.ToPtr(Unknown), + ProjectId: pid, + }, + }, + { + name: "asset and file input is nil", + a: nil, + f: nil, + url: "www.", + all: false, + want: nil, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := NewAsset(tt.a, tt.f, tt.url, tt.all) + + if !reflect.DeepEqual(result, tt.want) { + t.Errorf("want %+v, got %+v", tt.want, result) + } + }) + } +} + +func TestToAssetArchiveExtractionStatus(t *testing.T) { + tests := []struct { + name string + input *asset.ArchiveExtractionStatus + expected *AssetArchiveExtractionStatus + }{ + { + name: "Nil input", + input: nil, + expected: nil, + }, + { + name: "Status done", + input: lo.ToPtr(asset.ArchiveExtractionStatusDone), + expected: lo.ToPtr(AssetArchiveExtractionStatus("done")), + }, + { + name: "Status failed", + input: lo.ToPtr(asset.ArchiveExtractionStatusFailed), + expected: lo.ToPtr(AssetArchiveExtractionStatus("failed")), + }, + { + name: "Status in progress", + input: lo.ToPtr(asset.ArchiveExtractionStatusInProgress), + expected: lo.ToPtr(AssetArchiveExtractionStatus("in_progress")), + }, + { + name: "Status pending", + input: lo.ToPtr(asset.ArchiveExtractionStatusPending), + expected: lo.ToPtr(AssetArchiveExtractionStatus("pending")), + }, + { + name: "Unknown status", + input: lo.ToPtr(asset.ArchiveExtractionStatus("unknown")), + expected: nil, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := ToAssetArchiveExtractionStatus(tt.input) + if !reflect.DeepEqual(result, tt.expected) { + t.Errorf("expected %v, got %v", tt.expected, result) + } + }) + } +} + +func TestToPreviewType(t *testing.T) { + tests := []struct { + name string + input *asset.PreviewType + expected *AssetPreviewType + }{ + { + name: "Nil input", + input: nil, + expected: lo.ToPtr(Unknown), + }, + { + name: "PreviewTypeGeo", + input: lo.ToPtr(asset.PreviewTypeGeo), + expected: lo.ToPtr(Geo), + }, + { + name: "PreviewTypeGeo3dTiles", + input: lo.ToPtr(asset.PreviewTypeGeo3dTiles), + expected: lo.ToPtr(Geo3dTiles), + }, + { + name: "PreviewTypeGeoMvt", + input: lo.ToPtr(asset.PreviewTypeGeoMvt), + expected: lo.ToPtr(GeoMvt), + }, + { + name: "PreviewTypeModel3d", + input: lo.ToPtr(asset.PreviewTypeModel3d), + expected: lo.ToPtr(Model3d), + }, + { + name: "PreviewTypeImage", + input: lo.ToPtr(asset.PreviewTypeImage), + expected: lo.ToPtr(Image), + }, + { + name: "PreviewTypeImageSvg", + input: lo.ToPtr(asset.PreviewTypeImageSvg), + expected: lo.ToPtr(ImageSvg), + }, + { + name: "PreviewTypeCSV", + input: lo.ToPtr(asset.PreviewTypeCSV), + expected: lo.ToPtr(Csv), + }, + { + name: "PreviewTypeUnknown", + input: lo.ToPtr(asset.PreviewTypeUnknown), + expected: lo.ToPtr(Unknown), + }, + { + name: "Unrecognized PreviewType", + input: lo.ToPtr(asset.PreviewType("unrecognized")), + expected: lo.ToPtr(Unknown), + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := ToPreviewType(tt.input) + assert.Equal(t, tt.expected, result) + }) + } } diff --git a/server/pkg/integrationapi/comment_test.go b/server/pkg/integrationapi/comment_test.go new file mode 100644 index 0000000000..32ed9b9602 --- /dev/null +++ b/server/pkg/integrationapi/comment_test.go @@ -0,0 +1,61 @@ +package integrationapi + +import ( + "testing" + + "github.com/reearth/reearth-cms/server/pkg/operator" + "github.com/reearth/reearth-cms/server/pkg/thread" + "github.com/samber/lo" + "github.com/stretchr/testify/assert" +) + +func TestNewComment(t *testing.T) { + uid := thread.NewUserID() + iid := operator.NewIntegrationID() + authorUser := operator.OperatorFromUser(uid) + authorIntegration := operator.OperatorFromIntegration(iid) + c := thread.NewComment(thread.NewCommentID(), authorUser, "test") + cIntegration := thread.NewComment(thread.NewCommentID(), authorIntegration, "test") + authorID := c.Author().User().Ref() + authorIntegrationID := cIntegration.Author().Integration().Ref() + tests := []struct { + name string + input *thread.Comment + expected *Comment + }{ + { + name: "Nil input", + input: nil, + expected: nil, + }, + { + name: "User author", + input: c, + expected: &Comment{ + Content: lo.ToPtr("test"), + CreatedAt: lo.ToPtr(c.CreatedAt()), + Id: c.ID().Ref(), + AuthorType: lo.ToPtr(User), + AuthorId: lo.ToPtr(any(authorID)), + }, + }, + { + name: "Integration author", + input: cIntegration, + expected: &Comment{ + Content: lo.ToPtr("test"), + CreatedAt: lo.ToPtr(cIntegration.CreatedAt()), + Id: cIntegration.ID().Ref(), + AuthorType: lo.ToPtr(Integrtaion), + AuthorId: lo.ToPtr(any(authorIntegrationID)), + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := NewComment(tt.input) + assert.Equal(t, tt.expected, result) + }) + } +} diff --git a/server/pkg/integrationapi/condition_test.go b/server/pkg/integrationapi/condition_test.go new file mode 100644 index 0000000000..9e649e2c17 --- /dev/null +++ b/server/pkg/integrationapi/condition_test.go @@ -0,0 +1,708 @@ +package integrationapi + +import ( + "testing" + "time" + + "github.com/reearth/reearth-cms/server/pkg/id" + "github.com/reearth/reearth-cms/server/pkg/item/view" + "github.com/samber/lo" + "github.com/stretchr/testify/assert" +) + +func TestFieldSelectorTypeInto(t *testing.T) { + tests := []struct { + name string + input FieldSelectorType + expected view.FieldType + }{ + { + name: "FieldSelectorTypeId", + input: FieldSelectorTypeId, + expected: view.FieldTypeId, + }, + { + name: "FieldSelectorTypeCreationDate", + input: FieldSelectorTypeCreationDate, + expected: view.FieldTypeCreationDate, + }, + { + name: "FieldSelectorTypeModificationDate", + input: FieldSelectorTypeModificationDate, + expected: view.FieldTypeModificationDate, + }, + { + name: "FieldSelectorTypeStatus", + input: FieldSelectorTypeStatus, + expected: view.FieldTypeStatus, + }, + { + name: "FieldSelectorTypeCreationUser", + input: FieldSelectorTypeCreationUser, + expected: view.FieldTypeCreationUser, + }, + { + name: "FieldSelectorTypeModificationUser", + input: FieldSelectorTypeModificationUser, + expected: view.FieldTypeModificationUser, + }, + { + name: "FieldSelectorTypeField", + input: FieldSelectorTypeField, + expected: view.FieldTypeField, + }, + { + name: "FieldSelectorTypeMetaField", + input: FieldSelectorTypeMetaField, + expected: view.FieldTypeMetaField, + }, + { + name: "Default case", + input: FieldSelectorType("999"), // An unrecognized type + expected: view.FieldTypeId, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := tt.input.Into() + assert.Equal(t, tt.expected, result) + }) + } +} + +func TestStringOperatorInto(t *testing.T) { + tests := []struct { + name string + input ConditionStringOperator + expected view.StringOperator + }{ + { + name: "contains", + input: Contains, + expected: view.StringOperatorContains, + }, + { + name: "NotContains", + input: NotContains, + expected: view.StringOperatorNotContains, + }, + { + name: "StartsWith", + input: StartsWith, + expected: view.StringOperatorStartsWith, + }, + { + name: "NotStartsWith", + input: NotStartsWith, + expected: view.StringOperatorNotStartsWith, + }, + { + name: "EndsWith", + input: EndsWith, + expected: view.StringOperatorEndsWith, + }, + { + name: "NotEndsWith", + input: NotEndsWith, + expected: view.StringOperatorNotEndsWith, + }, + { + name: "Default case", + input: ConditionStringOperator("999"), // An unrecognized type + expected: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := tt.input.Into() + assert.Equal(t, tt.expected, result) + }) + } +} + +func TestNumberOperatorInto(t *testing.T) { + tests := []struct { + name string + input ConditionNumberOperator + expected view.NumberOperator + }{ + { + name: "GreaterThan", + input: GreaterThan, + expected: view.NumberOperatorGreaterThan, + }, + { + name: "GreaterThanOrEqualTo", + input: GreaterThanOrEqualTo, + expected: view.NumberOperatorGreaterThanOrEqualTo, + }, + { + name: "LessThan", + input: LessThan, + expected: view.NumberOperatorLessThan, + }, + { + name: "LessThanOrEqualTo", + input: LessThanOrEqualTo, + expected: view.NumberOperatorLessThanOrEqualTo, + }, + { + name: "Default case", + input: ConditionNumberOperator("999"), // An unrecognized type + expected: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := tt.input.Into() + assert.Equal(t, tt.expected, result) + }) + } +} + +func TestBasicOperatorInto(t *testing.T) { + tests := []struct { + name string + input ConditionBasicOperator + expected view.BasicOperator + }{ + { + name: "Equals", + input: ConditionBasicOperatorEquals, + expected: view.BasicOperatorEquals, + }, + { + name: "NotEquals", + input: ConditionBasicOperatorNotEquals, + expected: view.BasicOperatorNotEquals, + }, + { + name: "Default case", + input: ConditionBasicOperator("999"), // An unrecognized type + expected: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := tt.input.Into() + assert.Equal(t, tt.expected, result) + }) + } +} + +func TestTimeOperatorInto(t *testing.T) { + tests := []struct { + name string + input ConditionTimeOperator + expected view.TimeOperator + }{ + { + name: "After", + input: After, + expected: view.TimeOperatorAfter, + }, + { + name: "AfterOrOn", + input: AfterOrOn, + expected: view.TimeOperatorAfterOrOn, + }, + { + name: "Before", + input: Before, + expected: view.TimeOperatorBefore, + }, + { + name: "BeforeOrOn", + input: BeforeOrOn, + expected: view.TimeOperatorBeforeOrOn, + }, + { + name: "OfThisWeek", + input: OfThisWeek, + expected: view.TimeOperatorOfThisWeek, + }, + { + name: "OfThisMonth", + input: OfThisMonth, + expected: view.TimeOperatorOfThisMonth, + }, + { + name: "OfThisYear", + input: OfThisYear, + expected: view.TimeOperatorOfThisYear, + }, + { + name: "Default case", + input: ConditionTimeOperator("999"), // An unrecognized type + expected: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := tt.input.Into() + assert.Equal(t, tt.expected, result) + }) + } +} + +func TestBoolOperatorInto(t *testing.T) { + tests := []struct { + name string + input ConditionBoolOperator + expected view.BoolOperator + }{ + { + name: "equals", + input: ConditionBoolOperatorEquals, + expected: view.BoolOperatorEquals, + }, + { + name: "not equals", + input: ConditionBoolOperatorNotEquals, + expected: view.BoolOperatorNotEquals, + }, + { + name: "Default case", + input: ConditionBoolOperator("999"), // An unrecognized type + expected: "", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := tt.input.Into() + assert.Equal(t, tt.expected, result) + }) + } +} + +func TestConditionNullableOperator_Into(t *testing.T) { + tests := []struct { + input ConditionNullableOperator + expected view.NullableOperator + }{ + {Empty, view.NullableOperatorEmpty}, + {NotEmpty, view.NullableOperatorNotEmpty}, + {ConditionNullableOperator("99"), ""}, // Test for default case + } + + for _, test := range tests { + result := test.input.Into() + if result != test.expected { + t.Errorf("For input %v, expected %v but got %v", test.input, test.expected, result) + } + } +} + +func TestConditionMultipleOperator_Into(t *testing.T) { + tests := []struct { + input ConditionMultipleOperator + expected view.MultipleOperator + }{ + {IncludesAny, view.MultipleOperatorIncludesAny}, + {NotIncludesAny, view.MultipleOperatorNotIncludesAny}, + {IncludesAll, view.MultipleOperatorIncludesAll}, + {NotIncludesAll, view.MultipleOperatorNotIncludesAll}, + {ConditionMultipleOperator("99"), ""}, // Test for default case + } + + for _, test := range tests { + result := test.input.Into() + if result != test.expected { + t.Errorf("For input %v, expected %v but got %v", test.input, test.expected, result) + } + } +} + +func TestFieldSelector_Into(t *testing.T) { + fieldType := FieldSelector{ + FieldId: id.NewFieldID().Ref(), + Type: lo.ToPtr(FieldSelectorTypeId), + } + tests := []struct { + name string + input FieldSelector + expected view.FieldSelector + }{ + { + name: "success", + input: FieldSelector{ + FieldId: fieldType.FieldId, + Type: fieldType.Type, + }, + expected: view.FieldSelector{ + Type: view.FieldTypeId, + ID: fieldType.FieldId, + }, + }, + } + + for _, test := range tests { + result := test.input.Into() + if result != test.expected { + t.Errorf("For input %v, expected %v but got %v", test.input, test.expected, result) + } + } +} + +func TestConditionInto(t *testing.T) { + fieldID := id.NewFieldID().Ref() + var pIntf *interface{} + var emptyInterface interface{} + pIntf = &emptyInterface + *pIntf = "test" + timeNow := time.Now() + + tests := []struct { + name string + condition *Condition + want *view.Condition + }{ + { + name: "success bool", + condition: &Condition{ + Bool: &struct { + FieldId FieldSelector "json:\"fieldId\"" + Operator ConditionBoolOperator "json:\"operator\"" + Value bool "json:\"value\"" + }{ + FieldId: FieldSelector{ + FieldId: fieldID, + Type: lo.ToPtr(FieldSelectorTypeId), + }, + Operator: ConditionBoolOperatorEquals, + Value: true, + }, + }, + want: &view.Condition{ + ConditionType: view.ConditionTypeBool, + BoolCondition: &view.BoolCondition{ + Field: view.FieldSelector{ + Type: view.FieldTypeId, + ID: fieldID, + }, + Op: view.BoolOperatorEquals, + Value: true, + }, + }, + }, + { + name: "success type string", + condition: &Condition{ + String: &struct { + FieldId FieldSelector "json:\"fieldId\"" + Operator ConditionStringOperator "json:\"operator\"" + Value string "json:\"value\"" + }{ + FieldId: FieldSelector{ + FieldId: fieldID, + Type: lo.ToPtr(FieldSelectorTypeId), + }, + Operator: Contains, + Value: "CONTAINS", + }, + }, + want: &view.Condition{ + ConditionType: view.ConditionTypeString, + StringCondition: &view.StringCondition{ + Field: view.FieldSelector{ + Type: view.FieldTypeId, + ID: fieldID, + }, + Op: view.StringOperatorContains, + Value: "CONTAINS", + }, + }, + }, + { + name: "success number", + condition: &Condition{ + Number: &struct { + FieldId FieldSelector "json:\"fieldId\"" + Operator ConditionNumberOperator "json:\"operator\"" + Value float32 "json:\"value\"" + }{ + FieldId: FieldSelector{ + FieldId: fieldID, + Type: lo.ToPtr(FieldSelectorTypeId), + }, + Operator: GreaterThanOrEqualTo, + Value: float32(2), + }, + }, + want: &view.Condition{ + ConditionType: view.ConditionTypeNumber, + NumberCondition: &view.NumberCondition{ + Field: view.FieldSelector{ + Type: view.FieldTypeId, + ID: fieldID, + }, + Op: view.NumberOperatorGreaterThanOrEqualTo, + Value: float64(2), + }, + }, + }, + { + name: "success basic", + condition: &Condition{ + Basic: &struct { + FieldId *FieldSelector "json:\"fieldId,omitempty\"" + Operator *ConditionBasicOperator "json:\"operator,omitempty\"" + Value *interface{} "json:\"value,omitempty\"" + }{ + FieldId: &FieldSelector{ + FieldId: fieldID, + Type: lo.ToPtr(FieldSelectorTypeId), + }, + Operator: lo.ToPtr(ConditionBasicOperatorEquals), + Value: pIntf, + }, + }, + want: &view.Condition{ + ConditionType: view.ConditionTypeBasic, + BasicCondition: &view.BasicCondition{ + Field: view.FieldSelector{ + Type: view.FieldTypeId, + ID: fieldID, + }, + Op: view.BasicOperatorEquals, + Value: "test", + }, + }, + }, + { + name: "success time", + condition: &Condition{ + Time: &struct { + FieldId FieldSelector "json:\"fieldId\"" + Operator ConditionTimeOperator "json:\"operator\"" + Value time.Time "json:\"value\"" + }{ + FieldId: FieldSelector{ + FieldId: fieldID, + Type: lo.ToPtr(FieldSelectorTypeId), + }, + Operator: After, + Value: timeNow, + }, + }, + want: &view.Condition{ + ConditionType: view.ConditionTypeTime, + TimeCondition: &view.TimeCondition{ + Field: view.FieldSelector{ + Type: view.FieldTypeId, + ID: fieldID, + }, + Op: view.TimeOperatorAfter, + Value: timeNow, + }, + }, + }, + { + name: "success nullable", + condition: &Condition{ + Nullable: &struct { + FieldId *FieldSelector "json:\"fieldId,omitempty\"" + Operator *ConditionNullableOperator "json:\"operator,omitempty\"" + }{ + FieldId: &FieldSelector{ + FieldId: fieldID, + Type: lo.ToPtr(FieldSelectorTypeId), + }, + Operator: lo.ToPtr(Empty), + }, + }, + want: &view.Condition{ + ConditionType: view.ConditionTypeNullable, + NullableCondition: &view.NullableCondition{ + Field: view.FieldSelector{ + Type: view.FieldTypeId, + ID: fieldID, + }, + Op: view.NullableOperatorEmpty, + }, + }, + }, + { + name: "success multiple", + condition: &Condition{ + Multiple: &struct { + FieldId FieldSelector "json:\"fieldId\"" + Operator ConditionMultipleOperator "json:\"operator\"" + Value []interface{} "json:\"value\"" + }{ + FieldId: FieldSelector{ + FieldId: fieldID, + Type: lo.ToPtr(FieldSelectorTypeId), + }, + Operator: IncludesAll, + Value: []any{ + pIntf, + }, + }, + }, + want: &view.Condition{ + ConditionType: view.ConditionTypeMultiple, + MultipleCondition: &view.MultipleCondition{ + Field: view.FieldSelector{ + ID: fieldID, + Type: view.FieldTypeId, + }, + Op: view.MultipleOperatorIncludesAll, + Value: []any{ + pIntf, + }, + }, + }, + }, + { + name: "success and", + condition: &Condition{ + And: &[]Condition{ + { + Bool: &struct { + FieldId FieldSelector "json:\"fieldId\"" + Operator ConditionBoolOperator "json:\"operator\"" + Value bool "json:\"value\"" + }{ + FieldId: FieldSelector{ + FieldId: fieldID, + Type: lo.ToPtr(FieldSelectorTypeId), + }, + Operator: ConditionBoolOperatorEquals, + Value: true, + }, + }, + { + Bool: &struct { + FieldId FieldSelector "json:\"fieldId\"" + Operator ConditionBoolOperator "json:\"operator\"" + Value bool "json:\"value\"" + }{ + FieldId: FieldSelector{ + FieldId: fieldID, + Type: lo.ToPtr(FieldSelectorTypeId), + }, + Operator: ConditionBoolOperatorEquals, + Value: true, + }, + }, + }, + }, + want: &view.Condition{ + ConditionType: view.ConditionTypeAnd, + AndCondition: &view.AndCondition{ + Conditions: []view.Condition{ + { + ConditionType: view.ConditionTypeBool, + BoolCondition: &view.BoolCondition{ + Field: view.FieldSelector{ + Type: view.FieldTypeId, + ID: fieldID, + }, + Op: view.BoolOperatorEquals, + Value: true, + }, + }, + { + ConditionType: view.ConditionTypeBool, + BoolCondition: &view.BoolCondition{ + Field: view.FieldSelector{ + Type: view.FieldTypeId, + ID: fieldID, + }, + Op: view.BoolOperatorEquals, + Value: true, + }, + }, + }, + }, + }, + }, + { + name: "success or", + condition: &Condition{ + Or: &[]Condition{ + { + Bool: &struct { + FieldId FieldSelector "json:\"fieldId\"" + Operator ConditionBoolOperator "json:\"operator\"" + Value bool "json:\"value\"" + }{ + FieldId: FieldSelector{ + FieldId: fieldID, + Type: lo.ToPtr(FieldSelectorTypeId), + }, + Operator: ConditionBoolOperatorEquals, + Value: true, + }, + }, + { + Bool: &struct { + FieldId FieldSelector "json:\"fieldId\"" + Operator ConditionBoolOperator "json:\"operator\"" + Value bool "json:\"value\"" + }{ + FieldId: FieldSelector{ + FieldId: fieldID, + Type: lo.ToPtr(FieldSelectorTypeId), + }, + Operator: ConditionBoolOperatorEquals, + Value: true, + }, + }, + }, + }, + want: &view.Condition{ + ConditionType: view.ConditionTypeOr, + OrCondition: &view.OrCondition{ + Conditions: []view.Condition{ + { + ConditionType: view.ConditionTypeBool, + BoolCondition: &view.BoolCondition{ + Field: view.FieldSelector{ + Type: view.FieldTypeId, + ID: fieldID, + }, + Op: view.BoolOperatorEquals, + Value: true, + }, + }, + { + ConditionType: view.ConditionTypeBool, + BoolCondition: &view.BoolCondition{ + Field: view.FieldSelector{ + Type: view.FieldTypeId, + ID: fieldID, + }, + Op: view.BoolOperatorEquals, + Value: true, + }, + }, + }, + }, + }, + }, + { + name: "success nil", + condition: nil, + want: nil, + }, + { + name: "empty condition", + condition: &Condition{}, + want: nil, + }, + } + for _, test := range tests { + result := test.condition.Into() + if !assert.Equal(t, result, test.want) { + t.Errorf("expected %+v but got %+v", test.want, result) + } + } +} diff --git a/server/pkg/integrationapi/item_export_test.go b/server/pkg/integrationapi/item_export_test.go new file mode 100644 index 0000000000..1d49f7937e --- /dev/null +++ b/server/pkg/integrationapi/item_export_test.go @@ -0,0 +1,143 @@ +package integrationapi + +import ( + "encoding/json" + "fmt" + "testing" + + "github.com/reearth/reearth-cms/server/pkg/exporters" + "github.com/reearth/reearth-cms/server/pkg/id" + "github.com/reearth/reearth-cms/server/pkg/item" + "github.com/reearth/reearth-cms/server/pkg/schema" + "github.com/reearth/reearth-cms/server/pkg/value" + "github.com/reearth/reearth-cms/server/pkg/version" + "github.com/reearth/reearthx/account/accountdomain" + "github.com/reearth/reearthx/util" + "github.com/samber/lo" + "github.com/stretchr/testify/assert" +) + +func TestToGeometryType(t *testing.T) { + tests := []struct { + input *exporters.GeometryType + expected *GeometryType + }{ + { + input: lo.ToPtr(exporters.GeometryTypePoint), + expected: lo.ToPtr(GeometryTypePoint), + }, + { + input: lo.ToPtr(exporters.GeometryTypeMultiPoint), + expected: lo.ToPtr(GeometryTypeMultiPoint), + }, + { + input: lo.ToPtr(exporters.GeometryTypeLineString), + expected: lo.ToPtr(GeometryTypeLineString), + }, + { + input: lo.ToPtr(exporters.GeometryTypeMultiLineString), + expected: lo.ToPtr(GeometryTypeMultiLineString), + }, + { + input: lo.ToPtr(exporters.GeometryTypePolygon), + expected: lo.ToPtr(GeometryTypePolygon), + }, + { + input: lo.ToPtr(exporters.GeometryTypeMultiPolygon), + expected: lo.ToPtr(GeometryTypeMultiPolygon), + }, + { + input: lo.ToPtr(exporters.GeometryTypeGeometryCollection), + expected: lo.ToPtr(GeometryTypeGeometryCollection), + }, + { + input: nil, + expected: nil, + }, + } + + for _, tt := range tests { + result := toGeometryType(tt.input) + assert.Equal(t, tt.expected, result, "For input %v, expected %v but got %v", tt.input, tt.expected, result) + } +} + +func TestFeatureCollectionFromItems(t *testing.T) { + iid := id.NewItemID() + sid := id.NewSchemaID() + mid := id.NewModelID() + tid := id.NewThreadID() + pid := id.NewProjectID() + gst := schema.GeometryObjectSupportedTypeList{schema.GeometryObjectSupportedTypePoint, schema.GeometryObjectSupportedTypeLineString} + sf1 := schema.NewField(schema.NewGeometryObject(gst).TypeProperty()).NewID().Name("geo1").Key(id.RandomKey()).MustBuild() + + s1 := schema.New().ID(sid).Fields([]*schema.Field{sf1}).Workspace(accountdomain.NewWorkspaceID()).Project(pid).MustBuild() + str := "{\"coordinates\":[139.28179282584915,36.58570985749664],\"type\":\"Point\"}" + fi1 := item.NewField(sf1.ID(), value.TypeGeometryObject.Value(str).AsMultiple(), nil) + + i1 := item.New(). + ID(iid). + Schema(sid). + Project(pid). + Fields([]*item.Field{fi1}). + Model(mid). + Thread(tid). + MustBuild() + v1 := version.New() + vi1 := version.MustBeValue(v1, nil, version.NewRefs(version.Latest), util.Now(), i1) + // with geometry fields + ver1 := item.VersionedList{vi1} + + tests := []struct { + name string + inputVer item.VersionedList + inputSchema *schema.Schema + expected *FeatureCollection + expectError bool + }{ + { + name: "Valid input", + inputVer: ver1, + inputSchema: s1, + expected: &FeatureCollection{ + Features: &[]Feature{ + { + Id: &iid, + Geometry: &Geometry{ + Coordinates: &Geometry_Coordinates{ + union: json.RawMessage([]byte("[139.28179282584915,36.58570985749664]")), + }, + Type: lo.ToPtr(GeometryTypePoint), + }, + Properties: &map[string]interface{}{}, + Type: lo.ToPtr(FeatureTypeFeature), + }, + }, + Type: lo.ToPtr(FeatureCollectionTypeFeatureCollection), + }, + expectError: false, + }, + { + name: "Invalid input - nil schema", + inputVer: item.VersionedList{}, + inputSchema: nil, + expectError: true, + }, + { + name: "Invalid input - empty VersionedList", + inputVer: item.VersionedList{}, + inputSchema: &schema.Schema{}, + expectError: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result, err := FeatureCollectionFromItems(tt.inputVer, tt.inputSchema) + assert.Equal(t, tt.expected, result, "FeatureCollectionFromItems() expected %v but got %v", tt.expected, result) + if (err != nil) == tt.expectError { + fmt.Printf("Error is not matched") + } + }) + } +} diff --git a/server/pkg/integrationapi/project_test.go b/server/pkg/integrationapi/project_test.go new file mode 100644 index 0000000000..9e7269291b --- /dev/null +++ b/server/pkg/integrationapi/project_test.go @@ -0,0 +1,41 @@ +package integrationapi + +import ( + "testing" + "time" + + "github.com/reearth/reearth-cms/server/pkg/project" + "github.com/samber/lo" + "github.com/stretchr/testify/assert" +) + +func Test_NewProject(t *testing.T) { + timeNow := time.Now() + p1 := project.New().ID(project.NewID()).Workspace(project.NewWorkspaceID()). + Name("test").Description("testing").Alias("testalias").UpdatedAt(timeNow).MustBuild() + tests := []struct { + name string + p *project.Project + want Project + }{ + { + name: "success", + p: p1, + want: Project{ + Id: p1.ID().Ref(), + WorkspaceId: p1.Workspace().Ref(), + Alias: lo.ToPtr(p1.Alias()), + Name: lo.ToPtr(p1.Name()), + Description: lo.ToPtr(p1.Description()), + CreatedAt: lo.ToPtr(p1.CreatedAt()), + UpdatedAt: lo.ToPtr(p1.UpdatedAt()), + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := NewProject(p1) + assert.Equal(t, tt.want, result) + }) + } +} From 4328fb0f2d3a6ad63dd8418eed0deab2fd48e598 Mon Sep 17 00:00:00 2001 From: jasonkarel Date: Wed, 13 Nov 2024 12:48:26 +0700 Subject: [PATCH 3/8] minor fix on ut variable assignation --- server/pkg/integrationapi/project_test.go | 2 +- server/pkg/integrationapi/value_test.go | 30 +++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/server/pkg/integrationapi/project_test.go b/server/pkg/integrationapi/project_test.go index 9e7269291b..b149c40db9 100644 --- a/server/pkg/integrationapi/project_test.go +++ b/server/pkg/integrationapi/project_test.go @@ -34,7 +34,7 @@ func Test_NewProject(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - result := NewProject(p1) + result := NewProject(tt.p) assert.Equal(t, tt.want, result) }) } diff --git a/server/pkg/integrationapi/value_test.go b/server/pkg/integrationapi/value_test.go index d7b0dcc14a..87971daf97 100644 --- a/server/pkg/integrationapi/value_test.go +++ b/server/pkg/integrationapi/value_test.go @@ -220,3 +220,33 @@ func TestToValueType(t *testing.T) { }) } } + +// func TestToValues(t *testing.T) { +// type args struct { +// valueMultiple *value.Multiple +// schemaField *schema.Field +// assets *AssetContext +// } +// pid := id.NewProjectID() +// uid := accountdomain.NewUserID() + +// asset1 := asset.New().NewID().Project(pid).CreatedByUser(uid).Size(1000).Thread(id.NewThreadID()).NewUUID().MustBuild() +// tests := []struct { +// name string +// args args +// want any +// }{ +// { +// name: "success", +// args: args{ +// valueMultiple: value.NewMultiple(value.TypeBool, []any{true, false}), +// schemaField: schema.New().MustBuild().Field(schema.NewFieldID()), +// assets: &AssetContext{ +// Map: asset.Map{ +// asset1.ID(): asset1, +// }, +// }, +// }, +// }, +// } +// } From 889570714d6b23292d0acbc2aeb057045513386a Mon Sep 17 00:00:00 2001 From: jasonkarel Date: Thu, 14 Nov 2024 12:19:08 +0700 Subject: [PATCH 4/8] erase unnecessary code --- server/pkg/integrationapi/value_test.go | 30 ------------------------- 1 file changed, 30 deletions(-) diff --git a/server/pkg/integrationapi/value_test.go b/server/pkg/integrationapi/value_test.go index 87971daf97..d7b0dcc14a 100644 --- a/server/pkg/integrationapi/value_test.go +++ b/server/pkg/integrationapi/value_test.go @@ -220,33 +220,3 @@ func TestToValueType(t *testing.T) { }) } } - -// func TestToValues(t *testing.T) { -// type args struct { -// valueMultiple *value.Multiple -// schemaField *schema.Field -// assets *AssetContext -// } -// pid := id.NewProjectID() -// uid := accountdomain.NewUserID() - -// asset1 := asset.New().NewID().Project(pid).CreatedByUser(uid).Size(1000).Thread(id.NewThreadID()).NewUUID().MustBuild() -// tests := []struct { -// name string -// args args -// want any -// }{ -// { -// name: "success", -// args: args{ -// valueMultiple: value.NewMultiple(value.TypeBool, []any{true, false}), -// schemaField: schema.New().MustBuild().Field(schema.NewFieldID()), -// assets: &AssetContext{ -// Map: asset.Map{ -// asset1.ID(): asset1, -// }, -// }, -// }, -// }, -// } -// } From a5a22dc9d3ab0ff6c8ab1b8fefd743bfa3b383c7 Mon Sep 17 00:00:00 2001 From: jasonkarel Date: Mon, 18 Nov 2024 12:32:15 +0700 Subject: [PATCH 5/8] fix upload builder ut to test each pulbic method --- server/pkg/asset/upload_builder_test.go | 188 ++++++++++++++++++-- server/pkg/integrationapi/asset_test.go | 12 +- server/pkg/integrationapi/condition_test.go | 62 ++++--- 3 files changed, 222 insertions(+), 40 deletions(-) diff --git a/server/pkg/asset/upload_builder_test.go b/server/pkg/asset/upload_builder_test.go index 342ffffbf2..1560760385 100644 --- a/server/pkg/asset/upload_builder_test.go +++ b/server/pkg/asset/upload_builder_test.go @@ -4,15 +4,165 @@ import ( "testing" "time" + "github.com/reearth/reearth-cms/server/pkg/id" "github.com/stretchr/testify/assert" ) func TestUploadBuilder_NewUpload(t *testing.T) { - ub := &UploadBuilder{ - u: &Upload{}, + tests := []struct { + name string + want *UploadBuilder + }{ + { + name: "success", + want: &UploadBuilder{ + u: &Upload{}, + }, + }, + } + for _, test := range tests { + t.Run(string(test.name), func(t *testing.T) { + t.Parallel() + result := NewUpload() + assert.Equal(t, test.want, result) + }) + } +} + +func TestUploadBuilderUUID(t *testing.T) { + + tests := []struct { + name string + input string + want *UploadBuilder + }{ + { + name: "success", + input: "123", + want: &UploadBuilder{ + &Upload{ + uuid: "123", + }, + }, + }, + } + for _, test := range tests { + t.Run(string(test.name), func(t *testing.T) { + t.Parallel() + ub := NewUpload() + result := ub.UUID(test.input) + assert.Equal(t, test.want, result) + }) + } +} + +func TestUploadBuilderProject(t *testing.T) { + projectID := id.NewProjectID() + tests := []struct { + name string + input ProjectID + want *UploadBuilder + }{ + { + name: "success", + input: projectID, + want: &UploadBuilder{ + &Upload{ + project: projectID, + }, + }, + }, + } + for _, test := range tests { + t.Run(string(test.name), func(t *testing.T) { + t.Parallel() + ub := NewUpload() + result := ub.Project(test.input) + assert.Equal(t, test.want, result) + }) + } +} + +func TestUploadBuilderFileName(t *testing.T) { + tests := []struct { + name string + input string + want *UploadBuilder + }{ + { + name: "success", + input: "file.test", + want: &UploadBuilder{ + &Upload{ + fileName: "file.test", + }, + }, + }, } - assert.Equal(t, ub, NewUpload()) + for _, test := range tests { + t.Run(string(test.name), func(t *testing.T) { + t.Parallel() + ub := NewUpload() + result := ub.FileName(test.input) + assert.Equal(t, test.want, result) + }) + } +} +func TestUploadBuilderContentLength(t *testing.T) { + tests := []struct { + name string + input int64 + want *UploadBuilder + }{ + { + name: "success", + input: 2, + want: &UploadBuilder{ + &Upload{ + contentLength: 2, + }, + }, + }, + } + for _, test := range tests { + t.Run(string(test.name), func(t *testing.T) { + t.Parallel() + ub := NewUpload() + result := ub.ContentLength(test.input) + assert.Equal(t, test.want, result) + }) + } +} + +func TestUploadBuilderExpiresAt(t *testing.T) { + fixedTime := time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC) + tests := []struct { + name string + input time.Time + want *UploadBuilder + }{ + { + name: "success", + input: fixedTime, + want: &UploadBuilder{ + &Upload{ + expiresAt: fixedTime, + }, + }, + }, + } + for _, test := range tests { + t.Run(string(test.name), func(t *testing.T) { + t.Parallel() + ub := NewUpload() + result := ub.ExpiresAt(test.input) + assert.Equal(t, test.want, result) + }) + } +} + +func TestUploadBuilderBuild(t *testing.T) { projectID := NewProjectID() ubWithData := &UploadBuilder{ u: &Upload{ @@ -23,11 +173,29 @@ func TestUploadBuilder_NewUpload(t *testing.T) { expiresAt: time.Now(), }, } - fixedTime := time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC) - assert.Equal(t, ubWithData, ubWithData.UUID("1")) - assert.Equal(t, ubWithData, ubWithData.Project(projectID)) - assert.Equal(t, ubWithData, ubWithData.FileName("file.test")) - assert.Equal(t, ubWithData, ubWithData.ContentLength(int64(1))) - assert.Equal(t, ubWithData, ubWithData.ExpiresAt(fixedTime)) - assert.Equal(t, ubWithData.u, ubWithData.Build()) + now := time.Now() + tests := []struct { + name string + input time.Time + want *Upload + }{ + { + name: "success", + input: now, + want: &Upload{ + uuid: "1", + project: projectID, + fileName: "file.test", + contentLength: int64(1), + expiresAt: time.Now(), + }, + }, + } + for _, test := range tests { + t.Run(string(test.name), func(t *testing.T) { + t.Parallel() + result := ubWithData.Build() + assert.Equal(t, test.want, result) + }) + } } diff --git a/server/pkg/integrationapi/asset_test.go b/server/pkg/integrationapi/asset_test.go index 6ef5918db4..03dafb5d4a 100644 --- a/server/pkg/integrationapi/asset_test.go +++ b/server/pkg/integrationapi/asset_test.go @@ -132,22 +132,22 @@ func TestToAssetArchiveExtractionStatus(t *testing.T) { { name: "Status done", input: lo.ToPtr(asset.ArchiveExtractionStatusDone), - expected: lo.ToPtr(AssetArchiveExtractionStatus("done")), + expected: lo.ToPtr(Done), }, { name: "Status failed", input: lo.ToPtr(asset.ArchiveExtractionStatusFailed), - expected: lo.ToPtr(AssetArchiveExtractionStatus("failed")), + expected: lo.ToPtr(Failed), }, { name: "Status in progress", input: lo.ToPtr(asset.ArchiveExtractionStatusInProgress), - expected: lo.ToPtr(AssetArchiveExtractionStatus("in_progress")), + expected: lo.ToPtr(InProgress), }, { name: "Status pending", input: lo.ToPtr(asset.ArchiveExtractionStatusPending), - expected: lo.ToPtr(AssetArchiveExtractionStatus("pending")), + expected: lo.ToPtr(Pending), }, { name: "Unknown status", @@ -158,9 +158,10 @@ func TestToAssetArchiveExtractionStatus(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() result := ToAssetArchiveExtractionStatus(tt.input) if !reflect.DeepEqual(result, tt.expected) { - t.Errorf("expected %v, got %v", tt.expected, result) + t.Errorf("ToAssetArchiveExtractionStatus() expected %v, got %v", tt.expected, result) } }) } @@ -226,6 +227,7 @@ func TestToPreviewType(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() result := ToPreviewType(tt.input) assert.Equal(t, tt.expected, result) }) diff --git a/server/pkg/integrationapi/condition_test.go b/server/pkg/integrationapi/condition_test.go index 9e649e2c17..bee07e9d14 100644 --- a/server/pkg/integrationapi/condition_test.go +++ b/server/pkg/integrationapi/condition_test.go @@ -65,6 +65,7 @@ func TestFieldSelectorTypeInto(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() result := tt.input.Into() assert.Equal(t, tt.expected, result) }) @@ -116,6 +117,7 @@ func TestStringOperatorInto(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() result := tt.input.Into() assert.Equal(t, tt.expected, result) }) @@ -157,6 +159,7 @@ func TestNumberOperatorInto(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() result := tt.input.Into() assert.Equal(t, tt.expected, result) }) @@ -188,6 +191,7 @@ func TestBasicOperatorInto(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() result := tt.input.Into() assert.Equal(t, tt.expected, result) }) @@ -244,6 +248,7 @@ func TestTimeOperatorInto(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() result := tt.input.Into() assert.Equal(t, tt.expected, result) }) @@ -275,6 +280,7 @@ func TestBoolOperatorInto(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() result := tt.input.Into() assert.Equal(t, tt.expected, result) }) @@ -283,39 +289,43 @@ func TestBoolOperatorInto(t *testing.T) { func TestConditionNullableOperator_Into(t *testing.T) { tests := []struct { + name string input ConditionNullableOperator expected view.NullableOperator }{ - {Empty, view.NullableOperatorEmpty}, - {NotEmpty, view.NullableOperatorNotEmpty}, - {ConditionNullableOperator("99"), ""}, // Test for default case + {"success nullable operator", Empty, view.NullableOperatorEmpty}, + {"success nullable operator not empty", NotEmpty, view.NullableOperatorNotEmpty}, + {"success default case", ConditionNullableOperator("99"), ""}, // Test for default case } for _, test := range tests { - result := test.input.Into() - if result != test.expected { - t.Errorf("For input %v, expected %v but got %v", test.input, test.expected, result) - } + t.Run(string(test.name), func(t *testing.T) { + t.Parallel() + result := test.input.Into() + assert.Equal(t, test.expected, result) + }) } } func TestConditionMultipleOperator_Into(t *testing.T) { tests := []struct { + name string input ConditionMultipleOperator expected view.MultipleOperator }{ - {IncludesAny, view.MultipleOperatorIncludesAny}, - {NotIncludesAny, view.MultipleOperatorNotIncludesAny}, - {IncludesAll, view.MultipleOperatorIncludesAll}, - {NotIncludesAll, view.MultipleOperatorNotIncludesAll}, - {ConditionMultipleOperator("99"), ""}, // Test for default case + {"success IncludeAny", IncludesAny, view.MultipleOperatorIncludesAny}, + {"success NotIncludesAny", NotIncludesAny, view.MultipleOperatorNotIncludesAny}, + {"success IncludesAll", IncludesAll, view.MultipleOperatorIncludesAll}, + {"success NotIncludesAll", NotIncludesAll, view.MultipleOperatorNotIncludesAll}, + {"success default case", ConditionMultipleOperator("99"), ""}, // Test for default case } for _, test := range tests { - result := test.input.Into() - if result != test.expected { - t.Errorf("For input %v, expected %v but got %v", test.input, test.expected, result) - } + t.Run(string(test.name), func(t *testing.T) { + t.Parallel() + result := test.input.Into() + assert.Equal(t, test.expected, result) + }) } } @@ -343,10 +353,11 @@ func TestFieldSelector_Into(t *testing.T) { } for _, test := range tests { - result := test.input.Into() - if result != test.expected { - t.Errorf("For input %v, expected %v but got %v", test.input, test.expected, result) - } + t.Run(string(test.name), func(t *testing.T) { + t.Parallel() + result := test.input.Into() + assert.Equal(t, test.expected, result) + }) } } @@ -699,10 +710,11 @@ func TestConditionInto(t *testing.T) { want: nil, }, } - for _, test := range tests { - result := test.condition.Into() - if !assert.Equal(t, result, test.want) { - t.Errorf("expected %+v but got %+v", test.want, result) - } + for _, tc := range tests { + tc := tc + t.Run(tc.name, func(t *testing.T) { + t.Parallel() + assert.Equal(t, tc.want, tc.condition.Into()) + }) } } From 1644c4c9b9fe597e96d40bb211c1ed584245ce46 Mon Sep 17 00:00:00 2001 From: jasonkarel Date: Mon, 18 Nov 2024 13:46:10 +0700 Subject: [PATCH 6/8] fix item export ut setup --- server/pkg/integrationapi/item_export_test.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/server/pkg/integrationapi/item_export_test.go b/server/pkg/integrationapi/item_export_test.go index 1d49f7937e..e7d14c7847 100644 --- a/server/pkg/integrationapi/item_export_test.go +++ b/server/pkg/integrationapi/item_export_test.go @@ -2,7 +2,6 @@ package integrationapi import ( "encoding/json" - "fmt" "testing" "github.com/reearth/reearth-cms/server/pkg/exporters" @@ -135,8 +134,10 @@ func TestFeatureCollectionFromItems(t *testing.T) { t.Run(tt.name, func(t *testing.T) { result, err := FeatureCollectionFromItems(tt.inputVer, tt.inputSchema) assert.Equal(t, tt.expected, result, "FeatureCollectionFromItems() expected %v but got %v", tt.expected, result) - if (err != nil) == tt.expectError { - fmt.Printf("Error is not matched") + if tt.expectError { + assert.Error(t, err, "Expected an error but got none") + } else { + assert.NoError(t, err, "Expected no error but got: %v", err) } }) } From b8bc79380bb3d9eb8834e87018a24613e9b27d51 Mon Sep 17 00:00:00 2001 From: jasonkarel Date: Mon, 18 Nov 2024 15:36:55 +0700 Subject: [PATCH 7/8] fix time variable in upload builder build test --- server/pkg/asset/upload_builder_test.go | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/server/pkg/asset/upload_builder_test.go b/server/pkg/asset/upload_builder_test.go index 1560760385..ad03a6dd52 100644 --- a/server/pkg/asset/upload_builder_test.go +++ b/server/pkg/asset/upload_builder_test.go @@ -163,6 +163,7 @@ func TestUploadBuilderExpiresAt(t *testing.T) { } func TestUploadBuilderBuild(t *testing.T) { + now := time.Now() projectID := NewProjectID() ubWithData := &UploadBuilder{ u: &Upload{ @@ -170,10 +171,10 @@ func TestUploadBuilderBuild(t *testing.T) { project: projectID, fileName: "file.test", contentLength: int64(1), - expiresAt: time.Now(), + expiresAt: now, }, } - now := time.Now() + tests := []struct { name string input time.Time @@ -187,7 +188,7 @@ func TestUploadBuilderBuild(t *testing.T) { project: projectID, fileName: "file.test", contentLength: int64(1), - expiresAt: time.Now(), + expiresAt: now, }, }, } From e86d83ee10fde376085dd2b1ca658b2142aa8131 Mon Sep 17 00:00:00 2001 From: jasonkarel Date: Tue, 26 Nov 2024 12:31:20 +0700 Subject: [PATCH 8/8] fix ut format to add paralel --- server/pkg/asset/file_test.go | 17 +++++++---------- server/pkg/asset/preview_type_test.go | 1 + server/pkg/asset/upload_test.go | 2 +- server/pkg/integrationapi/asset_test.go | 10 +++------- server/pkg/integrationapi/comment_test.go | 1 + server/pkg/integrationapi/item_export_test.go | 17 +++++++++++++++-- server/pkg/integrationapi/project_test.go | 1 + 7 files changed, 29 insertions(+), 20 deletions(-) diff --git a/server/pkg/asset/file_test.go b/server/pkg/asset/file_test.go index 1082c1e6e5..664035b73b 100644 --- a/server/pkg/asset/file_test.go +++ b/server/pkg/asset/file_test.go @@ -1,7 +1,6 @@ package asset import ( - "reflect" "testing" "github.com/stretchr/testify/assert" @@ -93,10 +92,9 @@ func TestFile_Files(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() flatten := tt.files.FlattenChildren() - if !reflect.DeepEqual(flatten, tt.want) { - t.Errorf("expected %v, got %v", tt.want, flatten) - } + assert.Equal(t, flatten, tt.want) }) } } @@ -246,10 +244,9 @@ func Test_File_RootPath(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() result := tt.file.RootPath(tt.uuid) - if result != tt.want { - t.Errorf("expected %q, got %q", tt.want, result) - } + assert.Equal(t, result, tt.want) }) } } @@ -291,15 +288,15 @@ func Test_Clone(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() cloned := tt.file.Clone() - if !reflect.DeepEqual(cloned, tt.want) { - t.Errorf("expected %v, got %v", tt.want, cloned) - } + assert.Equal(t, cloned, tt.want) }) } } func Test_FilePath(t *testing.T) { + t.Parallel() assert.Equal(t, []string{ "/hello/c.txt", diff --git a/server/pkg/asset/preview_type_test.go b/server/pkg/asset/preview_type_test.go index 6aa4cec849..bdd324bce8 100644 --- a/server/pkg/asset/preview_type_test.go +++ b/server/pkg/asset/preview_type_test.go @@ -322,5 +322,6 @@ func TestPreviewType_StringRef(t *testing.T) { } func TestPreviewType_Prev(t *testing.T) { + t.Parallel() assert.Equal(t, func() *PreviewType { pt := PreviewType("image"); return &pt }(), PreviewTypeImage.Ref()) } diff --git a/server/pkg/asset/upload_test.go b/server/pkg/asset/upload_test.go index 1f8471b559..22069842be 100644 --- a/server/pkg/asset/upload_test.go +++ b/server/pkg/asset/upload_test.go @@ -8,7 +8,7 @@ import ( ) func TestUpload_Upload(t *testing.T) { - + t.Parallel() projectID := NewProjectID() timeNow := time.Now() uploadWithData := &Upload{ diff --git a/server/pkg/integrationapi/asset_test.go b/server/pkg/integrationapi/asset_test.go index 03dafb5d4a..a52cce19cf 100644 --- a/server/pkg/integrationapi/asset_test.go +++ b/server/pkg/integrationapi/asset_test.go @@ -1,7 +1,6 @@ package integrationapi import ( - "reflect" "testing" "time" @@ -109,11 +108,10 @@ func Test_NewAsset(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() result := NewAsset(tt.a, tt.f, tt.url, tt.all) - if !reflect.DeepEqual(result, tt.want) { - t.Errorf("want %+v, got %+v", tt.want, result) - } + assert.Equal(t, result, tt.want) }) } } @@ -160,9 +158,7 @@ func TestToAssetArchiveExtractionStatus(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() result := ToAssetArchiveExtractionStatus(tt.input) - if !reflect.DeepEqual(result, tt.expected) { - t.Errorf("ToAssetArchiveExtractionStatus() expected %v, got %v", tt.expected, result) - } + assert.Equal(t, result, tt.expected) }) } } diff --git a/server/pkg/integrationapi/comment_test.go b/server/pkg/integrationapi/comment_test.go index 32ed9b9602..d299f5fe67 100644 --- a/server/pkg/integrationapi/comment_test.go +++ b/server/pkg/integrationapi/comment_test.go @@ -54,6 +54,7 @@ func TestNewComment(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() result := NewComment(tt.input) assert.Equal(t, tt.expected, result) }) diff --git a/server/pkg/integrationapi/item_export_test.go b/server/pkg/integrationapi/item_export_test.go index e7d14c7847..63f1811243 100644 --- a/server/pkg/integrationapi/item_export_test.go +++ b/server/pkg/integrationapi/item_export_test.go @@ -18,46 +18,58 @@ import ( func TestToGeometryType(t *testing.T) { tests := []struct { + name string input *exporters.GeometryType expected *GeometryType }{ { + name: "success type point", input: lo.ToPtr(exporters.GeometryTypePoint), expected: lo.ToPtr(GeometryTypePoint), }, { + name: "success type multi point", input: lo.ToPtr(exporters.GeometryTypeMultiPoint), expected: lo.ToPtr(GeometryTypeMultiPoint), }, { + name: "success type line string", input: lo.ToPtr(exporters.GeometryTypeLineString), expected: lo.ToPtr(GeometryTypeLineString), }, { + name: "success type multi line string", input: lo.ToPtr(exporters.GeometryTypeMultiLineString), expected: lo.ToPtr(GeometryTypeMultiLineString), }, { + name: "success type polygon", input: lo.ToPtr(exporters.GeometryTypePolygon), expected: lo.ToPtr(GeometryTypePolygon), }, { + name: "success type multi polygon", input: lo.ToPtr(exporters.GeometryTypeMultiPolygon), expected: lo.ToPtr(GeometryTypeMultiPolygon), }, { + name: "success type geometry collection", input: lo.ToPtr(exporters.GeometryTypeGeometryCollection), expected: lo.ToPtr(GeometryTypeGeometryCollection), }, { + name: "success nil", input: nil, expected: nil, }, } for _, tt := range tests { - result := toGeometryType(tt.input) - assert.Equal(t, tt.expected, result, "For input %v, expected %v but got %v", tt.input, tt.expected, result) + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + result := toGeometryType(tt.input) + assert.Equal(t, tt.expected, result) + }) } } @@ -132,6 +144,7 @@ func TestFeatureCollectionFromItems(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() result, err := FeatureCollectionFromItems(tt.inputVer, tt.inputSchema) assert.Equal(t, tt.expected, result, "FeatureCollectionFromItems() expected %v but got %v", tt.expected, result) if tt.expectError { diff --git a/server/pkg/integrationapi/project_test.go b/server/pkg/integrationapi/project_test.go index b149c40db9..25244d48cc 100644 --- a/server/pkg/integrationapi/project_test.go +++ b/server/pkg/integrationapi/project_test.go @@ -34,6 +34,7 @@ func Test_NewProject(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + t.Parallel() result := NewProject(tt.p) assert.Equal(t, tt.want, result) })