You've already forked focalboard
							
							
				mirror of
				https://github.com/mattermost/focalboard.git
				synced 2025-10-31 00:17:42 +02:00 
			
		
		
		
	* Replace Block references to use pointers throughout all application layers * lint fixes * gofmt file, lint fix Co-authored-by: Mattermod <mattermod@users.noreply.github.com> Co-authored-by: Scott Bishel <scott.bishel@mattermost.com>
		
			
				
	
	
		
			267 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			267 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package app
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"reflect"
 | |
| 	"testing"
 | |
| 
 | |
| 	"github.com/golang/mock/gomock"
 | |
| 	"github.com/mattermost/focalboard/server/model"
 | |
| 	"github.com/mattermost/focalboard/server/utils"
 | |
| 	"github.com/stretchr/testify/assert"
 | |
| 	"github.com/stretchr/testify/require"
 | |
| )
 | |
| 
 | |
| func TestCreateCard(t *testing.T) {
 | |
| 	th, tearDown := SetupTestHelper(t)
 | |
| 	defer tearDown()
 | |
| 
 | |
| 	board := &model.Board{
 | |
| 		ID: utils.NewID(utils.IDTypeBoard),
 | |
| 	}
 | |
| 	userID := utils.NewID(utils.IDTypeUser)
 | |
| 
 | |
| 	props := makeProps(3)
 | |
| 
 | |
| 	card := &model.Card{
 | |
| 		BoardID:      board.ID,
 | |
| 		CreatedBy:    userID,
 | |
| 		ModifiedBy:   userID,
 | |
| 		Title:        "test card",
 | |
| 		ContentOrder: []string{utils.NewID(utils.IDTypeBlock), utils.NewID(utils.IDTypeBlock)},
 | |
| 		Properties:   props,
 | |
| 	}
 | |
| 	block := model.Card2Block(card)
 | |
| 
 | |
| 	t.Run("success scenario", func(t *testing.T) {
 | |
| 		th.Store.EXPECT().GetBoard(board.ID).Return(board, nil)
 | |
| 		th.Store.EXPECT().InsertBlock(gomock.AssignableToTypeOf(reflect.TypeOf(block)), userID).Return(nil)
 | |
| 		th.Store.EXPECT().GetMembersForBoard(board.ID).Return([]*model.BoardMember{}, nil)
 | |
| 
 | |
| 		newCard, err := th.App.CreateCard(card, board.ID, userID, false)
 | |
| 
 | |
| 		require.NoError(t, err)
 | |
| 		require.Equal(t, card.BoardID, newCard.BoardID)
 | |
| 		require.Equal(t, card.Title, newCard.Title)
 | |
| 		require.Equal(t, card.ContentOrder, newCard.ContentOrder)
 | |
| 		require.EqualValues(t, card.Properties, newCard.Properties)
 | |
| 	})
 | |
| 
 | |
| 	t.Run("error scenario", func(t *testing.T) {
 | |
| 		th.Store.EXPECT().GetBoard(board.ID).Return(board, nil)
 | |
| 		th.Store.EXPECT().InsertBlock(gomock.AssignableToTypeOf(reflect.TypeOf(block)), userID).Return(blockError{"error"})
 | |
| 
 | |
| 		newCard, err := th.App.CreateCard(card, board.ID, userID, false)
 | |
| 
 | |
| 		require.Error(t, err, "error")
 | |
| 		require.Nil(t, newCard)
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func TestGetCards(t *testing.T) {
 | |
| 	th, tearDown := SetupTestHelper(t)
 | |
| 	defer tearDown()
 | |
| 
 | |
| 	board := &model.Board{
 | |
| 		ID: utils.NewID(utils.IDTypeBoard),
 | |
| 	}
 | |
| 
 | |
| 	const cardCount = 25
 | |
| 
 | |
| 	// make some cards
 | |
| 	blocks := make([]*model.Block, 0, cardCount)
 | |
| 	for i := 0; i < cardCount; i++ {
 | |
| 		card := &model.Block{
 | |
| 			ID:       utils.NewID(utils.IDTypeBlock),
 | |
| 			ParentID: board.ID,
 | |
| 			Schema:   1,
 | |
| 			Type:     model.TypeCard,
 | |
| 			Title:    fmt.Sprintf("card %d", i),
 | |
| 			BoardID:  board.ID,
 | |
| 		}
 | |
| 		blocks = append(blocks, card)
 | |
| 	}
 | |
| 
 | |
| 	t.Run("success scenario", func(t *testing.T) {
 | |
| 		opts := model.QueryBlocksOptions{
 | |
| 			BoardID:   board.ID,
 | |
| 			BlockType: model.TypeCard,
 | |
| 		}
 | |
| 
 | |
| 		th.Store.EXPECT().GetBlocks(opts).Return(blocks, nil)
 | |
| 
 | |
| 		cards, err := th.App.GetCardsForBoard(board.ID, 0, 0)
 | |
| 		require.NoError(t, err)
 | |
| 		assert.Len(t, cards, cardCount)
 | |
| 	})
 | |
| 
 | |
| 	t.Run("error scenario", func(t *testing.T) {
 | |
| 		opts := model.QueryBlocksOptions{
 | |
| 			BoardID:   board.ID,
 | |
| 			BlockType: model.TypeCard,
 | |
| 		}
 | |
| 
 | |
| 		th.Store.EXPECT().GetBlocks(opts).Return(nil, blockError{"error"})
 | |
| 
 | |
| 		cards, err := th.App.GetCardsForBoard(board.ID, 0, 0)
 | |
| 		require.Error(t, err)
 | |
| 		require.Nil(t, cards)
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func TestPatchCard(t *testing.T) {
 | |
| 	th, tearDown := SetupTestHelper(t)
 | |
| 	defer tearDown()
 | |
| 
 | |
| 	board := &model.Board{
 | |
| 		ID: utils.NewID(utils.IDTypeBoard),
 | |
| 	}
 | |
| 	userID := utils.NewID(utils.IDTypeUser)
 | |
| 
 | |
| 	props := makeProps(3)
 | |
| 
 | |
| 	card := &model.Card{
 | |
| 		BoardID:      board.ID,
 | |
| 		CreatedBy:    userID,
 | |
| 		ModifiedBy:   userID,
 | |
| 		Title:        "test card for patch",
 | |
| 		ContentOrder: []string{utils.NewID(utils.IDTypeBlock), utils.NewID(utils.IDTypeBlock)},
 | |
| 		Properties:   copyProps(props),
 | |
| 	}
 | |
| 
 | |
| 	newTitle := "patched"
 | |
| 	newIcon := "😀"
 | |
| 	newContentOrder := reverse(card.ContentOrder)
 | |
| 
 | |
| 	cardPatch := &model.CardPatch{
 | |
| 		Title:             &newTitle,
 | |
| 		ContentOrder:      &newContentOrder,
 | |
| 		Icon:              &newIcon,
 | |
| 		UpdatedProperties: modifyProps(props),
 | |
| 	}
 | |
| 
 | |
| 	t.Run("success scenario", func(t *testing.T) {
 | |
| 		expectedPatchedCard := cardPatch.Patch(card)
 | |
| 		expectedPatchedBlock := model.Card2Block(expectedPatchedCard)
 | |
| 
 | |
| 		var blockPatch *model.BlockPatch
 | |
| 		th.Store.EXPECT().GetBoard(board.ID).Return(board, nil)
 | |
| 		th.Store.EXPECT().PatchBlock(card.ID, gomock.AssignableToTypeOf(reflect.TypeOf(blockPatch)), userID).Return(nil)
 | |
| 		th.Store.EXPECT().GetMembersForBoard(board.ID).Return([]*model.BoardMember{}, nil)
 | |
| 		th.Store.EXPECT().GetBlock(card.ID).Return(expectedPatchedBlock, nil).AnyTimes()
 | |
| 
 | |
| 		patchedCard, err := th.App.PatchCard(cardPatch, card.ID, userID, false)
 | |
| 
 | |
| 		require.NoError(t, err)
 | |
| 		require.Equal(t, board.ID, patchedCard.BoardID)
 | |
| 		require.Equal(t, newTitle, patchedCard.Title)
 | |
| 		require.Equal(t, newIcon, patchedCard.Icon)
 | |
| 		require.Equal(t, newContentOrder, patchedCard.ContentOrder)
 | |
| 		require.EqualValues(t, expectedPatchedCard.Properties, patchedCard.Properties)
 | |
| 	})
 | |
| 
 | |
| 	t.Run("error scenario", func(t *testing.T) {
 | |
| 		var blockPatch *model.BlockPatch
 | |
| 		th.Store.EXPECT().GetBoard(board.ID).Return(board, nil)
 | |
| 		th.Store.EXPECT().PatchBlock(card.ID, gomock.AssignableToTypeOf(reflect.TypeOf(blockPatch)), userID).Return(blockError{"error"})
 | |
| 
 | |
| 		patchedCard, err := th.App.PatchCard(cardPatch, card.ID, userID, false)
 | |
| 
 | |
| 		require.Error(t, err, "error")
 | |
| 		require.Nil(t, patchedCard)
 | |
| 	})
 | |
| }
 | |
| 
 | |
| func TestGetCard(t *testing.T) {
 | |
| 	th, tearDown := SetupTestHelper(t)
 | |
| 	defer tearDown()
 | |
| 
 | |
| 	boardID := utils.NewID(utils.IDTypeBoard)
 | |
| 	userID := utils.NewID(utils.IDTypeUser)
 | |
| 	props := makeProps(5)
 | |
| 	contentOrder := []string{utils.NewID(utils.IDTypeUser), utils.NewID(utils.IDTypeUser)}
 | |
| 	fields := make(map[string]any)
 | |
| 	fields["contentOrder"] = contentOrder
 | |
| 	fields["properties"] = props
 | |
| 	fields["icon"] = "😀"
 | |
| 	fields["isTemplate"] = true
 | |
| 
 | |
| 	block := &model.Block{
 | |
| 		ID:         utils.NewID(utils.IDTypeBlock),
 | |
| 		ParentID:   boardID,
 | |
| 		Type:       model.TypeCard,
 | |
| 		Title:      "test card",
 | |
| 		BoardID:    boardID,
 | |
| 		Fields:     fields,
 | |
| 		CreatedBy:  userID,
 | |
| 		ModifiedBy: userID,
 | |
| 	}
 | |
| 
 | |
| 	t.Run("success scenario", func(t *testing.T) {
 | |
| 		th.Store.EXPECT().GetBlock(block.ID).Return(block, nil)
 | |
| 
 | |
| 		card, err := th.App.GetCardByID(block.ID)
 | |
| 
 | |
| 		require.NoError(t, err)
 | |
| 		require.Equal(t, boardID, card.BoardID)
 | |
| 		require.Equal(t, block.Title, card.Title)
 | |
| 		require.Equal(t, "😀", card.Icon)
 | |
| 		require.Equal(t, true, card.IsTemplate)
 | |
| 		require.Equal(t, contentOrder, card.ContentOrder)
 | |
| 		require.EqualValues(t, props, card.Properties)
 | |
| 	})
 | |
| 
 | |
| 	t.Run("not found", func(t *testing.T) {
 | |
| 		bogusID := utils.NewID(utils.IDTypeBlock)
 | |
| 		th.Store.EXPECT().GetBlock(bogusID).Return(nil, model.NewErrNotFound(bogusID))
 | |
| 
 | |
| 		card, err := th.App.GetCardByID(bogusID)
 | |
| 
 | |
| 		require.Error(t, err, "error")
 | |
| 		require.True(t, model.IsErrNotFound(err))
 | |
| 		require.Nil(t, card)
 | |
| 	})
 | |
| 
 | |
| 	t.Run("error scenario", func(t *testing.T) {
 | |
| 		th.Store.EXPECT().GetBlock(block.ID).Return(nil, blockError{"error"})
 | |
| 
 | |
| 		card, err := th.App.GetCardByID(block.ID)
 | |
| 
 | |
| 		require.Error(t, err, "error")
 | |
| 		require.Nil(t, card)
 | |
| 	})
 | |
| }
 | |
| 
 | |
| // reverse is a helper function to copy and reverse a slice of strings.
 | |
| func reverse(src []string) []string {
 | |
| 	out := make([]string, 0, len(src))
 | |
| 	for i := len(src) - 1; i >= 0; i-- {
 | |
| 		out = append(out, src[i])
 | |
| 	}
 | |
| 	return out
 | |
| }
 | |
| 
 | |
| func makeProps(count int) map[string]any {
 | |
| 	props := make(map[string]any)
 | |
| 	for i := 0; i < count; i++ {
 | |
| 		props[utils.NewID(utils.IDTypeBlock)] = utils.NewID(utils.IDTypeBlock)
 | |
| 	}
 | |
| 	return props
 | |
| }
 | |
| 
 | |
| func copyProps(m map[string]any) map[string]any {
 | |
| 	out := make(map[string]any)
 | |
| 	for k, v := range m {
 | |
| 		out[k] = v
 | |
| 	}
 | |
| 	return out
 | |
| }
 | |
| 
 | |
| func modifyProps(m map[string]any) map[string]any {
 | |
| 	out := make(map[string]any)
 | |
| 	for k := range m {
 | |
| 		out[k] = utils.NewID(utils.IDTypeBlock)
 | |
| 	}
 | |
| 	return out
 | |
| }
 |