focalboard/server/app/content_blocks_test.go
Jesús Espino f915a20c64
Adding the new blocks based editor (#3825)
* Working in the new content block editor

* Moving blocksEditor content block into its own component

* Initial integration with quick development flow

* More WIP

* Adding drag and drop support with server side help

* Some extra work around the styles

* Adding image support

* Adding video and attachments, and fixing edit

* Putting everything behind a feature flag

* Adding support for download attachments

* Fixing compilation error

* Fixing linter errors

* Fixing javascript tests

* Fixing a typescript error

* Moving the move block to an action with undo support

* Fixing ci

* Fixing post merge errors

* Moving to more specific content-blocks api

* Apply suggestions from code review

Co-authored-by: Doug Lauder <wiggin77@warpmail.net>

* Fixing the behavior of certain blocks

* Fixing linter error

* Fixing javascript linter errors

* Adding permission testing for the new move content block api

* Adding some unit tests

* Improving a bit the tests

* Adding more unit tests to the backend

* Fixed PR suggestion

* Adding h1, h2 and h3 tests

* Adding image tests

* Adding video tests

* Adding attachment tests

* Adding quote block tests

* Adding divider tests

* Adding checkbox tests

* Adding list item block tests

* Adding text block tests

* Reorganizing a bit the code to support deveditor eagain

* Fixing dark theme on editor view

* Fixing linter errors

* Fixing tests and removing unneeded data-testid

* Adding root input tests

* Fixing some merge problems

* Fixing text/text.test.tsx test

* Adding more unit tests to the blocks editor

* Fix linter error

* Adding blocksEditor tests

* Fixing linter errors

* Adding tests for blockContent

* Update webapp/src/components/blocksEditor/blockContent.test.tsx

Fix linter warning

* Update webapp/src/components/blocksEditor/blockContent.test.tsx

Fix linter warning

* Update webapp/src/components/blocksEditor/blockContent.test.tsx

Fix linter error

* Fixing test

* Removing unneeded TODO

Co-authored-by: Doug Lauder <wiggin77@warpmail.net>
2022-11-15 16:59:07 +01:00

191 lines
6.8 KiB
Go

package app
import (
"fmt"
"testing"
"github.com/golang/mock/gomock"
"github.com/pkg/errors"
"github.com/stretchr/testify/require"
"github.com/mattermost/focalboard/server/model"
)
type contentOrderMatcher struct {
contentOrder []string
}
func NewContentOrderMatcher(contentOrder []string) contentOrderMatcher {
return contentOrderMatcher{contentOrder}
}
func (com contentOrderMatcher) Matches(x interface{}) bool {
patch, ok := x.(*model.BlockPatch)
if !ok {
return false
}
contentOrderData, ok := patch.UpdatedFields["contentOrder"]
if !ok {
return false
}
contentOrder, ok := contentOrderData.([]interface{})
if !ok {
return false
}
if len(contentOrder) != len(com.contentOrder) {
return false
}
for i := range contentOrder {
if contentOrder[i] != com.contentOrder[i] {
return false
}
}
return true
}
func (com contentOrderMatcher) String() string {
return fmt.Sprint(&model.BlockPatch{UpdatedFields: map[string]interface{}{"contentOrder": com.contentOrder}})
}
func TestMoveContentBlock(t *testing.T) {
th, tearDown := SetupTestHelper(t)
defer tearDown()
ttCases := []struct {
name string
srcBlock model.Block
dstBlock model.Block
parentBlock *model.Block
where string
userID string
mockPatch bool
mockPatchError error
errorMessage string
expectedContentOrder []string
}{
{
name: "not matching parents",
srcBlock: model.Block{ID: "test-1", ParentID: "test-card"},
dstBlock: model.Block{ID: "test-2", ParentID: "other-test-card"},
parentBlock: nil,
where: "after",
userID: "user-id",
errorMessage: "not matching parent test-card and other-test-card",
},
{
name: "parent not found",
srcBlock: model.Block{ID: "test-1", ParentID: "invalid-card"},
dstBlock: model.Block{ID: "test-2", ParentID: "invalid-card"},
parentBlock: &model.Block{ID: "invalid-card"},
where: "after",
userID: "user-id",
errorMessage: "{test} not found",
},
{
name: "valid parent without content order",
srcBlock: model.Block{ID: "test-1", ParentID: "test-card"},
dstBlock: model.Block{ID: "test-2", ParentID: "test-card"},
parentBlock: &model.Block{ID: "test-card"},
where: "after",
userID: "user-id",
errorMessage: "source block test-1 not found",
},
{
name: "valid parent with content order but without test-1 in it",
srcBlock: model.Block{ID: "test-1", ParentID: "test-card"},
dstBlock: model.Block{ID: "test-2", ParentID: "test-card"},
parentBlock: &model.Block{ID: "test-card", Fields: map[string]interface{}{"contentOrder": []interface{}{"test-2"}}},
where: "after",
userID: "user-id",
errorMessage: "source block test-1 not found",
},
{
name: "valid parent with content order but without test-2 in it",
srcBlock: model.Block{ID: "test-1", ParentID: "test-card"},
dstBlock: model.Block{ID: "test-2", ParentID: "test-card"},
parentBlock: &model.Block{ID: "test-card", Fields: map[string]interface{}{"contentOrder": []interface{}{"test-1"}}},
where: "after",
userID: "user-id",
errorMessage: "destination block test-2 not found",
},
{
name: "valid request but fail on patchparent with content order",
srcBlock: model.Block{ID: "test-1", ParentID: "test-card"},
dstBlock: model.Block{ID: "test-2", ParentID: "test-card"},
parentBlock: &model.Block{ID: "test-card", Fields: map[string]interface{}{"contentOrder": []interface{}{"test-1", "test-2"}}},
where: "after",
userID: "user-id",
mockPatch: true,
mockPatchError: errors.New("test error"),
errorMessage: "test error",
},
{
name: "valid request with not real change",
srcBlock: model.Block{ID: "test-2", ParentID: "test-card"},
dstBlock: model.Block{ID: "test-1", ParentID: "test-card"},
parentBlock: &model.Block{ID: "test-card", Fields: map[string]interface{}{"contentOrder": []interface{}{"test-1", "test-2", "test-3"}}, BoardID: "test-board"},
where: "after",
userID: "user-id",
mockPatch: true,
errorMessage: "",
expectedContentOrder: []string{"test-1", "test-2", "test-3"},
},
{
name: "valid request changing order with before",
srcBlock: model.Block{ID: "test-2", ParentID: "test-card"},
dstBlock: model.Block{ID: "test-1", ParentID: "test-card"},
parentBlock: &model.Block{ID: "test-card", Fields: map[string]interface{}{"contentOrder": []interface{}{"test-1", "test-2", "test-3"}}, BoardID: "test-board"},
where: "before",
userID: "user-id",
mockPatch: true,
errorMessage: "",
expectedContentOrder: []string{"test-2", "test-1", "test-3"},
},
{
name: "valid request changing order with after",
srcBlock: model.Block{ID: "test-1", ParentID: "test-card"},
dstBlock: model.Block{ID: "test-2", ParentID: "test-card"},
parentBlock: &model.Block{ID: "test-card", Fields: map[string]interface{}{"contentOrder": []interface{}{"test-1", "test-2", "test-3"}}, BoardID: "test-board"},
where: "after",
userID: "user-id",
mockPatch: true,
errorMessage: "",
expectedContentOrder: []string{"test-2", "test-1", "test-3"},
},
}
for _, tc := range ttCases {
t.Run(tc.name, func(t *testing.T) {
if tc.parentBlock != nil {
if tc.parentBlock.ID == "invalid-card" {
th.Store.EXPECT().GetBlock(tc.srcBlock.ParentID).Return(nil, model.NewErrNotFound("test"))
} else {
th.Store.EXPECT().GetBlock(tc.parentBlock.ID).Return(tc.parentBlock, nil)
if tc.mockPatch {
if tc.mockPatchError != nil {
th.Store.EXPECT().GetBlock(tc.parentBlock.ID).Return(nil, tc.mockPatchError)
} else {
th.Store.EXPECT().GetBlock(tc.parentBlock.ID).Return(tc.parentBlock, nil)
th.Store.EXPECT().PatchBlock(tc.parentBlock.ID, NewContentOrderMatcher(tc.expectedContentOrder), gomock.Eq("user-id")).Return(nil)
th.Store.EXPECT().GetBlock(tc.parentBlock.ID).Return(tc.parentBlock, nil)
th.Store.EXPECT().GetBoard(tc.parentBlock.BoardID).Return(&model.Board{ID: "test-board"}, nil)
// this call comes from the WS server notification
th.Store.EXPECT().GetMembersForBoard(gomock.Any()).Times(1)
}
}
}
}
err := th.App.MoveContentBlock(&tc.srcBlock, &tc.dstBlock, tc.where, tc.userID)
if tc.errorMessage == "" {
require.NoError(t, err)
} else {
require.EqualError(t, err, tc.errorMessage)
}
})
}
}