2020-10-21 11:32:13 +02:00
|
|
|
package app
|
|
|
|
|
|
|
|
import (
|
2022-06-15 12:17:44 +02:00
|
|
|
"database/sql"
|
2020-10-21 11:32:13 +02:00
|
|
|
"testing"
|
|
|
|
|
2022-03-22 16:24:34 +02:00
|
|
|
"github.com/golang/mock/gomock"
|
2020-10-21 11:32:13 +02:00
|
|
|
"github.com/stretchr/testify/require"
|
2022-06-15 12:17:44 +02:00
|
|
|
|
2024-06-07 20:00:08 +02:00
|
|
|
mmModel "github.com/mattermost/mattermost/server/public/model"
|
2022-06-15 12:17:44 +02:00
|
|
|
|
|
|
|
"github.com/mattermost/focalboard/server/model"
|
2020-10-21 11:32:13 +02:00
|
|
|
)
|
|
|
|
|
2021-07-09 03:09:02 +02:00
|
|
|
type blockError struct {
|
|
|
|
msg string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (be blockError) Error() string {
|
|
|
|
return be.msg
|
|
|
|
}
|
|
|
|
|
2021-07-08 16:36:43 +02:00
|
|
|
func TestInsertBlock(t *testing.T) {
|
2021-08-25 22:08:01 +02:00
|
|
|
th, tearDown := SetupTestHelper(t)
|
|
|
|
defer tearDown()
|
2021-07-08 16:36:43 +02:00
|
|
|
|
2022-06-29 14:35:24 +02:00
|
|
|
t.Run("success scenario", func(t *testing.T) {
|
2022-03-22 16:24:34 +02:00
|
|
|
boardID := testBoardID
|
2022-10-25 22:46:43 +02:00
|
|
|
block := &model.Block{BoardID: boardID}
|
2022-03-22 16:24:34 +02:00
|
|
|
board := &model.Board{ID: boardID}
|
|
|
|
th.Store.EXPECT().GetBoard(boardID).Return(board, nil)
|
2022-10-25 22:46:43 +02:00
|
|
|
th.Store.EXPECT().InsertBlock(block, "user-id-1").Return(nil)
|
2022-03-22 16:24:34 +02:00
|
|
|
th.Store.EXPECT().GetMembersForBoard(boardID).Return([]*model.BoardMember{}, nil)
|
|
|
|
err := th.App.InsertBlock(block, "user-id-1")
|
2021-07-08 16:36:43 +02:00
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
|
|
|
|
2022-06-29 14:35:24 +02:00
|
|
|
t.Run("error scenario", func(t *testing.T) {
|
2022-03-22 16:24:34 +02:00
|
|
|
boardID := testBoardID
|
2022-10-25 22:46:43 +02:00
|
|
|
block := &model.Block{BoardID: boardID}
|
2022-03-22 16:24:34 +02:00
|
|
|
board := &model.Board{ID: boardID}
|
|
|
|
th.Store.EXPECT().GetBoard(boardID).Return(board, nil)
|
2022-10-25 22:46:43 +02:00
|
|
|
th.Store.EXPECT().InsertBlock(block, "user-id-1").Return(blockError{"error"})
|
2022-03-22 16:24:34 +02:00
|
|
|
err := th.App.InsertBlock(block, "user-id-1")
|
2021-07-09 03:09:02 +02:00
|
|
|
require.Error(t, err, "error")
|
2021-07-08 16:36:43 +02:00
|
|
|
})
|
|
|
|
}
|
2021-12-10 16:17:00 +02:00
|
|
|
|
|
|
|
func TestPatchBlocks(t *testing.T) {
|
|
|
|
th, tearDown := SetupTestHelper(t)
|
|
|
|
defer tearDown()
|
|
|
|
|
2022-06-29 14:35:24 +02:00
|
|
|
t.Run("patchBlocks success scenario", func(t *testing.T) {
|
2022-06-15 12:17:44 +02:00
|
|
|
blockPatches := model.BlockPatchBatch{
|
|
|
|
BlockIDs: []string{"block1"},
|
|
|
|
BlockPatches: []model.BlockPatch{
|
|
|
|
{Title: mmModel.NewString("new title")},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2022-10-25 22:46:43 +02:00
|
|
|
block1 := &model.Block{ID: "block1"}
|
|
|
|
th.Store.EXPECT().GetBlocksByIDs([]string{"block1"}).Return([]*model.Block{block1}, nil)
|
2022-03-22 16:24:34 +02:00
|
|
|
th.Store.EXPECT().PatchBlocks(gomock.Eq(&blockPatches), gomock.Eq("user-id-1")).Return(nil)
|
2022-10-25 22:46:43 +02:00
|
|
|
th.Store.EXPECT().GetBlock("block1").Return(block1, nil)
|
2022-06-15 12:17:44 +02:00
|
|
|
// this call comes from the WS server notification
|
|
|
|
th.Store.EXPECT().GetMembersForBoard(gomock.Any()).Times(1)
|
2022-03-22 16:24:34 +02:00
|
|
|
err := th.App.PatchBlocks("team-id", &blockPatches, "user-id-1")
|
2021-12-10 16:17:00 +02:00
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
|
|
|
|
2022-06-29 14:35:24 +02:00
|
|
|
t.Run("patchBlocks error scenario", func(t *testing.T) {
|
2022-06-15 12:17:44 +02:00
|
|
|
blockPatches := model.BlockPatchBatch{BlockIDs: []string{}}
|
|
|
|
th.Store.EXPECT().GetBlocksByIDs([]string{}).Return(nil, sql.ErrNoRows)
|
2022-03-22 16:24:34 +02:00
|
|
|
err := th.App.PatchBlocks("team-id", &blockPatches, "user-id-1")
|
2022-06-15 12:17:44 +02:00
|
|
|
require.ErrorIs(t, err, sql.ErrNoRows)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("cloud limit error scenario", func(t *testing.T) {
|
2022-12-22 19:40:20 +02:00
|
|
|
t.Skipf("The Cloud Limits feature has been disabled")
|
|
|
|
|
2022-06-15 12:17:44 +02:00
|
|
|
th.App.SetCardLimit(5)
|
|
|
|
|
|
|
|
fakeLicense := &mmModel.License{
|
|
|
|
Features: &mmModel.Features{Cloud: mmModel.NewBool(true)},
|
|
|
|
}
|
|
|
|
|
|
|
|
blockPatches := model.BlockPatchBatch{
|
|
|
|
BlockIDs: []string{"block1"},
|
|
|
|
BlockPatches: []model.BlockPatch{
|
|
|
|
{Title: mmModel.NewString("new title")},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
2022-10-25 22:46:43 +02:00
|
|
|
block1 := &model.Block{
|
2022-06-15 12:17:44 +02:00
|
|
|
ID: "block1",
|
|
|
|
Type: model.TypeCard,
|
|
|
|
ParentID: "board-id",
|
|
|
|
BoardID: "board-id",
|
|
|
|
UpdateAt: 100,
|
|
|
|
}
|
|
|
|
|
|
|
|
board1 := &model.Board{
|
|
|
|
ID: "board-id",
|
|
|
|
Type: model.BoardTypeOpen,
|
|
|
|
}
|
|
|
|
|
2022-10-25 22:46:43 +02:00
|
|
|
th.Store.EXPECT().GetBlocksByIDs([]string{"block1"}).Return([]*model.Block{block1}, nil)
|
2022-06-15 12:17:44 +02:00
|
|
|
th.Store.EXPECT().GetBoard("board-id").Return(board1, nil)
|
|
|
|
th.Store.EXPECT().GetLicense().Return(fakeLicense)
|
|
|
|
th.Store.EXPECT().GetCardLimitTimestamp().Return(int64(150), nil)
|
|
|
|
err := th.App.PatchBlocks("team-id", &blockPatches, "user-id-1")
|
2022-09-13 12:18:40 +02:00
|
|
|
require.ErrorIs(t, err, model.ErrPatchUpdatesLimitedCards)
|
2021-12-10 16:17:00 +02:00
|
|
|
})
|
|
|
|
}
|
2022-02-22 19:42:49 +02:00
|
|
|
|
|
|
|
func TestDeleteBlock(t *testing.T) {
|
|
|
|
th, tearDown := SetupTestHelper(t)
|
|
|
|
defer tearDown()
|
|
|
|
|
2022-06-29 14:35:24 +02:00
|
|
|
t.Run("success scenario", func(t *testing.T) {
|
2022-03-22 16:24:34 +02:00
|
|
|
boardID := testBoardID
|
|
|
|
board := &model.Board{ID: boardID}
|
2022-10-25 22:46:43 +02:00
|
|
|
block := &model.Block{
|
2022-03-22 16:24:34 +02:00
|
|
|
ID: "block-id",
|
|
|
|
BoardID: board.ID,
|
2022-02-22 19:42:49 +02:00
|
|
|
}
|
2022-10-25 22:46:43 +02:00
|
|
|
th.Store.EXPECT().GetBlock(gomock.Eq("block-id")).Return(block, nil)
|
2022-03-22 16:24:34 +02:00
|
|
|
th.Store.EXPECT().DeleteBlock(gomock.Eq("block-id"), gomock.Eq("user-id-1")).Return(nil)
|
|
|
|
th.Store.EXPECT().GetBoard(gomock.Eq(testBoardID)).Return(board, nil)
|
|
|
|
th.Store.EXPECT().GetMembersForBoard(boardID).Return([]*model.BoardMember{}, nil)
|
|
|
|
err := th.App.DeleteBlock("block-id", "user-id-1")
|
2022-02-22 19:42:49 +02:00
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
|
|
|
|
2022-06-29 14:35:24 +02:00
|
|
|
t.Run("error scenario", func(t *testing.T) {
|
2022-03-22 16:24:34 +02:00
|
|
|
boardID := testBoardID
|
|
|
|
board := &model.Board{ID: boardID}
|
2022-10-25 22:46:43 +02:00
|
|
|
block := &model.Block{
|
2022-03-22 16:24:34 +02:00
|
|
|
ID: "block-id",
|
|
|
|
BoardID: board.ID,
|
2022-02-22 19:42:49 +02:00
|
|
|
}
|
2022-10-25 22:46:43 +02:00
|
|
|
th.Store.EXPECT().GetBlock(gomock.Eq("block-id")).Return(block, nil)
|
2022-03-22 16:24:34 +02:00
|
|
|
th.Store.EXPECT().DeleteBlock(gomock.Eq("block-id"), gomock.Eq("user-id-1")).Return(blockError{"error"})
|
|
|
|
th.Store.EXPECT().GetBoard(gomock.Eq(testBoardID)).Return(board, nil)
|
|
|
|
err := th.App.DeleteBlock("block-id", "user-id-1")
|
2022-02-22 19:42:49 +02:00
|
|
|
require.Error(t, err, "error")
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUndeleteBlock(t *testing.T) {
|
|
|
|
th, tearDown := SetupTestHelper(t)
|
|
|
|
defer tearDown()
|
|
|
|
|
2022-06-29 14:35:24 +02:00
|
|
|
t.Run("success scenario", func(t *testing.T) {
|
2022-03-22 16:24:34 +02:00
|
|
|
boardID := testBoardID
|
|
|
|
board := &model.Board{ID: boardID}
|
2022-10-25 22:46:43 +02:00
|
|
|
block := &model.Block{
|
2022-03-22 16:24:34 +02:00
|
|
|
ID: "block-id",
|
|
|
|
BoardID: board.ID,
|
2022-02-22 19:42:49 +02:00
|
|
|
}
|
|
|
|
th.Store.EXPECT().GetBlockHistory(
|
|
|
|
gomock.Eq("block-id"),
|
|
|
|
gomock.Eq(model.QueryBlockHistoryOptions{Limit: 1, Descending: true}),
|
2022-10-25 22:46:43 +02:00
|
|
|
).Return([]*model.Block{block}, nil)
|
2022-03-22 16:24:34 +02:00
|
|
|
th.Store.EXPECT().UndeleteBlock(gomock.Eq("block-id"), gomock.Eq("user-id-1")).Return(nil)
|
2022-10-25 22:46:43 +02:00
|
|
|
th.Store.EXPECT().GetBlock(gomock.Eq("block-id")).Return(block, nil)
|
2022-03-22 16:24:34 +02:00
|
|
|
th.Store.EXPECT().GetBoard(boardID).Return(board, nil)
|
|
|
|
th.Store.EXPECT().GetMembersForBoard(boardID).Return([]*model.BoardMember{}, nil)
|
2022-04-05 17:00:04 +02:00
|
|
|
_, err := th.App.UndeleteBlock("block-id", "user-id-1")
|
2022-02-22 19:42:49 +02:00
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
|
|
|
|
2022-06-29 14:35:24 +02:00
|
|
|
t.Run("error scenario", func(t *testing.T) {
|
2022-10-25 22:46:43 +02:00
|
|
|
block := &model.Block{
|
2022-02-22 19:42:49 +02:00
|
|
|
ID: "block-id",
|
|
|
|
}
|
|
|
|
th.Store.EXPECT().GetBlockHistory(
|
|
|
|
gomock.Eq("block-id"),
|
|
|
|
gomock.Eq(model.QueryBlockHistoryOptions{Limit: 1, Descending: true}),
|
2022-10-25 22:46:43 +02:00
|
|
|
).Return([]*model.Block{block}, nil)
|
2022-03-22 16:24:34 +02:00
|
|
|
th.Store.EXPECT().UndeleteBlock(gomock.Eq("block-id"), gomock.Eq("user-id-1")).Return(blockError{"error"})
|
2022-04-05 17:00:04 +02:00
|
|
|
_, err := th.App.UndeleteBlock("block-id", "user-id-1")
|
2022-02-22 19:42:49 +02:00
|
|
|
require.Error(t, err, "error")
|
|
|
|
})
|
|
|
|
}
|
2022-06-29 14:35:24 +02:00
|
|
|
|
|
|
|
func TestInsertBlocks(t *testing.T) {
|
|
|
|
th, tearDown := SetupTestHelper(t)
|
|
|
|
defer tearDown()
|
|
|
|
|
|
|
|
t.Run("success scenario", func(t *testing.T) {
|
|
|
|
boardID := testBoardID
|
2022-10-25 22:46:43 +02:00
|
|
|
block := &model.Block{BoardID: boardID}
|
2022-06-29 14:35:24 +02:00
|
|
|
board := &model.Board{ID: boardID}
|
|
|
|
th.Store.EXPECT().GetBoard(boardID).Return(board, nil)
|
2022-10-25 22:46:43 +02:00
|
|
|
th.Store.EXPECT().InsertBlock(block, "user-id-1").Return(nil)
|
2022-06-29 14:35:24 +02:00
|
|
|
th.Store.EXPECT().GetMembersForBoard(boardID).Return([]*model.BoardMember{}, nil)
|
2022-10-25 22:46:43 +02:00
|
|
|
_, err := th.App.InsertBlocks([]*model.Block{block}, "user-id-1")
|
2022-06-29 14:35:24 +02:00
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("error scenario", func(t *testing.T) {
|
|
|
|
boardID := testBoardID
|
2022-10-25 22:46:43 +02:00
|
|
|
block := &model.Block{BoardID: boardID}
|
2022-06-29 14:35:24 +02:00
|
|
|
board := &model.Board{ID: boardID}
|
|
|
|
th.Store.EXPECT().GetBoard(boardID).Return(board, nil)
|
2022-10-25 22:46:43 +02:00
|
|
|
th.Store.EXPECT().InsertBlock(block, "user-id-1").Return(blockError{"error"})
|
|
|
|
_, err := th.App.InsertBlocks([]*model.Block{block}, "user-id-1")
|
2022-06-29 14:35:24 +02:00
|
|
|
require.Error(t, err, "error")
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("create view within limits", func(t *testing.T) {
|
2022-12-22 19:40:20 +02:00
|
|
|
t.Skipf("The Cloud Limits feature has been disabled")
|
|
|
|
|
2022-06-29 14:35:24 +02:00
|
|
|
boardID := testBoardID
|
2022-10-25 22:46:43 +02:00
|
|
|
block := &model.Block{
|
2022-06-29 14:35:24 +02:00
|
|
|
Type: model.TypeView,
|
|
|
|
ParentID: "parent_id",
|
|
|
|
BoardID: boardID,
|
|
|
|
}
|
|
|
|
board := &model.Board{ID: boardID}
|
|
|
|
th.Store.EXPECT().GetBoard(boardID).Return(board, nil)
|
2022-10-25 22:46:43 +02:00
|
|
|
th.Store.EXPECT().InsertBlock(block, "user-id-1").Return(nil)
|
2022-06-29 14:35:24 +02:00
|
|
|
th.Store.EXPECT().GetMembersForBoard(boardID).Return([]*model.BoardMember{}, nil)
|
|
|
|
|
|
|
|
// setting up mocks for limits
|
|
|
|
fakeLicense := &mmModel.License{
|
|
|
|
Features: &mmModel.Features{Cloud: mmModel.NewBool(true)},
|
|
|
|
}
|
|
|
|
th.Store.EXPECT().GetLicense().Return(fakeLicense)
|
|
|
|
|
|
|
|
th.Store.EXPECT().GetUsedCardsCount().Return(1, nil)
|
|
|
|
th.Store.EXPECT().GetCardLimitTimestamp().Return(int64(1), nil)
|
2022-10-25 22:46:43 +02:00
|
|
|
th.Store.EXPECT().GetBlocksWithParentAndType("test-board-id", "parent_id", "view").Return([]*model.Block{{}}, nil)
|
2022-06-29 14:35:24 +02:00
|
|
|
|
2022-10-25 22:46:43 +02:00
|
|
|
_, err := th.App.InsertBlocks([]*model.Block{block}, "user-id-1")
|
2022-06-29 14:35:24 +02:00
|
|
|
require.NoError(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("create view exceeding limits", func(t *testing.T) {
|
2022-12-22 19:40:20 +02:00
|
|
|
t.Skipf("The Cloud Limits feature has been disabled")
|
|
|
|
|
2022-06-29 14:35:24 +02:00
|
|
|
boardID := testBoardID
|
2022-10-25 22:46:43 +02:00
|
|
|
block := &model.Block{
|
2022-06-29 14:35:24 +02:00
|
|
|
Type: model.TypeView,
|
|
|
|
ParentID: "parent_id",
|
|
|
|
BoardID: boardID,
|
|
|
|
}
|
|
|
|
board := &model.Board{ID: boardID}
|
|
|
|
th.Store.EXPECT().GetBoard(boardID).Return(board, nil)
|
|
|
|
|
|
|
|
// setting up mocks for limits
|
|
|
|
fakeLicense := &mmModel.License{
|
|
|
|
Features: &mmModel.Features{Cloud: mmModel.NewBool(true)},
|
|
|
|
}
|
|
|
|
th.Store.EXPECT().GetLicense().Return(fakeLicense)
|
|
|
|
|
|
|
|
th.Store.EXPECT().GetUsedCardsCount().Return(1, nil)
|
|
|
|
th.Store.EXPECT().GetCardLimitTimestamp().Return(int64(1), nil)
|
2022-10-25 22:46:43 +02:00
|
|
|
th.Store.EXPECT().GetBlocksWithParentAndType("test-board-id", "parent_id", "view").Return([]*model.Block{{}, {}}, nil)
|
2022-06-29 14:35:24 +02:00
|
|
|
|
2022-10-25 22:46:43 +02:00
|
|
|
_, err := th.App.InsertBlocks([]*model.Block{block}, "user-id-1")
|
2022-06-29 14:35:24 +02:00
|
|
|
require.Error(t, err)
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("creating multiple views, reaching limit in the process", func(t *testing.T) {
|
|
|
|
t.Skipf("Will be fixed soon")
|
|
|
|
|
|
|
|
boardID := testBoardID
|
2022-10-25 22:46:43 +02:00
|
|
|
view1 := &model.Block{
|
2022-06-29 14:35:24 +02:00
|
|
|
Type: model.TypeView,
|
|
|
|
ParentID: "parent_id",
|
|
|
|
BoardID: boardID,
|
|
|
|
}
|
|
|
|
|
2022-10-25 22:46:43 +02:00
|
|
|
view2 := &model.Block{
|
2022-06-29 14:35:24 +02:00
|
|
|
Type: model.TypeView,
|
|
|
|
ParentID: "parent_id",
|
|
|
|
BoardID: boardID,
|
|
|
|
}
|
|
|
|
|
|
|
|
board := &model.Board{ID: boardID}
|
|
|
|
th.Store.EXPECT().GetBoard(boardID).Return(board, nil)
|
2022-10-25 22:46:43 +02:00
|
|
|
th.Store.EXPECT().InsertBlock(view1, "user-id-1").Return(nil).Times(2)
|
2022-06-29 14:35:24 +02:00
|
|
|
th.Store.EXPECT().GetMembersForBoard(boardID).Return([]*model.BoardMember{}, nil).Times(2)
|
|
|
|
|
|
|
|
// setting up mocks for limits
|
|
|
|
fakeLicense := &mmModel.License{
|
|
|
|
Features: &mmModel.Features{Cloud: mmModel.NewBool(true)},
|
|
|
|
}
|
|
|
|
th.Store.EXPECT().GetLicense().Return(fakeLicense).Times(2)
|
|
|
|
|
|
|
|
th.Store.EXPECT().GetUsedCardsCount().Return(1, nil).Times(2)
|
|
|
|
th.Store.EXPECT().GetCardLimitTimestamp().Return(int64(1), nil).Times(2)
|
2022-10-25 22:46:43 +02:00
|
|
|
th.Store.EXPECT().GetBlocksWithParentAndType("test-board-id", "parent_id", "view").Return([]*model.Block{{}}, nil).Times(2)
|
2022-06-29 14:35:24 +02:00
|
|
|
|
2022-10-25 22:46:43 +02:00
|
|
|
_, err := th.App.InsertBlocks([]*model.Block{view1, view2}, "user-id-1")
|
2022-06-29 14:35:24 +02:00
|
|
|
require.Error(t, err)
|
|
|
|
})
|
|
|
|
}
|