You've already forked focalboard
							
							
				mirror of
				https://github.com/mattermost/focalboard.git
				synced 2025-10-31 00:17:42 +02:00 
			
		
		
		
	* 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>
		
			
				
	
	
		
			192 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			192 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)
 | |
| 			}
 | |
| 		})
 | |
| 	}
 | |
| }
 |