From f18de08c87fb1226ced833e3bf67d1c2548ae1ab Mon Sep 17 00:00:00 2001
From: Alex Petraky <petraky@perx.ru>
Date: Tue, 19 Mar 2024 10:01:57 +0000
Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?=
 =?UTF-8?q?=D0=BD=D0=B0=20=D0=BE=D0=BF=D1=86=D0=B8=D1=8F=20=D1=81=D0=BE?=
 =?UTF-8?q?=D0=B7=D0=B4=D0=B0=D0=B2=D0=B0=D1=82=D1=8C=20=D0=B7=D0=B0=D0=BF?=
 =?UTF-8?q?=D0=B8=D1=81=D0=B8=20=D0=B2=20=D1=81=D1=82=D0=B0=D1=82=D1=83?=
 =?UTF-8?q?=D1=81=D0=B5=20=D0=B4=D1=80=D0=B0=D1=84=D1=82=20=D0=BF=D1=80?=
 =?UTF-8?q?=D0=B8=20=D1=83=D1=81=D1=82=D0=B0=D0=BD=D0=BE=D0=B2=D0=BA=D0=B5?=
 =?UTF-8?q?=20=D1=87=D0=B5=D1=80=D0=B5=D0=B7=20Setup?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 pkg/setup/item.go      | 43 ++++++++++++++++++---
 pkg/setup/item_test.go | 86 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 123 insertions(+), 6 deletions(-)

diff --git a/pkg/setup/item.go b/pkg/setup/item.go
index d275d0ff..a17512d0 100644
--- a/pkg/setup/item.go
+++ b/pkg/setup/item.go
@@ -18,18 +18,21 @@ var (
 )
 
 type ItemsOption func(c *ItemConfig)
+type PublishItemFn func(s *Setup, item *items.Item) (*items.Item, bool)
 type UpdateItemFn func(s *Setup, exist, new *items.Item) (*items.Item, bool)
 type DeleteItemFn func(s *Setup, col *items.Item) bool
 
 type ItemConfig struct {
-	item     *items.Item
-	UpdateFn UpdateItemFn
-	DeleteFn DeleteItemFn
+	item      *items.Item
+	PublishFn PublishItemFn
+	UpdateFn  UpdateItemFn
+	DeleteFn  DeleteItemFn
 }
 
 func NewItemConfig(item *items.Item, opt ...ItemsOption) ItemConfig {
 	c := ItemConfig{item: item}
 
+	PublishItem()(&c)
 	KeepExistingItem()(&c)
 	DeleteItemIfRemove()(&c)
 
@@ -120,6 +123,18 @@ func DeleteItemIfRemove() ItemsOption {
 	}
 }
 
