diff --git a/server/internal/usecase/interactor/item_test.go b/server/internal/usecase/interactor/item_test.go index a8ce0df47..cf2c52573 100644 --- a/server/internal/usecase/interactor/item_test.go +++ b/server/internal/usecase/interactor/item_test.go @@ -3,6 +3,7 @@ package interactor import ( "context" "errors" + "io" "testing" "time" @@ -11,6 +12,7 @@ import ( "github.com/reearth/reearth-cms/server/internal/usecase/interfaces" "github.com/reearth/reearth-cms/server/internal/usecase/repo" "github.com/reearth/reearth-cms/server/pkg/id" + "github.com/reearth/reearth-cms/server/pkg/integrationapi" "github.com/reearth/reearth-cms/server/pkg/item" "github.com/reearth/reearth-cms/server/pkg/model" "github.com/reearth/reearth-cms/server/pkg/project" @@ -22,6 +24,7 @@ import ( "github.com/reearth/reearthx/account/accountdomain/user" "github.com/reearth/reearthx/account/accountdomain/workspace" "github.com/reearth/reearthx/account/accountusecase" + "github.com/reearth/reearthx/i18n" "github.com/reearth/reearthx/rerror" "github.com/reearth/reearthx/usecasex" "github.com/reearth/reearthx/util" @@ -1082,3 +1085,659 @@ func TestWorkFlow(t *testing.T) { assert.NoError(t, err) assert.Equal(t, map[id.ItemID]item.Status{i.ID(): item.StatusPublic}, status) } + +func TestItem_ItemsAsCSV(t *testing.T) { + r := []workspace.Role{workspace.RoleReader, workspace.RoleWriter} + w := accountdomain.NewWorkspaceID() + prj := project.New().NewID().Workspace(w).RequestRoles(r).MustBuild() + + gst := schema.GeometryObjectSupportedTypeList{schema.GeometryObjectSupportedTypePoint, schema.GeometryObjectSupportedTypeLineString} + gest := schema.GeometryEditorSupportedTypeList{schema.GeometryEditorSupportedTypePoint, schema.GeometryEditorSupportedTypeLineString} + + sid1 := id.NewSchemaID() + fid1 := id.NewFieldID() + sf1 := schema.NewField(schema.NewGeometryObject(gst).TypeProperty()).NewID().Name("geo1").Key(id.RandomKey()).ID(fid1).MustBuild() + s1 := schema.New().ID(sid1).Workspace(w).Project(prj.ID()).Fields(schema.FieldList{sf1}).MustBuild() + m1 := model.New().NewID().Schema(s1.ID()).Key(id.RandomKey()).Project(s1.Project()).MustBuild() + fi1 := item.NewField(sf1.ID(), value.TypeGeometryObject.Value("{\"coordinates\":[139.28179282584915,36.58570985749664],\"type\":\"Point\"}").AsMultiple(), nil) + fs1 := []*item.Field{fi1} + i1 := item.New().ID(id.NewItemID()).Schema(s1.ID()).Model(m1.ID()).Project(s1.Project()).Thread(id.NewThreadID()).Fields(fs1).MustBuild() + i1IDStr := i1.ID().String() + + sid2 := id.NewSchemaID() + fid2 := id.NewFieldID() + sf2 := schema.NewField(schema.NewGeometryEditor(gest).TypeProperty()).NewID().Name("geo2").Key(id.RandomKey()).ID(fid2).MustBuild() + s2 := schema.New().ID(sid2).Workspace(accountdomain.NewWorkspaceID()).Project(prj.ID()).Fields(schema.FieldList{sf2}).MustBuild() + m2 := model.New().NewID().Schema(s2.ID()).Key(id.RandomKey()).Project(s2.Project()).MustBuild() + fi2 := item.NewField(sf2.ID(), value.TypeGeometryEditor.Value("{\"coordinates\": [[[138.90306434425662,36.11737907906834],[138.90306434425662,36.33622175736386],[138.67187898370287,36.33622175736386],[138.67187898370287,36.11737907906834],[138.90306434425662,36.11737907906834]]],\"type\": \"Polygon\"}").AsMultiple(), nil) + fs2 := []*item.Field{fi2} + i2 := item.New().NewID().Schema(s2.ID()).Model(m2.ID()).Project(s2.Project()).Thread(id.NewThreadID()).Fields(fs2).MustBuild() + + fid3 := id.NewFieldID() + in4, _ := schema.NewInteger(lo.ToPtr(int64(1)), lo.ToPtr(int64(100))) + tp4 := in4.TypeProperty() + sf3 := schema.NewField(tp4).NewID().Name("age").Key(id.RandomKey()).ID(fid3).MustBuild() + s3 := schema.New().ID(sid2).Workspace(accountdomain.NewWorkspaceID()).Project(prj.ID()).Fields(schema.FieldList{sf3}).MustBuild() + m3 := model.New().NewID().Schema(s3.ID()).Key(id.RandomKey()).Project(s3.Project()).MustBuild() + fs3 := []*item.Field{item.NewField(sf3.ID(), value.TypeReference.Value(nil).AsMultiple(), nil)} + i3 := item.New().NewID().Schema(s3.ID()).Model(m3.ID()).Project(s3.Project()).Thread(id.NewThreadID()).Fields(fs3).MustBuild() + + m4 := id.NewModelID() + + ctx := context.Background() + db := memory.New() + lo.Must0(db.Project.Save(ctx, prj)) + lo.Must0(db.Schema.Save(ctx, s1)) + lo.Must0(db.Model.Save(ctx, m1)) + lo.Must0(db.Item.Save(ctx, i1)) + lo.Must0(db.Schema.Save(ctx, s2)) + lo.Must0(db.Model.Save(ctx, m2)) + lo.Must0(db.Item.Save(ctx, i2)) + lo.Must0(db.Schema.Save(ctx, s3)) + lo.Must0(db.Model.Save(ctx, m3)) + lo.Must0(db.Item.Save(ctx, i3)) + itemUC := NewItem(db, nil) + itemUC.ignoreEvent = true + + page1 := 1 + perPage1 := 10 + + wid := accountdomain.NewWorkspaceID() + u := user.New().NewID().Email("aaa@bbb.com").Workspace(wid).Name("foo").MustBuild() + op := &usecase.Operator{ + AcOperator: &accountusecase.Operator{ + User: lo.ToPtr(u.ID()), + }, + } + + opUserNil := &usecase.Operator{ + AcOperator: &accountusecase.Operator{}, + } + + type args struct { + ctx context.Context + modelID id.ModelID + page *int + perPage *int + op *usecase.Operator + } + tests := []struct { + name string + args args + mockItemErr bool + want []byte + wantError error + }{ + { + name: "success", + args: args{ + ctx: context.Background(), + modelID: m1.ID(), + page: &page1, + perPage: &perPage1, + op: op, + }, + want: []byte("id,location_lat,location_lng\n" + i1IDStr + ",139.28179282584915,36.58570985749664\n"), + wantError: nil, + }, + { + name: "error point type is not supported in any geometry field multiple coordinates", + args: args{ + ctx: context.Background(), + modelID: m2.ID(), + page: &page1, + perPage: &perPage1, + op: op, + }, + want: []byte{}, + wantError: pointFieldIsNotSupportedError, + }, + { + name: "error point type is not supported in any geometry field non geometry field", + args: args{ + ctx: context.Background(), + modelID: m3.ID(), + page: &page1, + perPage: &perPage1, + op: op, + }, + want: []byte{}, + wantError: pointFieldIsNotSupportedError, + }, + { + name: "error model ID not found", + args: args{ + ctx: context.Background(), + modelID: m4, + page: &page1, + perPage: &perPage1, + op: op, + }, + want: []byte{}, + wantError: rerror.ErrNotFound, + }, + { + name: "error operator user is nil", + args: args{ + ctx: context.Background(), + modelID: m4, + page: &page1, + perPage: &perPage1, + op: opUserNil, + }, + want: []byte{}, + wantError: interfaces.ErrInvalidOperator, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + ctx := context.Background() + + pr, err := itemUC.ItemsAsCSV(ctx, tt.args.modelID, tt.args.page, tt.args.perPage, tt.args.op) + result := []byte{} + if pr != nil { + result, _ = io.ReadAll(pr) + } + + assert.Equal(t, tt.want, result) + assert.Equal(t, tt.wantError, err) + }) + } +} + +func TestItem_ItemsAsGeoJSON(t *testing.T) { + r := []workspace.Role{workspace.RoleReader, workspace.RoleWriter} + w := accountdomain.NewWorkspaceID() + prj := project.New().NewID().Workspace(w).RequestRoles(r).MustBuild() + + gst := schema.GeometryObjectSupportedTypeList{schema.GeometryObjectSupportedTypePoint, schema.GeometryObjectSupportedTypeLineString} + gest := schema.GeometryEditorSupportedTypeList{schema.GeometryEditorSupportedTypePoint, schema.GeometryEditorSupportedTypeLineString} + + sid1 := id.NewSchemaID() + fid1 := id.NewFieldID() + sf1 := schema.NewField(schema.NewGeometryObject(gst).TypeProperty()).NewID().Name("geo1").Key(id.RandomKey()).ID(fid1).MustBuild() + s1 := schema.New().ID(sid1).Workspace(w).Project(prj.ID()).Fields(schema.FieldList{sf1}).MustBuild() + m1 := model.New().NewID().Schema(s1.ID()).Key(id.RandomKey()).Project(s1.Project()).MustBuild() + fi1 := item.NewField(sf1.ID(), value.TypeGeometryObject.Value("{\"coordinates\":[139.28179282584915,36.58570985749664],\"type\":\"Point\"}").AsMultiple(), nil) + fs1 := []*item.Field{fi1} + i1 := item.New().ID(id.NewItemID()).Schema(s1.ID()).Model(m1.ID()).Project(s1.Project()).Thread(id.NewThreadID()).Fields(fs1).MustBuild() + + v1 := version.New() + vi1 := version.MustBeValue(v1, nil, version.NewRefs(version.Latest), util.Now(), i1) + // with geometry fields + ver1 := item.VersionedList{vi1} + + fc1, _ := featureCollectionFromItems(ver1, s1) + + sid2 := id.NewSchemaID() + fid2 := id.NewFieldID() + sf2 := schema.NewField(schema.NewGeometryEditor(gest).TypeProperty()).NewID().Name("geo2").Key(id.RandomKey()).ID(fid2).MustBuild() + s2 := schema.New().ID(sid2).Workspace(accountdomain.NewWorkspaceID()).Project(prj.ID()).Fields(schema.FieldList{sf2}).MustBuild() + m2 := model.New().NewID().Schema(s2.ID()).Key(id.RandomKey()).Project(s2.Project()).MustBuild() + fi2 := item.NewField(sf2.ID(), value.TypeGeometryEditor.Value("{\"coordinates\": [[[138.90306434425662,36.11737907906834],[138.90306434425662,36.33622175736386],[138.67187898370287,36.33622175736386],[138.67187898370287,36.11737907906834],[138.90306434425662,36.11737907906834]]],\"type\": \"Polygon\"}").AsMultiple(), nil) + fs2 := []*item.Field{fi2} + i2 := item.New().NewID().Schema(s2.ID()).Model(m2.ID()).Project(s2.Project()).Thread(id.NewThreadID()).Fields(fs2).MustBuild() + + fid3 := id.NewFieldID() + in4, _ := schema.NewInteger(lo.ToPtr(int64(1)), lo.ToPtr(int64(100))) + tp4 := in4.TypeProperty() + sf3 := schema.NewField(tp4).NewID().Name("age").Key(id.RandomKey()).ID(fid3).MustBuild() + s3 := schema.New().ID(sid2).Workspace(accountdomain.NewWorkspaceID()).Project(prj.ID()).Fields(schema.FieldList{sf3}).MustBuild() + m3 := model.New().NewID().Schema(s3.ID()).Key(id.RandomKey()).Project(s3.Project()).MustBuild() + fs3 := []*item.Field{item.NewField(sf3.ID(), value.TypeReference.Value(nil).AsMultiple(), nil)} + i3 := item.New().NewID().Schema(s3.ID()).Model(m3.ID()).Project(s3.Project()).Thread(id.NewThreadID()).Fields(fs3).MustBuild() + + m4 := id.NewModelID() + + ctx := context.Background() + db := memory.New() + lo.Must0(db.Project.Save(ctx, prj)) + lo.Must0(db.Schema.Save(ctx, s1)) + lo.Must0(db.Model.Save(ctx, m1)) + lo.Must0(db.Item.Save(ctx, i1)) + lo.Must0(db.Schema.Save(ctx, s2)) + lo.Must0(db.Model.Save(ctx, m2)) + lo.Must0(db.Item.Save(ctx, i2)) + lo.Must0(db.Schema.Save(ctx, s3)) + lo.Must0(db.Model.Save(ctx, m3)) + lo.Must0(db.Item.Save(ctx, i3)) + itemUC := NewItem(db, nil) + itemUC.ignoreEvent = true + + page1 := 1 + perPage1 := 10 + + wid := accountdomain.NewWorkspaceID() + u := user.New().NewID().Email("aaa@bbb.com").Workspace(wid).Name("foo").MustBuild() + op := &usecase.Operator{ + AcOperator: &accountusecase.Operator{ + User: lo.ToPtr(u.ID()), + }, + } + + opUserNil := &usecase.Operator{ + AcOperator: &accountusecase.Operator{}, + } + + type args struct { + ctx context.Context + modelID id.ModelID + page *int + perPage *int + op *usecase.Operator + } + tests := []struct { + name string + args args + mockItemErr bool + want *integrationapi.FeatureCollection + wantError error + }{ + { + name: "success", + args: args{ + ctx: context.Background(), + modelID: m1.ID(), + page: &page1, + perPage: &perPage1, + op: op, + }, + want: fc1, + wantError: nil, + }, + { + name: "error no geometry field in this model", + args: args{ + ctx: context.Background(), + modelID: m2.ID(), + page: &page1, + perPage: &perPage1, + op: op, + }, + want: nil, + wantError: rerror.NewE(i18n.T("no geometry field in this model")), + }, + { + name: "error no geometry field in this model / integer", + args: args{ + ctx: context.Background(), + modelID: m3.ID(), + page: &page1, + perPage: &perPage1, + op: op, + }, + want: nil, + wantError: rerror.NewE(i18n.T("no geometry field in this model")), + }, + { + name: "error model ID not found", + args: args{ + ctx: context.Background(), + modelID: m4, + page: &page1, + perPage: &perPage1, + op: op, + }, + want: nil, + wantError: rerror.ErrNotFound, + }, + { + name: "error operator user is nil", + args: args{ + ctx: context.Background(), + modelID: m1.ID(), + page: &page1, + perPage: &perPage1, + op: opUserNil, + }, + want: nil, + wantError: interfaces.ErrInvalidOperator, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + ctx := context.Background() + + result, err := itemUC.ItemsAsGeoJSON(ctx, tt.args.modelID, tt.args.page, tt.args.perPage, tt.args.op) + + assert.Equal(t, tt.want, result) + assert.Equal(t, tt.wantError, err) + }) + } +} + +func TestItem_ItemsWithProjectAsCSV(t *testing.T) { + r := []workspace.Role{workspace.RoleReader, workspace.RoleWriter} + w := accountdomain.NewWorkspaceID() + prj := project.New().NewID().Workspace(w).RequestRoles(r).MustBuild() + + gst := schema.GeometryObjectSupportedTypeList{schema.GeometryObjectSupportedTypePoint, schema.GeometryObjectSupportedTypeLineString} + gest := schema.GeometryEditorSupportedTypeList{schema.GeometryEditorSupportedTypePoint, schema.GeometryEditorSupportedTypeLineString} + + sid1 := id.NewSchemaID() + fid1 := id.NewFieldID() + sf1 := schema.NewField(schema.NewGeometryObject(gst).TypeProperty()).NewID().Name("geo1").Key(id.RandomKey()).ID(fid1).MustBuild() + s1 := schema.New().ID(sid1).Workspace(w).Project(prj.ID()).Fields(schema.FieldList{sf1}).MustBuild() + m1 := model.New().NewID().Schema(s1.ID()).Key(id.RandomKey()).Project(s1.Project()).MustBuild() + fi1 := item.NewField(sf1.ID(), value.TypeGeometryObject.Value("{\"coordinates\":[139.28179282584915,36.58570985749664],\"type\":\"Point\"}").AsMultiple(), nil) + fs1 := []*item.Field{fi1} + i1 := item.New().ID(id.NewItemID()).Schema(s1.ID()).Model(m1.ID()).Project(s1.Project()).Thread(id.NewThreadID()).Fields(fs1).MustBuild() + i1IDStr := i1.ID().String() + + sid2 := id.NewSchemaID() + fid2 := id.NewFieldID() + sf2 := schema.NewField(schema.NewGeometryEditor(gest).TypeProperty()).NewID().Name("geo2").Key(id.RandomKey()).ID(fid2).MustBuild() + s2 := schema.New().ID(sid2).Workspace(accountdomain.NewWorkspaceID()).Project(prj.ID()).Fields(schema.FieldList{sf2}).MustBuild() + m2 := model.New().NewID().Schema(s2.ID()).Key(id.RandomKey()).Project(s2.Project()).MustBuild() + fi2 := item.NewField(sf2.ID(), value.TypeGeometryEditor.Value("{\"coordinates\": [[[138.90306434425662,36.11737907906834],[138.90306434425662,36.33622175736386],[138.67187898370287,36.33622175736386],[138.67187898370287,36.11737907906834],[138.90306434425662,36.11737907906834]]],\"type\": \"Polygon\"}").AsMultiple(), nil) + fs2 := []*item.Field{fi2} + i2 := item.New().NewID().Schema(s2.ID()).Model(m2.ID()).Project(s2.Project()).Thread(id.NewThreadID()).Fields(fs2).MustBuild() + + fid3 := id.NewFieldID() + in4, _ := schema.NewInteger(lo.ToPtr(int64(1)), lo.ToPtr(int64(100))) + tp4 := in4.TypeProperty() + sf3 := schema.NewField(tp4).NewID().Name("age").Key(id.RandomKey()).ID(fid3).MustBuild() + s3 := schema.New().ID(sid2).Workspace(accountdomain.NewWorkspaceID()).Project(prj.ID()).Fields(schema.FieldList{sf3}).MustBuild() + m3 := model.New().NewID().Schema(s3.ID()).Key(id.RandomKey()).Project(s3.Project()).MustBuild() + fs3 := []*item.Field{item.NewField(sf3.ID(), value.TypeReference.Value(nil).AsMultiple(), nil)} + i3 := item.New().NewID().Schema(s3.ID()).Model(m3.ID()).Project(s3.Project()).Thread(id.NewThreadID()).Fields(fs3).MustBuild() + + m4 := id.NewModelID() + + ctx := context.Background() + db := memory.New() + lo.Must0(db.Project.Save(ctx, prj)) + lo.Must0(db.Schema.Save(ctx, s1)) + lo.Must0(db.Model.Save(ctx, m1)) + lo.Must0(db.Item.Save(ctx, i1)) + lo.Must0(db.Schema.Save(ctx, s2)) + lo.Must0(db.Model.Save(ctx, m2)) + lo.Must0(db.Item.Save(ctx, i2)) + lo.Must0(db.Schema.Save(ctx, s3)) + lo.Must0(db.Model.Save(ctx, m3)) + lo.Must0(db.Item.Save(ctx, i3)) + itemUC := NewItem(db, nil) + itemUC.ignoreEvent = true + + page1 := 1 + perPage1 := 10 + + wid := accountdomain.NewWorkspaceID() + u := user.New().NewID().Email("aaa@bbb.com").Workspace(wid).Name("foo").MustBuild() + op := &usecase.Operator{ + AcOperator: &accountusecase.Operator{ + User: lo.ToPtr(u.ID()), + }, + } + + opUserNil := &usecase.Operator{ + AcOperator: &accountusecase.Operator{}, + } + + type args struct { + ctx context.Context + projectIDorAlias project.IDOrAlias + modelIDOrKey model.IDOrKey + page *int + perPage *int + op *usecase.Operator + } + tests := []struct { + name string + args args + mockItemErr bool + want []byte + wantError error + }{ + { + name: "success", + args: args{ + ctx: context.Background(), + projectIDorAlias: project.IDOrAlias(prj.ID().String()), + modelIDOrKey: model.IDOrKey(m1.ID().String()), + page: &page1, + perPage: &perPage1, + op: op, + }, + want: []byte("id,location_lat,location_lng\n" + i1IDStr + ",139.28179282584915,36.58570985749664\n"), + wantError: nil, + }, + { + name: "error pointFieldIsNotSupportedError", + args: args{ + ctx: context.Background(), + projectIDorAlias: project.IDOrAlias(prj.ID().String()), + modelIDOrKey: model.IDOrKey(m2.ID().String()), + page: &page1, + perPage: &perPage1, + op: op, + }, + want: []byte{}, + wantError: pointFieldIsNotSupportedError, + }, + { + name: "error pointFieldIsNotSupportedError non-geometry type", + args: args{ + ctx: context.Background(), + projectIDorAlias: project.IDOrAlias(prj.ID().String()), + modelIDOrKey: model.IDOrKey(m3.ID().String()), + page: &page1, + perPage: &perPage1, + op: op, + }, + want: []byte{}, + wantError: pointFieldIsNotSupportedError, + }, + { + name: "error model ID not found", + args: args{ + ctx: context.Background(), + projectIDorAlias: project.IDOrAlias(prj.ID().String()), + modelIDOrKey: model.IDOrKey(m4.String()), + page: &page1, + perPage: &perPage1, + op: op, + }, + want: []byte{}, + wantError: rerror.ErrNotFound, + }, + { + name: "error operator user is nil", + args: args{ + ctx: context.Background(), + projectIDorAlias: project.IDOrAlias(prj.ID().String()), + modelIDOrKey: model.IDOrKey(m1.ID().String()), + page: &page1, + perPage: &perPage1, + op: opUserNil, + }, + want: []byte{}, + wantError: interfaces.ErrInvalidOperator, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + ctx := context.Background() + + pr, err := itemUC.ItemsWithProjectAsCSV(ctx, tt.args.projectIDorAlias, tt.args.modelIDOrKey, tt.args.page, tt.args.perPage, tt.args.op) + result := []byte{} + if pr != nil { + result, _ = io.ReadAll(pr) + } + + assert.Equal(t, tt.want, result) + assert.Equal(t, tt.wantError, err) + }) + } +} + +func TestItem_ItemsWithProjectAsGeoJSON(t *testing.T) { + r := []workspace.Role{workspace.RoleReader, workspace.RoleWriter} + w := accountdomain.NewWorkspaceID() + prj := project.New().NewID().Workspace(w).RequestRoles(r).MustBuild() + + gst := schema.GeometryObjectSupportedTypeList{schema.GeometryObjectSupportedTypePoint, schema.GeometryObjectSupportedTypeLineString} + gest := schema.GeometryEditorSupportedTypeList{schema.GeometryEditorSupportedTypePoint, schema.GeometryEditorSupportedTypeLineString} + + sid1 := id.NewSchemaID() + fid1 := id.NewFieldID() + sf1 := schema.NewField(schema.NewGeometryObject(gst).TypeProperty()).NewID().Name("geo1").Key(id.RandomKey()).ID(fid1).MustBuild() + s1 := schema.New().ID(sid1).Workspace(w).Project(prj.ID()).Fields(schema.FieldList{sf1}).MustBuild() + m1 := model.New().NewID().Schema(s1.ID()).Key(id.RandomKey()).Project(s1.Project()).MustBuild() + fi1 := item.NewField(sf1.ID(), value.TypeGeometryObject.Value("{\"coordinates\":[139.28179282584915,36.58570985749664],\"type\":\"Point\"}").AsMultiple(), nil) + fs1 := []*item.Field{fi1} + i1 := item.New().ID(id.NewItemID()).Schema(s1.ID()).Model(m1.ID()).Project(s1.Project()).Thread(id.NewThreadID()).Fields(fs1).MustBuild() + + v1 := version.New() + vi1 := version.MustBeValue(v1, nil, version.NewRefs(version.Latest), util.Now(), i1) + // with geometry fields + ver1 := item.VersionedList{vi1} + + fc1, _ := featureCollectionFromItems(ver1, s1) + + sid2 := id.NewSchemaID() + fid2 := id.NewFieldID() + sf2 := schema.NewField(schema.NewGeometryEditor(gest).TypeProperty()).NewID().Name("geo2").Key(id.RandomKey()).ID(fid2).MustBuild() + s2 := schema.New().ID(sid2).Workspace(accountdomain.NewWorkspaceID()).Project(prj.ID()).Fields(schema.FieldList{sf2}).MustBuild() + m2 := model.New().NewID().Schema(s2.ID()).Key(id.RandomKey()).Project(s2.Project()).MustBuild() + fi2 := item.NewField(sf2.ID(), value.TypeGeometryEditor.Value("{\"coordinates\": [[[138.90306434425662,36.11737907906834],[138.90306434425662,36.33622175736386],[138.67187898370287,36.33622175736386],[138.67187898370287,36.11737907906834],[138.90306434425662,36.11737907906834]]],\"type\": \"Polygon\"}").AsMultiple(), nil) + fs2 := []*item.Field{fi2} + i2 := item.New().NewID().Schema(s2.ID()).Model(m2.ID()).Project(s2.Project()).Thread(id.NewThreadID()).Fields(fs2).MustBuild() + + fid3 := id.NewFieldID() + in4, _ := schema.NewInteger(lo.ToPtr(int64(1)), lo.ToPtr(int64(100))) + tp4 := in4.TypeProperty() + sf3 := schema.NewField(tp4).NewID().Name("age").Key(id.RandomKey()).ID(fid3).MustBuild() + s3 := schema.New().ID(sid2).Workspace(accountdomain.NewWorkspaceID()).Project(prj.ID()).Fields(schema.FieldList{sf3}).MustBuild() + m3 := model.New().NewID().Schema(s3.ID()).Key(id.RandomKey()).Project(s3.Project()).MustBuild() + fs3 := []*item.Field{item.NewField(sf3.ID(), value.TypeReference.Value(nil).AsMultiple(), nil)} + i3 := item.New().NewID().Schema(s3.ID()).Model(m3.ID()).Project(s3.Project()).Thread(id.NewThreadID()).Fields(fs3).MustBuild() + + m4 := id.NewModelID() + + ctx := context.Background() + db := memory.New() + lo.Must0(db.Project.Save(ctx, prj)) + lo.Must0(db.Schema.Save(ctx, s1)) + lo.Must0(db.Model.Save(ctx, m1)) + lo.Must0(db.Item.Save(ctx, i1)) + lo.Must0(db.Schema.Save(ctx, s2)) + lo.Must0(db.Model.Save(ctx, m2)) + lo.Must0(db.Item.Save(ctx, i2)) + lo.Must0(db.Schema.Save(ctx, s3)) + lo.Must0(db.Model.Save(ctx, m3)) + lo.Must0(db.Item.Save(ctx, i3)) + itemUC := NewItem(db, nil) + itemUC.ignoreEvent = true + + page1 := 1 + perPage1 := 10 + + wid := accountdomain.NewWorkspaceID() + u := user.New().NewID().Email("aaa@bbb.com").Workspace(wid).Name("foo").MustBuild() + op := &usecase.Operator{ + AcOperator: &accountusecase.Operator{ + User: lo.ToPtr(u.ID()), + }, + } + + opUserNil := &usecase.Operator{ + AcOperator: &accountusecase.Operator{}, + } + + type args struct { + ctx context.Context + projectIDorAlias project.IDOrAlias + modelIDOrKey model.IDOrKey + page *int + perPage *int + op *usecase.Operator + } + tests := []struct { + name string + args args + mockItemErr bool + want *integrationapi.FeatureCollection + wantError error + }{ + { + name: "success", + args: args{ + ctx: context.Background(), + projectIDorAlias: project.IDOrAlias(prj.ID().String()), + modelIDOrKey: model.IDOrKey(m1.ID().String()), + page: &page1, + perPage: &perPage1, + op: op, + }, + want: fc1, + wantError: nil, + }, + { + name: "error pointFieldIsNotSupportedError", + args: args{ + ctx: context.Background(), + projectIDorAlias: project.IDOrAlias(prj.ID().String()), + modelIDOrKey: model.IDOrKey(m2.ID().String()), + page: &page1, + perPage: &perPage1, + op: op, + }, + want: nil, + wantError: rerror.NewE(i18n.T("no geometry field in this model")), + }, + { + name: "error pointFieldIsNotSupportedError non-geometry type", + args: args{ + ctx: context.Background(), + projectIDorAlias: project.IDOrAlias(prj.ID().String()), + modelIDOrKey: model.IDOrKey(m3.ID().String()), + page: &page1, + perPage: &perPage1, + op: op, + }, + want: nil, + wantError: rerror.NewE(i18n.T("no geometry field in this model")), + }, + { + name: "error model ID not found", + args: args{ + ctx: context.Background(), + projectIDorAlias: project.IDOrAlias(prj.ID().String()), + modelIDOrKey: model.IDOrKey(m4.String()), + page: &page1, + perPage: &perPage1, + op: op, + }, + want: nil, + wantError: rerror.ErrNotFound, + }, + { + name: "error operator user is nil", + args: args{ + ctx: context.Background(), + projectIDorAlias: project.IDOrAlias(prj.ID().String()), + modelIDOrKey: model.IDOrKey(m1.ID().String()), + page: &page1, + perPage: &perPage1, + op: opUserNil, + }, + want: nil, + wantError: interfaces.ErrInvalidOperator, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + ctx := context.Background() + + result, err := itemUC.ItemsWithProjectAsGeoJSON(ctx, tt.args.projectIDorAlias, tt.args.modelIDOrKey, tt.args.page, tt.args.perPage, tt.args.op) + + assert.Equal(t, tt.want, result) + assert.Equal(t, tt.wantError, err) + }) + } +}