+func PublishItem() ItemsOption {
+	return func(c *ItemConfig) {
+		c.PublishFn = func(s *Setup, item *items.Item) (*items.Item, bool) { return item, true }
+	}
+}
+
+func KeepDraft() ItemsOption {
+	return func(c *ItemConfig) {
+		c.PublishFn = func(s *Setup, item *items.Item) (*items.Item, bool) { return item, false }
+	}
+}
+
 func (s *Setup) InstallItems(ctx context.Context) error {
 	if len(s.Items) == 0 {
 		return nil
@@ -153,11 +168,27 @@ func (s *Setup) InstallItem(ctx context.Context, exists map[string]*items.Item,
 
 	exist, ok := exists[item.ID]
 	if !ok {
-		return items.CreateAndPublishItem(ctx, s.content.Items, item)
+		if item, publish := c.PublishFn(s, item); publish {
+			return items.CreateAndPublishItem(ctx, s.content.Items, item)
+		}
+		if _, err := s.content.Items.Create(ctx, item); err != nil {
+			return errors.Wrap(err, "create item")
+		}
+		return nil
 	}
 
-	if item, changed := c.UpdateFn(s, exist, c.item); changed {
-		return items.UpdateAndPublishItem(ctx, s.content.Items, item)
+	if item, changed := c.UpdateFn(s, exist, item); changed {
+		if _, publish := c.PublishFn(s, item); publish {
+			return items.UpdateAndPublishItem(ctx, s.content.Items, item)
+		}
+		if err := s.content.Items.Update(ctx, item); err != nil {
+			return errors.Wrap(err, "update item")
+		}
+		if err := s.content.Items.Unpublish(ctx, item); err != nil {
+			return errors.Wrap(err, "unpublish item")
+		}
+		return nil
+
 	}
 
 	return nil
diff --git a/pkg/setup/item_test.go b/pkg/setup/item_test.go
index 920292f5..2d2e1a77 100644
--- a/pkg/setup/item_test.go
+++ b/pkg/setup/item_test.go
@@ -277,3 +277,89 @@ func TestSetup_InstallItems(t *testing.T) {
 		})
 	}
 }
+
+func TestSetup_CreateDraft(t *testing.T) {
+
+	tests := []struct {
+		name      string
+		items     []*items.Item
+		itemsCall func(svc *itemsMock.Items)
+		wantErr   func(t *testing.T, err error)
+	}{
+		{
+			name:  "Install one item",
+			items: []*items.Item{{ID: "1", SpaceID: "sp", EnvID: "env", CollectionID: "coll", Data: map[string]interface{}{"text": "test"}}},
+			itemsCall: func(svc *itemsMock.Items) {
+				svc.On("Find", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, 0, nil).Once()
+				svc.On("Create", mock.Anything, &items.Item{ID: "1", SpaceID: "sp", EnvID: "env", CollectionID: "coll", Data: map[string]interface{}{"text": "test"}}).Return(&items.Item{ID: "1", SpaceID: "sp", EnvID: "env", CollectionID: "coll", Data: map[string]interface{}{"text": "test"}}, nil).Once()
+			},
+			wantErr: func(t *testing.T, err error) {
+				assert.NoError(t, err)
+			},
+		},
+		{
+			name: "Install multiple items success",
+			items: []*items.Item{
+				{ID: "1", SpaceID: "sp", EnvID: "env", CollectionID: "coll", Data: map[string]interface{}{"text": "test"}},
+				{ID: "2", SpaceID: "sp", EnvID: "env", CollectionID: "coll", Data: map[string]interface{}{"text": "test"}},
+			},
+			itemsCall: func(svc *itemsMock.Items) {
+				svc.On("Find", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(nil, 0, nil).Once()
+				svc.On("Create", mock.Anything, &items.Item{ID: "1", SpaceID: "sp", EnvID: "env", CollectionID: "coll", Data: map[string]interface{}{"text": "test"}}).Return(&items.Item{ID: "1", SpaceID: "sp", EnvID: "env", CollectionID: "coll", Data: map[string]interface{}{"text": "test"}}, nil).Once()
+				svc.On("Create", mock.Anything, &items.Item{ID: "2", SpaceID: "sp", EnvID: "env", CollectionID: "coll", Data: map[string]interface{}{"text": "test"}}).Return(&items.Item{ID: "2", SpaceID: "sp", EnvID: "env", CollectionID: "coll", Data: map[string]interface{}{"text": "test"}}, nil).Once()
+			},
+			wantErr: func(t *testing.T, err error) {
+				assert.NoError(t, err)
+			},
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			i := &itemsMock.Items{}
+			if tt.itemsCall != nil {
+				tt.itemsCall(i)
+			}
+
+			s := NewSetup(&content.Content{Items: i}, "sp", "env", nil)
+			s.AddItems(tt.items, KeepDraft())
+			tt.wantErr(t, s.InstallItems(context.Background()))
+		})
+	}
+}
+
+func TestSetup_UpdateDraft(t *testing.T) {
+
+	tests := []struct {
+		name      string
+		items     []*items.Item
+		itemsCall func(svc *itemsMock.Items)
+		wantErr   func(t *testing.T, err error)
+	}{
+		{
+			name:  "Update one item that was published",
+			items: []*items.Item{{ID: "1", SpaceID: "sp", EnvID: "env", CollectionID: "coll", Data: map[string]interface{}{"text": "test"}}},
+			itemsCall: func(svc *itemsMock.Items) {
+				svc.On("Find", mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return([]*items.Item{{ID: "1", SpaceID: "sp", EnvID: "env", CollectionID: "coll", State: items.StatePublished, Data: map[string]interface{}{"text": "test"}}}, 1, nil).Once()
+				svc.On("Update", mock.Anything, &items.Item{ID: "1", SpaceID: "sp", EnvID: "env", CollectionID: "coll", State: items.StatePublished, Data: map[string]interface{}{"text": "test"}}).Return(nil).Once()
+				svc.On("Unpublish", mock.Anything, &items.Item{ID: "1", SpaceID: "sp", EnvID: "env", CollectionID: "coll", State: items.StatePublished, Data: map[string]interface{}{"text": "test"}}).Return(nil).Once()
+			},
+			wantErr: func(t *testing.T, err error) {
+				assert.NoError(t, err)
+			},
+		},
+	}
+
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			i := &itemsMock.Items{}
+			if tt.itemsCall != nil {
+				tt.itemsCall(i)
+			}
+
+			s := NewSetup(&content.Content{Items: i}, "sp", "env", nil)
+			s.AddItems(tt.items, KeepDraft())
+			tt.wantErr(t, s.InstallItems(context.Background()))
+		})
+	}
+}
-- 
GitLab