Doug Lauder
2023-03-22 17:22:27 -04:00
коммит произвёл GitHub
родитель b61c096497
Коммит c943ed6859
13276 изменённых файлов: 1695615 добавлений и 223189 удалений

397
server/boards/integrationtests/blocks_test.go Обычный файл
Просмотреть файл

@@ -0,0 +1,397 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package integrationtests
import (
"testing"
"time"
"github.com/mattermost/mattermost-server/v6/server/boards/model"
"github.com/mattermost/mattermost-server/v6/server/boards/utils"
"github.com/stretchr/testify/require"
)
func TestGetBlocks(t *testing.T) {
th := SetupTestHelperWithToken(t).Start()
defer th.TearDown()
board := th.CreateBoard("team-id", model.BoardTypeOpen)
initialID1 := utils.NewID(utils.IDTypeBlock)
initialID2 := utils.NewID(utils.IDTypeBlock)
newBlocks := []*model.Block{
{
ID: initialID1,
BoardID: board.ID,
CreateAt: 1,
UpdateAt: 1,
Type: model.TypeCard,
},
{
ID: initialID2,
BoardID: board.ID,
CreateAt: 1,
UpdateAt: 1,
Type: model.TypeCard,
},
}
newBlocks, resp := th.Client.InsertBlocks(board.ID, newBlocks, false)
require.NoError(t, resp.Error)
require.Len(t, newBlocks, 2)
blockID1 := newBlocks[0].ID
blockID2 := newBlocks[1].ID
blocks, resp := th.Client.GetBlocksForBoard(board.ID)
require.NoError(t, resp.Error)
require.Len(t, blocks, 2)
blockIDs := make([]string, len(blocks))
for i, b := range blocks {
blockIDs[i] = b.ID
}
require.Contains(t, blockIDs, blockID1)
require.Contains(t, blockIDs, blockID2)
}
func TestPostBlock(t *testing.T) {
th := SetupTestHelperWithToken(t).Start()
defer th.TearDown()
board := th.CreateBoard("team-id", model.BoardTypeOpen)
var blockID1 string
var blockID2 string
var blockID3 string
t.Run("Create a single block", func(t *testing.T) {
initialID1 := utils.NewID(utils.IDTypeBlock)
block := &model.Block{
ID: initialID1,
BoardID: board.ID,
CreateAt: 1,
UpdateAt: 1,
Type: model.TypeCard,
Title: "New title",
}
newBlocks, resp := th.Client.InsertBlocks(board.ID, []*model.Block{block}, false)
require.NoError(t, resp.Error)
require.Len(t, newBlocks, 1)
blockID1 = newBlocks[0].ID
blocks, resp := th.Client.GetBlocksForBoard(board.ID)
require.NoError(t, resp.Error)
require.Len(t, blocks, 1)
blockIDs := make([]string, len(blocks))
for i, b := range blocks {
blockIDs[i] = b.ID
}
require.Contains(t, blockIDs, blockID1)
})
t.Run("Create a couple of blocks in the same call", func(t *testing.T) {
initialID2 := utils.NewID(utils.IDTypeBlock)
initialID3 := utils.NewID(utils.IDTypeBlock)
newBlocks := []*model.Block{
{
ID: initialID2,
BoardID: board.ID,
CreateAt: 1,
UpdateAt: 1,
Type: model.TypeCard,
},
{
ID: initialID3,
BoardID: board.ID,
CreateAt: 1,
UpdateAt: 1,
Type: model.TypeCard,
},
}
newBlocks, resp := th.Client.InsertBlocks(board.ID, newBlocks, false)
require.NoError(t, resp.Error)
require.Len(t, newBlocks, 2)
blockID2 = newBlocks[0].ID
blockID3 = newBlocks[1].ID
require.NotEqual(t, initialID2, blockID2)
require.NotEqual(t, initialID3, blockID3)
blocks, resp := th.Client.GetBlocksForBoard(board.ID)
require.NoError(t, resp.Error)
require.Len(t, blocks, 3)
blockIDs := make([]string, len(blocks))
for i, b := range blocks {
blockIDs[i] = b.ID
}
require.Contains(t, blockIDs, blockID1)
require.Contains(t, blockIDs, blockID2)
require.Contains(t, blockIDs, blockID3)
})
t.Run("Update a block should not be possible through the insert endpoint", func(t *testing.T) {
block := &model.Block{
ID: blockID1,
BoardID: board.ID,
CreateAt: 1,
UpdateAt: 20,
Type: model.TypeCard,
Title: "Updated title",
}
newBlocks, resp := th.Client.InsertBlocks(board.ID, []*model.Block{block}, false)
require.NoError(t, resp.Error)
require.Len(t, newBlocks, 1)
blockID4 := newBlocks[0].ID
require.NotEqual(t, blockID1, blockID4)
blocks, resp := th.Client.GetBlocksForBoard(board.ID)
require.NoError(t, resp.Error)
require.Len(t, blocks, 4)
var block4 *model.Block
for _, b := range blocks {
if b.ID == blockID4 {
block4 = b
}
}
require.NotNil(t, block4)
require.Equal(t, "Updated title", block4.Title)
})
}
func TestPatchBlock(t *testing.T) {
th := SetupTestHelperWithToken(t).Start()
defer th.TearDown()
initialID := utils.NewID(utils.IDTypeBlock)
board := th.CreateBoard("team-id", model.BoardTypeOpen)
time.Sleep(10 * time.Millisecond)
block := &model.Block{
ID: initialID,
BoardID: board.ID,
CreateAt: 1,
UpdateAt: 1,
Type: model.TypeCard,
Title: "New title",
Fields: map[string]interface{}{"test": "test value", "test2": "test value 2"},
}
newBlocks, resp := th.Client.InsertBlocks(board.ID, []*model.Block{block}, false)
th.CheckOK(resp)
require.Len(t, newBlocks, 1)
blockID := newBlocks[0].ID
t.Run("Patch a block basic field", func(t *testing.T) {
newTitle := "Updated title"
blockPatch := &model.BlockPatch{
Title: &newTitle,
}
_, resp := th.Client.PatchBlock(board.ID, blockID, blockPatch, false)
require.NoError(t, resp.Error)
blocks, resp := th.Client.GetBlocksForBoard(board.ID)
require.NoError(t, resp.Error)
require.Len(t, blocks, 1)
var updatedBlock *model.Block
for _, b := range blocks {
if b.ID == blockID {
updatedBlock = b
}
}
require.NotNil(t, updatedBlock)
require.Equal(t, "Updated title", updatedBlock.Title)
})
t.Run("Patch a block custom fields", func(t *testing.T) {
blockPatch := &model.BlockPatch{
UpdatedFields: map[string]interface{}{
"test": "new test value",
"test3": "new field",
},
}
_, resp := th.Client.PatchBlock(board.ID, blockID, blockPatch, false)
require.NoError(t, resp.Error)
blocks, resp := th.Client.GetBlocksForBoard(board.ID)
require.NoError(t, resp.Error)
require.Len(t, blocks, 1)
var updatedBlock *model.Block
for _, b := range blocks {
if b.ID == blockID {
updatedBlock = b
}
}
require.NotNil(t, updatedBlock)
require.Equal(t, "new test value", updatedBlock.Fields["test"])
require.Equal(t, "new field", updatedBlock.Fields["test3"])
})
t.Run("Patch a block to remove custom fields", func(t *testing.T) {
blockPatch := &model.BlockPatch{
DeletedFields: []string{"test", "test3", "test100"},
}
_, resp := th.Client.PatchBlock(board.ID, blockID, blockPatch, false)
require.NoError(t, resp.Error)
blocks, resp := th.Client.GetBlocksForBoard(board.ID)
require.NoError(t, resp.Error)
require.Len(t, blocks, 1)
var updatedBlock *model.Block
for _, b := range blocks {
if b.ID == blockID {
updatedBlock = b
}
}
require.NotNil(t, updatedBlock)
require.Equal(t, nil, updatedBlock.Fields["test"])
require.Equal(t, "test value 2", updatedBlock.Fields["test2"])
require.Equal(t, nil, updatedBlock.Fields["test3"])
})
}
func TestDeleteBlock(t *testing.T) {
th := SetupTestHelperWithToken(t).Start()
defer th.TearDown()
board := th.CreateBoard("team-id", model.BoardTypeOpen)
time.Sleep(10 * time.Millisecond)
var blockID string
t.Run("Create a block", func(t *testing.T) {
initialID := utils.NewID(utils.IDTypeBlock)
block := &model.Block{
ID: initialID,
BoardID: board.ID,
CreateAt: 1,
UpdateAt: 1,
Type: model.TypeCard,
Title: "New title",
}
newBlocks, resp := th.Client.InsertBlocks(board.ID, []*model.Block{block}, false)
require.NoError(t, resp.Error)
require.Len(t, newBlocks, 1)
require.NotZero(t, newBlocks[0].ID)
require.NotEqual(t, initialID, newBlocks[0].ID)
blockID = newBlocks[0].ID
blocks, resp := th.Client.GetBlocksForBoard(board.ID)
require.NoError(t, resp.Error)
require.Len(t, blocks, 1)
blockIDs := make([]string, len(blocks))
for i, b := range blocks {
blockIDs[i] = b.ID
}
require.Contains(t, blockIDs, blockID)
})
t.Run("Delete a block", func(t *testing.T) {
// this avoids triggering uniqueness constraint of
// id,insert_at on block history
time.Sleep(10 * time.Millisecond)
_, resp := th.Client.DeleteBlock(board.ID, blockID, false)
require.NoError(t, resp.Error)
blocks, resp := th.Client.GetBlocksForBoard(board.ID)
require.NoError(t, resp.Error)
require.Empty(t, blocks)
})
}
func TestUndeleteBlock(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
board := th.CreateBoard("team-id", model.BoardTypeOpen)
blocks, resp := th.Client.GetBlocksForBoard(board.ID)
require.NoError(t, resp.Error)
initialCount := len(blocks)
var blockID string
t.Run("Create a block", func(t *testing.T) {
initialID := utils.NewID(utils.IDTypeBoard)
block := &model.Block{
ID: initialID,
BoardID: board.ID,
CreateAt: 1,
UpdateAt: 1,
Type: model.TypeBoard,
Title: "New title",
}
newBlocks, resp := th.Client.InsertBlocks(board.ID, []*model.Block{block}, false)
require.NoError(t, resp.Error)
require.Len(t, newBlocks, 1)
require.NotZero(t, newBlocks[0].ID)
require.NotEqual(t, initialID, newBlocks[0].ID)
blockID = newBlocks[0].ID
blocks, resp := th.Client.GetBlocksForBoard(board.ID)
require.NoError(t, resp.Error)
require.Len(t, blocks, initialCount+1)
blockIDs := make([]string, len(blocks))
for i, b := range blocks {
blockIDs[i] = b.ID
}
require.Contains(t, blockIDs, blockID)
})
t.Run("Delete a block", func(t *testing.T) {
// this avoids triggering uniqueness constraint of
// id,insert_at on block history
time.Sleep(10 * time.Millisecond)
_, resp := th.Client.DeleteBlock(board.ID, blockID, false)
require.NoError(t, resp.Error)
blocks, resp := th.Client.GetBlocksForBoard(board.ID)
require.NoError(t, resp.Error)
require.Len(t, blocks, initialCount)
})
t.Run("Undelete a block", func(t *testing.T) {
// this avoids triggering uniqueness constraint of
// id,insert_at on block history
time.Sleep(10 * time.Millisecond)
_, resp := th.Client.UndeleteBlock(board.ID, blockID)
require.NoError(t, resp.Error)
blocks, resp := th.Client.GetBlocksForBoard(board.ID)
require.NoError(t, resp.Error)
require.Len(t, blocks, initialCount+1)
})
t.Run("Try to undelete a block without permissions", func(t *testing.T) {
// this avoids triggering uniqueness constraint of
// id,insert_at on block history
time.Sleep(10 * time.Millisecond)
_, resp := th.Client.DeleteBlock(board.ID, blockID, false)
require.NoError(t, resp.Error)
_, resp = th.Client2.UndeleteBlock(board.ID, blockID)
th.CheckForbidden(resp)
blocks, resp := th.Client.GetBlocksForBoard(board.ID)
require.NoError(t, resp.Error)
require.Len(t, blocks, initialCount)
})
}

2247
server/boards/integrationtests/board_test.go Обычный файл

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@@ -0,0 +1,825 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package integrationtests
import (
"testing"
"github.com/mattermost/mattermost-server/v6/server/boards/model"
"github.com/stretchr/testify/require"
)
func TestCreateBoardsAndBlocks(t *testing.T) {
teamID := testTeamID
t.Run("a non authenticated user should be rejected", func(t *testing.T) {
th := SetupTestHelper(t).Start()
defer th.TearDown()
newBab := &model.BoardsAndBlocks{
Boards: []*model.Board{},
Blocks: []*model.Block{},
}
bab, resp := th.Client.CreateBoardsAndBlocks(newBab)
th.CheckUnauthorized(resp)
require.Nil(t, bab)
})
t.Run("invalid boards and blocks", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
t.Run("no boards", func(t *testing.T) {
newBab := &model.BoardsAndBlocks{
Boards: []*model.Board{},
Blocks: []*model.Block{
{ID: "block-id", BoardID: "board-id", Type: model.TypeCard},
},
}
bab, resp := th.Client.CreateBoardsAndBlocks(newBab)
th.CheckBadRequest(resp)
require.Nil(t, bab)
})
t.Run("no blocks", func(t *testing.T) {
newBab := &model.BoardsAndBlocks{
Boards: []*model.Board{
{ID: "board-id", TeamID: teamID, Type: model.BoardTypePrivate},
},
Blocks: []*model.Block{},
}
bab, resp := th.Client.CreateBoardsAndBlocks(newBab)
th.CheckBadRequest(resp)
require.Nil(t, bab)
})
t.Run("blocks from nonexistent boards", func(t *testing.T) {
newBab := &model.BoardsAndBlocks{
Boards: []*model.Board{
{ID: "board-id", TeamID: teamID, Type: model.BoardTypePrivate},
},
Blocks: []*model.Block{
{ID: "block-id", BoardID: "nonexistent-board-id", Type: model.TypeCard, CreateAt: 1, UpdateAt: 1},
},
}
bab, resp := th.Client.CreateBoardsAndBlocks(newBab)
th.CheckBadRequest(resp)
require.Nil(t, bab)
})
t.Run("boards with no IDs", func(t *testing.T) {
newBab := &model.BoardsAndBlocks{
Boards: []*model.Board{
{ID: "board-id", TeamID: teamID, Type: model.BoardTypePrivate},
{TeamID: teamID, Type: model.BoardTypePrivate},
},
Blocks: []*model.Block{
{ID: "block-id", BoardID: "board-id", Type: model.TypeCard, CreateAt: 1, UpdateAt: 1},
},
}
bab, resp := th.Client.CreateBoardsAndBlocks(newBab)
th.CheckBadRequest(resp)
require.Nil(t, bab)
})
t.Run("boards from different teams", func(t *testing.T) {
newBab := &model.BoardsAndBlocks{
Boards: []*model.Board{
{ID: "board-id-1", TeamID: "team-id-1", Type: model.BoardTypePrivate},
{ID: "board-id-2", TeamID: "team-id-2", Type: model.BoardTypePrivate},
},
Blocks: []*model.Block{
{ID: "block-id", BoardID: "board-id-1", Type: model.TypeCard, CreateAt: 1, UpdateAt: 1},
},
}
bab, resp := th.Client.CreateBoardsAndBlocks(newBab)
th.CheckBadRequest(resp)
require.Nil(t, bab)
})
t.Run("creating boards and blocks", func(t *testing.T) {
newBab := &model.BoardsAndBlocks{
Boards: []*model.Board{
{ID: "board-id-1", Title: "public board", TeamID: teamID, Type: model.BoardTypeOpen},
{ID: "board-id-2", Title: "private board", TeamID: teamID, Type: model.BoardTypePrivate},
},
Blocks: []*model.Block{
{ID: "block-id-1", Title: "block 1", BoardID: "board-id-1", Type: model.TypeCard, CreateAt: 1, UpdateAt: 1},
{ID: "block-id-2", Title: "block 2", BoardID: "board-id-2", Type: model.TypeCard, CreateAt: 1, UpdateAt: 1},
},
}
bab, resp := th.Client.CreateBoardsAndBlocks(newBab)
th.CheckOK(resp)
require.NotNil(t, bab)
require.Len(t, bab.Boards, 2)
require.Len(t, bab.Blocks, 2)
// board 1 should have been created with a new ID, and its
// block should be there too
boardsTermPublic, resp := th.Client.SearchBoardsForTeam(teamID, "public")
th.CheckOK(resp)
require.Len(t, boardsTermPublic, 1)
board1 := boardsTermPublic[0]
require.Equal(t, "public board", board1.Title)
require.Equal(t, model.BoardTypeOpen, board1.Type)
require.NotEqual(t, "board-id-1", board1.ID)
blocks1, err := th.Server.App().GetBlocksForBoard(board1.ID)
require.NoError(t, err)
require.Len(t, blocks1, 1)
require.Equal(t, "block 1", blocks1[0].Title)
// board 1 should have been created with a new ID, and its
// block should be there too
boardsTermPrivate, resp := th.Client.SearchBoardsForTeam(teamID, "private")
th.CheckOK(resp)
require.Len(t, boardsTermPrivate, 1)
board2 := boardsTermPrivate[0]
require.Equal(t, "private board", board2.Title)
require.Equal(t, model.BoardTypePrivate, board2.Type)
require.NotEqual(t, "board-id-2", board2.ID)
blocks2, err := th.Server.App().GetBlocksForBoard(board2.ID)
require.NoError(t, err)
require.Len(t, blocks2, 1)
require.Equal(t, "block 2", blocks2[0].Title)
// user should be an admin of both newly created boards
user1 := th.GetUser1()
members1, err := th.Server.App().GetMembersForBoard(board1.ID)
require.NoError(t, err)
require.Len(t, members1, 1)
require.Equal(t, user1.ID, members1[0].UserID)
members2, err := th.Server.App().GetMembersForBoard(board2.ID)
require.NoError(t, err)
require.Len(t, members2, 1)
require.Equal(t, user1.ID, members2[0].UserID)
})
})
}
func TestPatchBoardsAndBlocks(t *testing.T) {
teamID := "team-id"
t.Run("a non authenticated user should be rejected", func(t *testing.T) {
th := SetupTestHelper(t).Start()
defer th.TearDown()
pbab := &model.PatchBoardsAndBlocks{}
bab, resp := th.Client.PatchBoardsAndBlocks(pbab)
th.CheckUnauthorized(resp)
require.Nil(t, bab)
})
t.Run("invalid patch boards and blocks", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
userID := th.GetUser1().ID
initialTitle := "initial title 1"
newTitle := "new title 1"
newBoard1 := &model.Board{
Title: initialTitle,
TeamID: teamID,
Type: model.BoardTypeOpen,
}
board1, err := th.Server.App().CreateBoard(newBoard1, userID, true)
require.NoError(t, err)
require.NotNil(t, board1)
newBoard2 := &model.Board{
Title: initialTitle,
TeamID: teamID,
Type: model.BoardTypeOpen,
}
board2, err := th.Server.App().CreateBoard(newBoard2, userID, true)
require.NoError(t, err)
require.NotNil(t, board2)
newBlock1 := &model.Block{
ID: "block-id-1",
BoardID: board1.ID,
Title: initialTitle,
}
require.NoError(t, th.Server.App().InsertBlock(newBlock1, userID))
block1, err := th.Server.App().GetBlockByID("block-id-1")
require.NoError(t, err)
require.NotNil(t, block1)
newBlock2 := &model.Block{
ID: "block-id-2",
BoardID: board2.ID,
Title: initialTitle,
}
require.NoError(t, th.Server.App().InsertBlock(newBlock2, userID))
block2, err := th.Server.App().GetBlockByID("block-id-2")
require.NoError(t, err)
require.NotNil(t, block2)
t.Run("no board IDs", func(t *testing.T) {
pbab := &model.PatchBoardsAndBlocks{
BoardIDs: []string{},
BoardPatches: []*model.BoardPatch{
{Title: &newTitle},
{Title: &newTitle},
},
BlockIDs: []string{block1.ID, block2.ID},
BlockPatches: []*model.BlockPatch{
{Title: &newTitle},
{Title: &newTitle},
},
}
bab, resp := th.Client.PatchBoardsAndBlocks(pbab)
th.CheckBadRequest(resp)
require.Nil(t, bab)
})
t.Run("missmatch board IDs and patches", func(t *testing.T) {
pbab := &model.PatchBoardsAndBlocks{
BoardIDs: []string{board1.ID, board2.ID},
BoardPatches: []*model.BoardPatch{
{Title: &newTitle},
},
BlockIDs: []string{block1.ID, block2.ID},
BlockPatches: []*model.BlockPatch{
{Title: &newTitle},
{Title: &newTitle},
},
}
bab, resp := th.Client.PatchBoardsAndBlocks(pbab)
th.CheckBadRequest(resp)
require.Nil(t, bab)
})
t.Run("no block IDs", func(t *testing.T) {
pbab := &model.PatchBoardsAndBlocks{
BoardIDs: []string{board1.ID, board2.ID},
BoardPatches: []*model.BoardPatch{
{Title: &newTitle},
{Title: &newTitle},
},
BlockIDs: []string{},
BlockPatches: []*model.BlockPatch{
{Title: &newTitle},
{Title: &newTitle},
},
}
bab, resp := th.Client.PatchBoardsAndBlocks(pbab)
th.CheckBadRequest(resp)
require.Nil(t, bab)
})
t.Run("missmatch block IDs and patches", func(t *testing.T) {
pbab := &model.PatchBoardsAndBlocks{
BoardIDs: []string{board1.ID, board2.ID},
BoardPatches: []*model.BoardPatch{
{Title: &newTitle},
{Title: &newTitle},
},
BlockIDs: []string{block1.ID, block2.ID},
BlockPatches: []*model.BlockPatch{
{Title: &newTitle},
},
}
bab, resp := th.Client.PatchBoardsAndBlocks(pbab)
th.CheckBadRequest(resp)
require.Nil(t, bab)
})
t.Run("block that doesn't belong to any board", func(t *testing.T) {
pbab := &model.PatchBoardsAndBlocks{
BoardIDs: []string{board1.ID},
BoardPatches: []*model.BoardPatch{
{Title: &newTitle},
},
BlockIDs: []string{block1.ID, block2.ID},
BlockPatches: []*model.BlockPatch{
{Title: &newTitle},
{Title: &newTitle},
},
}
bab, resp := th.Client.PatchBoardsAndBlocks(pbab)
th.CheckBadRequest(resp)
require.Nil(t, bab)
})
})
t.Run("if the user doesn't have permissions for one of the boards, nothing should be updated", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
userID := th.GetUser1().ID
initialTitle := "initial title 2"
newTitle := "new title 2"
newBoard1 := &model.Board{
Title: initialTitle,
TeamID: teamID,
Type: model.BoardTypeOpen,
}
board1, err := th.Server.App().CreateBoard(newBoard1, userID, true)
require.NoError(t, err)
require.NotNil(t, board1)
newBoard2 := &model.Board{
Title: initialTitle,
TeamID: teamID,
Type: model.BoardTypeOpen,
}
board2, err := th.Server.App().CreateBoard(newBoard2, userID, false)
require.NoError(t, err)
require.NotNil(t, board2)
newBlock1 := &model.Block{
ID: "block-id-1",
BoardID: board1.ID,
Title: initialTitle,
}
require.NoError(t, th.Server.App().InsertBlock(newBlock1, userID))
block1, err := th.Server.App().GetBlockByID("block-id-1")
require.NoError(t, err)
require.NotNil(t, block1)
newBlock2 := &model.Block{
ID: "block-id-2",
BoardID: board2.ID,
Title: initialTitle,
}
require.NoError(t, th.Server.App().InsertBlock(newBlock2, userID))
block2, err := th.Server.App().GetBlockByID("block-id-2")
require.NoError(t, err)
require.NotNil(t, block2)
pbab := &model.PatchBoardsAndBlocks{
BoardIDs: []string{board1.ID, board2.ID},
BoardPatches: []*model.BoardPatch{
{Title: &newTitle},
{Title: &newTitle},
},
BlockIDs: []string{block1.ID, block2.ID},
BlockPatches: []*model.BlockPatch{
{Title: &newTitle},
{Title: &newTitle},
},
}
bab, resp := th.Client.PatchBoardsAndBlocks(pbab)
th.CheckForbidden(resp)
require.Nil(t, bab)
})
t.Run("boards belonging to different teams should be rejected", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
userID := th.GetUser1().ID
initialTitle := "initial title 3"
newTitle := "new title 3"
newBoard1 := &model.Board{
Title: initialTitle,
TeamID: teamID,
Type: model.BoardTypeOpen,
}
board1, err := th.Server.App().CreateBoard(newBoard1, userID, true)
require.NoError(t, err)
require.NotNil(t, board1)
newBoard2 := &model.Board{
Title: initialTitle,
TeamID: "different-team-id",
Type: model.BoardTypeOpen,
}
board2, err := th.Server.App().CreateBoard(newBoard2, userID, true)
require.NoError(t, err)
require.NotNil(t, board2)
newBlock1 := &model.Block{
ID: "block-id-1",
BoardID: board1.ID,
Title: initialTitle,
}
require.NoError(t, th.Server.App().InsertBlock(newBlock1, userID))
block1, err := th.Server.App().GetBlockByID("block-id-1")
require.NoError(t, err)
require.NotNil(t, block1)
newBlock2 := &model.Block{
ID: "block-id-2",
BoardID: board2.ID,
Title: initialTitle,
}
require.NoError(t, th.Server.App().InsertBlock(newBlock2, userID))
block2, err := th.Server.App().GetBlockByID("block-id-2")
require.NoError(t, err)
require.NotNil(t, block2)
pbab := &model.PatchBoardsAndBlocks{
BoardIDs: []string{board1.ID, board2.ID},
BoardPatches: []*model.BoardPatch{
{Title: &newTitle},
{Title: &newTitle},
},
BlockIDs: []string{block1.ID, "board-id-2"},
BlockPatches: []*model.BlockPatch{
{Title: &newTitle},
{Title: &newTitle},
},
}
bab, resp := th.Client.PatchBoardsAndBlocks(pbab)
th.CheckBadRequest(resp)
require.Nil(t, bab)
})
t.Run("patches should be rejected if one is invalid", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
userID := th.GetUser1().ID
initialTitle := "initial title 4"
newTitle := "new title 4"
newBoard1 := &model.Board{
Title: initialTitle,
TeamID: teamID,
Type: model.BoardTypeOpen,
}
board1, err := th.Server.App().CreateBoard(newBoard1, userID, true)
require.NoError(t, err)
require.NotNil(t, board1)
newBoard2 := &model.Board{
Title: initialTitle,
TeamID: teamID,
Type: model.BoardTypeOpen,
}
board2, err := th.Server.App().CreateBoard(newBoard2, userID, false)
require.NoError(t, err)
require.NotNil(t, board2)
newBlock1 := &model.Block{
ID: "block-id-1",
BoardID: board1.ID,
Title: initialTitle,
}
require.NoError(t, th.Server.App().InsertBlock(newBlock1, userID))
block1, err := th.Server.App().GetBlockByID("block-id-1")
require.NoError(t, err)
require.NotNil(t, block1)
newBlock2 := &model.Block{
ID: "block-id-2",
BoardID: board2.ID,
Title: initialTitle,
}
require.NoError(t, th.Server.App().InsertBlock(newBlock2, userID))
block2, err := th.Server.App().GetBlockByID("block-id-2")
require.NoError(t, err)
require.NotNil(t, block2)
var invalidPatchType model.BoardType = "invalid"
invalidPatch := &model.BoardPatch{Type: &invalidPatchType}
pbab := &model.PatchBoardsAndBlocks{
BoardIDs: []string{board1.ID, board2.ID},
BoardPatches: []*model.BoardPatch{
{Title: &newTitle},
invalidPatch,
},
BlockIDs: []string{block1.ID, "board-id-2"},
BlockPatches: []*model.BlockPatch{
{Title: &newTitle},
{Title: &newTitle},
},
}
bab, resp := th.Client.PatchBoardsAndBlocks(pbab)
th.CheckBadRequest(resp)
require.Nil(t, bab)
})
t.Run("patches should be rejected if there is a block that doesn't belong to the boards being patched", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
userID := th.GetUser1().ID
initialTitle := "initial title"
newTitle := "new patched title"
newBoard1 := &model.Board{
Title: initialTitle,
TeamID: teamID,
Type: model.BoardTypeOpen,
}
board1, err := th.Server.App().CreateBoard(newBoard1, userID, true)
require.NoError(t, err)
require.NotNil(t, board1)
newBoard2 := &model.Board{
Title: initialTitle,
TeamID: teamID,
Type: model.BoardTypeOpen,
}
board2, err := th.Server.App().CreateBoard(newBoard2, userID, true)
require.NoError(t, err)
require.NotNil(t, board2)
newBlock1 := &model.Block{
ID: "block-id-1",
BoardID: board1.ID,
Title: initialTitle,
}
require.NoError(t, th.Server.App().InsertBlock(newBlock1, userID))
block1, err := th.Server.App().GetBlockByID("block-id-1")
require.NoError(t, err)
require.NotNil(t, block1)
newBlock2 := &model.Block{
ID: "block-id-2",
BoardID: board2.ID,
Title: initialTitle,
}
require.NoError(t, th.Server.App().InsertBlock(newBlock2, userID))
block2, err := th.Server.App().GetBlockByID("block-id-2")
require.NoError(t, err)
require.NotNil(t, block2)
pbab := &model.PatchBoardsAndBlocks{
BoardIDs: []string{board1.ID},
BoardPatches: []*model.BoardPatch{
{Title: &newTitle},
},
BlockIDs: []string{block1.ID, block2.ID},
BlockPatches: []*model.BlockPatch{
{Title: &newTitle},
{Title: &newTitle},
},
}
bab, resp := th.Client.PatchBoardsAndBlocks(pbab)
th.CheckBadRequest(resp)
require.Nil(t, bab)
})
t.Run("patches should be applied if they're valid and they're related", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
userID := th.GetUser1().ID
initialTitle := "initial title"
newTitle := "new other title"
newBoard1 := &model.Board{
Title: initialTitle,
TeamID: teamID,
Type: model.BoardTypeOpen,
}
board1, err := th.Server.App().CreateBoard(newBoard1, userID, true)
require.NoError(t, err)
require.NotNil(t, board1)
newBoard2 := &model.Board{
Title: initialTitle,
TeamID: teamID,
Type: model.BoardTypeOpen,
}
board2, err := th.Server.App().CreateBoard(newBoard2, userID, true)
require.NoError(t, err)
require.NotNil(t, board2)
newBlock1 := &model.Block{
ID: "block-id-1",
BoardID: board1.ID,
Title: initialTitle,
}
require.NoError(t, th.Server.App().InsertBlock(newBlock1, userID))
block1, err := th.Server.App().GetBlockByID("block-id-1")
require.NoError(t, err)
require.NotNil(t, block1)
newBlock2 := &model.Block{
ID: "block-id-2",
BoardID: board2.ID,
Title: initialTitle,
}
require.NoError(t, th.Server.App().InsertBlock(newBlock2, userID))
block2, err := th.Server.App().GetBlockByID("block-id-2")
require.NoError(t, err)
require.NotNil(t, block2)
pbab := &model.PatchBoardsAndBlocks{
BoardIDs: []string{board1.ID, board2.ID},
BoardPatches: []*model.BoardPatch{
{Title: &newTitle},
{Title: &newTitle},
},
BlockIDs: []string{block1.ID, block2.ID},
BlockPatches: []*model.BlockPatch{
{Title: &newTitle},
{Title: &newTitle},
},
}
bab, resp := th.Client.PatchBoardsAndBlocks(pbab)
th.CheckOK(resp)
require.NotNil(t, bab)
require.Len(t, bab.Boards, 2)
require.Len(t, bab.Blocks, 2)
// ensure that the entities have been updated
rBoard1, err := th.Server.App().GetBoard(board1.ID)
require.NoError(t, err)
require.Equal(t, newTitle, rBoard1.Title)
rBlock1, err := th.Server.App().GetBlockByID(block1.ID)
require.NoError(t, err)
require.Equal(t, newTitle, rBlock1.Title)
rBoard2, err := th.Server.App().GetBoard(board2.ID)
require.NoError(t, err)
require.Equal(t, newTitle, rBoard2.Title)
rBlock2, err := th.Server.App().GetBlockByID(block2.ID)
require.NoError(t, err)
require.Equal(t, newTitle, rBlock2.Title)
})
}
func TestDeleteBoardsAndBlocks(t *testing.T) {
teamID := "team-id"
t.Run("a non authenticated user should be rejected", func(t *testing.T) {
th := SetupTestHelper(t).Start()
defer th.TearDown()
dbab := &model.DeleteBoardsAndBlocks{}
success, resp := th.Client.DeleteBoardsAndBlocks(dbab)
th.CheckUnauthorized(resp)
require.False(t, success)
})
t.Run("invalid delete boards and blocks", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
// a board and a block are required for the permission checks
newBoard := &model.Board{
TeamID: teamID,
Type: model.BoardTypeOpen,
}
board, err := th.Server.App().CreateBoard(newBoard, th.GetUser1().ID, true)
require.NoError(t, err)
require.NotNil(t, board)
newBlock := &model.Block{
ID: "block-id-1",
BoardID: board.ID,
Title: "title",
}
require.NoError(t, th.Server.App().InsertBlock(newBlock, th.GetUser1().ID))
block, err := th.Server.App().GetBlockByID(newBlock.ID)
require.NoError(t, err)
require.NotNil(t, block)
t.Run("no boards", func(t *testing.T) {
dbab := &model.DeleteBoardsAndBlocks{
Blocks: []string{block.ID},
}
success, resp := th.Client.DeleteBoardsAndBlocks(dbab)
th.CheckBadRequest(resp)
require.False(t, success)
})
t.Run("boards from different teams", func(t *testing.T) {
newOtherTeamsBoard := &model.Board{
TeamID: "another-team-id",
Type: model.BoardTypeOpen,
}
otherTeamsBoard, err := th.Server.App().CreateBoard(newOtherTeamsBoard, th.GetUser1().ID, true)
require.NoError(t, err)
require.NotNil(t, board)
dbab := &model.DeleteBoardsAndBlocks{
Boards: []string{board.ID, otherTeamsBoard.ID},
Blocks: []string{"block-id-1"},
}
success, resp := th.Client.DeleteBoardsAndBlocks(dbab)
th.CheckBadRequest(resp)
require.False(t, success)
})
})
t.Run("if the user has no permissions to one of the boards, nothing should be deleted", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
// the user is an admin of the first board
newBoard1 := &model.Board{
Type: model.BoardTypeOpen,
TeamID: "team_id_1",
}
board1, err := th.Server.App().CreateBoard(newBoard1, th.GetUser1().ID, true)
require.NoError(t, err)
require.NotNil(t, board1)
// but not of the second
newBoard2 := &model.Board{
Type: model.BoardTypeOpen,
TeamID: "team_id_1",
}
board2, err := th.Server.App().CreateBoard(newBoard2, th.GetUser1().ID, false)
require.NoError(t, err)
require.NotNil(t, board2)
dbab := &model.DeleteBoardsAndBlocks{
Boards: []string{board1.ID, board2.ID},
Blocks: []string{"block-id-1"},
}
success, resp := th.Client.DeleteBoardsAndBlocks(dbab)
th.CheckForbidden(resp)
require.False(t, success)
})
t.Run("all boards and blocks should be deleted if the request is correct", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
newBab := &model.BoardsAndBlocks{
Boards: []*model.Board{
{ID: "board-id-1", Title: "public board", TeamID: teamID, Type: model.BoardTypeOpen},
{ID: "board-id-2", Title: "private board", TeamID: teamID, Type: model.BoardTypePrivate},
},
Blocks: []*model.Block{
{ID: "block-id-1", Title: "block 1", BoardID: "board-id-1", Type: model.TypeCard, CreateAt: 1, UpdateAt: 1},
{ID: "block-id-2", Title: "block 2", BoardID: "board-id-2", Type: model.TypeCard, CreateAt: 1, UpdateAt: 1},
},
}
bab, err := th.Server.App().CreateBoardsAndBlocks(newBab, th.GetUser1().ID, true)
require.NoError(t, err)
require.Len(t, bab.Boards, 2)
require.Len(t, bab.Blocks, 2)
// ensure that the entities have been successfully created
board1, err := th.Server.App().GetBoard("board-id-1")
require.NoError(t, err)
require.NotNil(t, board1)
block1, err := th.Server.App().GetBlockByID("block-id-1")
require.NoError(t, err)
require.NotNil(t, block1)
board2, err := th.Server.App().GetBoard("board-id-2")
require.NoError(t, err)
require.NotNil(t, board2)
block2, err := th.Server.App().GetBlockByID("block-id-2")
require.NoError(t, err)
require.NotNil(t, block2)
// call the API to delete boards and blocks
dbab := &model.DeleteBoardsAndBlocks{
Boards: []string{"board-id-1", "board-id-2"},
Blocks: []string{"block-id-1", "block-id-2"},
}
success, resp := th.Client.DeleteBoardsAndBlocks(dbab)
th.CheckOK(resp)
require.True(t, success)
// ensure that the entities have been successfully deleted
board1, err = th.Server.App().GetBoard("board-id-1")
require.Error(t, err)
require.True(t, model.IsErrNotFound(err))
require.Nil(t, board1)
block1, err = th.Server.App().GetBlockByID("block-id-1")
require.Error(t, err)
require.True(t, model.IsErrNotFound(err))
require.Nil(t, block1)
board2, err = th.Server.App().GetBoard("board-id-2")
require.Error(t, err)
require.True(t, model.IsErrNotFound(err))
require.Nil(t, board2)
block2, err = th.Server.App().GetBlockByID("block-id-2")
require.Error(t, err)
require.True(t, model.IsErrNotFound(err))
require.Nil(t, block2)
})
}

Просмотреть файл

@@ -0,0 +1,127 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package integrationtests
import (
"io"
"net/http"
"net/http/httptest"
"testing"
"github.com/stretchr/testify/assert"
"github.com/mattermost/mattermost-server/v6/server/boards/server"
"github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/server/platform/shared/mlog"
)
func TestSetConfiguration(t *testing.T) {
boolTrue := true
stringRef := ""
baseFeatureFlags := &model.FeatureFlags{}
basePluginSettings := &model.PluginSettings{
Directory: &stringRef,
}
driverName := "testDriver"
dataSource := "testDirectory"
baseSQLSettings := &model.SqlSettings{
DriverName: &driverName,
DataSource: &dataSource,
}
directory := "testDirectory"
baseFileSettings := &model.FileSettings{
DriverName: &driverName,
Directory: &directory,
MaxFileSize: model.NewInt64(1024 * 1024),
}
days := 365
baseDataRetentionSettings := &model.DataRetentionSettings{
BoardsRetentionDays: &days,
}
usernameRef := "username"
baseTeamSettings := &model.TeamSettings{
TeammateNameDisplay: &usernameRef,
}
falseRef := false
basePrivacySettings := &model.PrivacySettings{
ShowEmailAddress: &falseRef,
ShowFullName: &falseRef,
}
baseConfig := &model.Config{
FeatureFlags: baseFeatureFlags,
PluginSettings: *basePluginSettings,
SqlSettings: *baseSQLSettings,
FileSettings: *baseFileSettings,
DataRetentionSettings: *baseDataRetentionSettings,
TeamSettings: *baseTeamSettings,
PrivacySettings: *basePrivacySettings,
}
t.Run("test enable telemetry", func(t *testing.T) {
logSettings := &model.LogSettings{
EnableDiagnostics: &boolTrue,
}
mmConfig := baseConfig
mmConfig.LogSettings = *logSettings
config := server.CreateBoardsConfig(*mmConfig, "", "testId")
assert.Equal(t, true, config.Telemetry)
assert.Equal(t, "testId", config.TelemetryID)
})
t.Run("test enable shared boards", func(t *testing.T) {
mmConfig := baseConfig
mmConfig.PluginSettings.Plugins = make(map[string]map[string]interface{})
mmConfig.PluginSettings.Plugins[server.PluginName] = make(map[string]interface{})
mmConfig.PluginSettings.Plugins[server.PluginName][server.SharedBoardsName] = true
config := server.CreateBoardsConfig(*mmConfig, "", "")
assert.Equal(t, true, config.EnablePublicSharedBoards)
})
t.Run("test boards feature flags", func(t *testing.T) {
featureFlags := &model.FeatureFlags{
TestFeature: "test",
TestBoolFeature: boolTrue,
BoardsFeatureFlags: "hello_world-myTest",
}
mmConfig := baseConfig
mmConfig.FeatureFlags = featureFlags
config := server.CreateBoardsConfig(*mmConfig, "", "")
assert.Equal(t, "true", config.FeatureFlags["TestBoolFeature"])
assert.Equal(t, "test", config.FeatureFlags["TestFeature"])
assert.Equal(t, "true", config.FeatureFlags["hello_world"])
assert.Equal(t, "true", config.FeatureFlags["myTest"])
})
}
func TestServeHTTP(t *testing.T) {
th := SetupTestHelperPluginMode(t)
defer th.TearDown()
b := server.NewBoardsServiceForTest(th.Server, &FakePluginAdapter{}, nil, mlog.CreateConsoleTestLogger(true, mlog.LvlError))
assert := assert.New(t)
w := httptest.NewRecorder()
r := httptest.NewRequest(http.MethodGet, "/hello", nil)
b.ServeHTTP(nil, w, r)
result := w.Result()
assert.NotNil(result)
defer result.Body.Close()
bodyBytes, err := io.ReadAll(result.Body)
assert.Nil(err)
bodyString := string(bodyBytes)
assert.Equal("Hello", bodyString)
}

291
server/boards/integrationtests/cards_test.go Обычный файл
Просмотреть файл

@@ -0,0 +1,291 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package integrationtests
import (
"fmt"
"strconv"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/v6/server/boards/model"
"github.com/mattermost/mattermost-server/v6/server/boards/utils"
)
func TestCreateCard(t *testing.T) {
t.Run("a non authenticated user should be rejected", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
board := th.CreateBoard(testTeamID, model.BoardTypeOpen)
th.Logout(th.Client)
card := &model.Card{
Title: "basic card",
}
cardNew, resp := th.Client.CreateCard(board.ID, card, false)
th.CheckUnauthorized(resp)
require.Nil(t, cardNew)
})
t.Run("good", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
board := th.CreateBoard(testTeamID, model.BoardTypeOpen)
contentOrder := []string{utils.NewID(utils.IDTypeBlock), utils.NewID(utils.IDTypeBlock), utils.NewID(utils.IDTypeBlock)}
card := &model.Card{
Title: "test card 1",
Icon: "😱",
ContentOrder: contentOrder,
}
cardNew, resp := th.Client.CreateCard(board.ID, card, false)
require.NoError(t, resp.Error)
th.CheckOK(resp)
require.NotNil(t, cardNew)
require.Equal(t, board.ID, cardNew.BoardID)
require.Equal(t, "test card 1", cardNew.Title)
require.Equal(t, "😱", cardNew.Icon)
require.Equal(t, contentOrder, cardNew.ContentOrder)
})
t.Run("invalid card", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
board := th.CreateBoard(testTeamID, model.BoardTypeOpen)
card := &model.Card{
Title: "too many emoji's",
Icon: "😱😱😱😱",
}
cardNew, resp := th.Client.CreateCard(board.ID, card, false)
require.Error(t, resp.Error)
require.Nil(t, cardNew)
})
}
func TestGetCards(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
board := th.CreateBoard(testTeamID, model.BoardTypeOpen)
userID := th.GetUser1().ID
const cardCount = 25
// make some cards with content
for i := 0; i < cardCount; i++ {
card := &model.Card{
BoardID: board.ID,
CreatedBy: userID,
ModifiedBy: userID,
Title: fmt.Sprintf("%d", i),
}
cardNew, resp := th.Client.CreateCard(board.ID, card, true)
th.CheckOK(resp)
blocks := make([]*model.Block, 0, 3)
for j := 0; j < 3; j++ {
now := model.GetMillis()
block := &model.Block{
ID: utils.NewID(utils.IDTypeBlock),
ParentID: cardNew.ID,
CreatedBy: userID,
ModifiedBy: userID,
CreateAt: now,
UpdateAt: now,
Schema: 1,
Type: model.TypeText,
Title: fmt.Sprintf("text %d for card %d", j, i),
BoardID: board.ID,
}
blocks = append(blocks, block)
}
_, resp = th.Client.InsertBlocks(board.ID, blocks, true)
th.CheckOK(resp)
}
t.Run("fetch all cards", func(t *testing.T) {
cards, resp := th.Client.GetCards(board.ID, 0, -1)
th.CheckOK(resp)
assert.Len(t, cards, cardCount)
})
t.Run("fetch with pagination", func(t *testing.T) {
cardNums := make(map[int]struct{})
// return first 10
cards, resp := th.Client.GetCards(board.ID, 0, 10)
th.CheckOK(resp)
assert.Len(t, cards, 10)
for _, card := range cards {
cardNum, err := strconv.Atoi(card.Title)
require.NoError(t, err)
cardNums[cardNum] = struct{}{}
}
// return second 10
cards, resp = th.Client.GetCards(board.ID, 1, 10)
th.CheckOK(resp)
assert.Len(t, cards, 10)
for _, card := range cards {
cardNum, err := strconv.Atoi(card.Title)
require.NoError(t, err)
cardNums[cardNum] = struct{}{}
}
// return remaining 5
cards, resp = th.Client.GetCards(board.ID, 2, 10)
th.CheckOK(resp)
assert.Len(t, cards, 5)
for _, card := range cards {
cardNum, err := strconv.Atoi(card.Title)
require.NoError(t, err)
cardNums[cardNum] = struct{}{}
}
// make sure all card numbers were returned
assert.Len(t, cardNums, cardCount)
for i := 0; i < cardCount; i++ {
_, ok := cardNums[i]
assert.True(t, ok)
}
})
t.Run("a non authenticated user should be rejected", func(t *testing.T) {
th.Logout(th.Client)
cards, resp := th.Client.GetCards(board.ID, 0, 10)
th.CheckUnauthorized(resp)
require.Nil(t, cards)
})
}
func TestPatchCard(t *testing.T) {
t.Run("a non authenticated user should be rejected", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
_, cards := th.CreateBoardAndCards(testTeamID, model.BoardTypeOpen, 1)
card := cards[0]
th.Logout(th.Client)
newTitle := "another title"
patch := &model.CardPatch{
Title: &newTitle,
}
patchedCard, resp := th.Client.PatchCard(card.ID, patch, false)
th.CheckUnauthorized(resp)
require.Nil(t, patchedCard)
})
t.Run("good", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
board, cards := th.CreateBoardAndCards(testTeamID, model.BoardTypeOpen, 1)
card := cards[0]
// Patch the card
newTitle := "another title"
newIcon := "🐿"
newContentOrder := reverse(card.ContentOrder)
updatedProps := modifyCardProps(card.Properties)
patch := &model.CardPatch{
Title: &newTitle,
Icon: &newIcon,
ContentOrder: &newContentOrder,
UpdatedProperties: updatedProps,
}
patchedCard, resp := th.Client.PatchCard(card.ID, patch, false)
th.CheckOK(resp)
require.NotNil(t, patchedCard)
require.Equal(t, board.ID, patchedCard.BoardID)
require.Equal(t, newTitle, patchedCard.Title)
require.Equal(t, newIcon, patchedCard.Icon)
require.NotEqual(t, card.ContentOrder, patchedCard.ContentOrder)
require.ElementsMatch(t, card.ContentOrder, patchedCard.ContentOrder)
require.EqualValues(t, updatedProps, patchedCard.Properties)
})
t.Run("invalid card patch", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
_, cards := th.CreateBoardAndCards(testTeamID, model.BoardTypeOpen, 1)
card := cards[0]
// Bad patch (too many emoji)
newIcon := "🐿🐿🐿"
patch := &model.CardPatch{
Icon: &newIcon,
}
cardNew, resp := th.Client.PatchCard(card.ID, patch, false)
require.Error(t, resp.Error)
require.Nil(t, cardNew)
})
}
func TestGetCard(t *testing.T) {
t.Run("a non authenticated user should be rejected", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
_, cards := th.CreateBoardAndCards(testTeamID, model.BoardTypeOpen, 1)
card := cards[0]
th.Logout(th.Client)
cardFetched, resp := th.Client.GetCard(card.ID)
th.CheckUnauthorized(resp)
require.Nil(t, cardFetched)
})
t.Run("good", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
board, cards := th.CreateBoardAndCards(testTeamID, model.BoardTypeOpen, 1)
card := cards[0]
cardFetched, resp := th.Client.GetCard(card.ID)
th.CheckOK(resp)
require.NotNil(t, cardFetched)
require.Equal(t, board.ID, cardFetched.BoardID)
require.Equal(t, card.Title, cardFetched.Title)
require.Equal(t, card.Icon, cardFetched.Icon)
require.Equal(t, card.ContentOrder, cardFetched.ContentOrder)
require.EqualValues(t, card.Properties, cardFetched.Properties)
})
}
// Helpers.
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 modifyCardProps(m map[string]any) map[string]any {
out := make(map[string]any)
for k := range m {
out[k] = utils.NewID(utils.IDTypeBlock)
}
return out
}

Просмотреть файл

@@ -0,0 +1,551 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package integrationtests
import (
"errors"
"fmt"
"net/http"
"os"
"testing"
"time"
"github.com/mattermost/mattermost-server/v6/server/boards/client"
"github.com/mattermost/mattermost-server/v6/server/boards/model"
"github.com/mattermost/mattermost-server/v6/server/boards/server"
"github.com/mattermost/mattermost-server/v6/server/boards/services/auth"
"github.com/mattermost/mattermost-server/v6/server/boards/services/config"
"github.com/mattermost/mattermost-server/v6/server/boards/services/permissions/localpermissions"
"github.com/mattermost/mattermost-server/v6/server/boards/services/permissions/mmpermissions"
"github.com/mattermost/mattermost-server/v6/server/boards/services/store"
"github.com/mattermost/mattermost-server/v6/server/boards/services/store/sqlstore"
"github.com/mattermost/mattermost-server/v6/server/boards/utils"
mm_model "github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/server/platform/shared/mlog"
"github.com/stretchr/testify/require"
)
const (
user1Username = "user1"
user2Username = "user2"
password = "Pa$$word"
testTeamID = "team-id"
)
const (
userAnon string = "anon"
userNoTeamMember string = "no-team-member"
userTeamMember string = "team-member"
userViewer string = "viewer"
userCommenter string = "commenter"
userEditor string = "editor"
userAdmin string = "admin"
userGuest string = "guest"
)
var (
userAnonID = userAnon
userNoTeamMemberID = userNoTeamMember
userTeamMemberID = userTeamMember
userViewerID = userViewer
userCommenterID = userCommenter
userEditorID = userEditor
userAdminID = userAdmin
userGuestID = userGuest
)
type LicenseType int
const (
LicenseNone LicenseType = iota // 0
LicenseProfessional // 1
LicenseEnterprise // 2
)
type TestHelper struct {
T *testing.T
Server *server.Server
Client *client.Client
Client2 *client.Client
origEnvUnitTesting string
}
type FakePermissionPluginAPI struct{}
func (*FakePermissionPluginAPI) HasPermissionTo(userID string, permission *mm_model.Permission) bool {
return userID == userAdmin
}
func (*FakePermissionPluginAPI) HasPermissionToTeam(userID string, teamID string, permission *mm_model.Permission) bool {
if permission.Id == model.PermissionManageTeam.Id {
return false
}
if userID == userNoTeamMember {
return false
}
if teamID == "empty-team" {
return false
}
return true
}
func (*FakePermissionPluginAPI) HasPermissionToChannel(userID string, channelID string, permission *mm_model.Permission) bool {
return channelID == "valid-channel-id" || channelID == "valid-channel-id-2"
}
func GetTestConfig(t *testing.T) *config.Configuration {
driver := os.Getenv("MM_SQLSETTINGS_DRIVERNAME")
if driver == "" {
driver = model.PostgresDBType
}
storeType := sqlstore.NewStoreType(driver, driver, true)
storeType.Store.Shutdown()
storeType.Logger.Shutdown()
logging := `
{
"testing": {
"type": "console",
"options": {
"out": "stdout"
},
"format": "plain",
"format_options": {
"delim": " "
},
"levels": [
{"id": 5, "name": "debug"},
{"id": 4, "name": "info"},
{"id": 3, "name": "warn"},
{"id": 2, "name": "error", "stacktrace": true},
{"id": 1, "name": "fatal", "stacktrace": true},
{"id": 0, "name": "panic", "stacktrace": true}
]
}
}`
return &config.Configuration{
ServerRoot: "http://localhost:8888",
Port: 8888,
DBType: driver,
DBConfigString: storeType.ConnString,
DBTablePrefix: "test_",
WebPath: "./pack",
FilesDriver: "local",
FilesPath: "./files",
LoggingCfgJSON: logging,
SessionExpireTime: int64(30 * time.Second),
AuthMode: "native",
}
}
func newTestServer(t *testing.T, singleUserToken string) *server.Server {
return newTestServerWithLicense(t, singleUserToken, LicenseNone)
}
func newTestServerWithLicense(t *testing.T, singleUserToken string, licenseType LicenseType) *server.Server {
cfg := GetTestConfig(t)
logger, _ := mlog.NewLogger()
err := logger.Configure("", cfg.LoggingCfgJSON, nil)
require.NoError(t, err)
singleUser := singleUserToken != ""
innerStore, err := server.NewStore(cfg, singleUser, logger)
require.NoError(t, err)
var db store.Store
switch licenseType {
case LicenseProfessional:
db = NewTestProfessionalStore(innerStore)
case LicenseEnterprise:
db = NewTestEnterpriseStore(innerStore)
case LicenseNone:
fallthrough
default:
db = innerStore
}
permissionsService := localpermissions.New(db, logger)
params := server.Params{
Cfg: cfg,
SingleUserToken: singleUserToken,
DBStore: db,
Logger: logger,
PermissionsService: permissionsService,
}
srv, err := server.New(params)
require.NoError(t, err)
return srv
}
func NewTestServerPluginMode(t *testing.T) *server.Server {
cfg := GetTestConfig(t)
cfg.AuthMode = "mattermost"
cfg.EnablePublicSharedBoards = true
logger, _ := mlog.NewLogger()
if err := logger.Configure("", cfg.LoggingCfgJSON, nil); err != nil {
panic(err)
}
innerStore, err := server.NewStore(cfg, false, logger)
if err != nil {
panic(err)
}
db := NewPluginTestStore(innerStore)
permissionsService := mmpermissions.New(db, &FakePermissionPluginAPI{}, logger)
params := server.Params{
Cfg: cfg,
DBStore: db,
Logger: logger,
PermissionsService: permissionsService,
}
srv, err := server.New(params)
if err != nil {
panic(err)
}
return srv
}
func newTestServerLocalMode(t *testing.T) *server.Server {
cfg := GetTestConfig(t)
cfg.EnablePublicSharedBoards = true
logger, _ := mlog.NewLogger()
err := logger.Configure("", cfg.LoggingCfgJSON, nil)
require.NoError(t, err)
db, err := server.NewStore(cfg, false, logger)
require.NoError(t, err)
permissionsService := localpermissions.New(db, logger)
params := server.Params{
Cfg: cfg,
DBStore: db,
Logger: logger,
PermissionsService: permissionsService,
}
srv, err := server.New(params)
require.NoError(t, err)
// Reduce password has strength for unit tests to dramatically speed up account creation and login
auth.PasswordHashStrength = 4
return srv
}
func SetupTestHelperWithToken(t *testing.T) *TestHelper {
origUnitTesting := os.Getenv("FOCALBOARD_UNIT_TESTING")
os.Setenv("FOCALBOARD_UNIT_TESTING", "1")
sessionToken := "TESTTOKEN"
th := &TestHelper{
T: t,
origEnvUnitTesting: origUnitTesting,
}
th.Server = newTestServer(t, sessionToken)
th.Client = client.NewClient(th.Server.Config().ServerRoot, sessionToken)
th.Client2 = client.NewClient(th.Server.Config().ServerRoot, sessionToken)
return th
}
func SetupTestHelper(t *testing.T) *TestHelper {
return SetupTestHelperWithLicense(t, LicenseNone)
}
func SetupTestHelperPluginMode(t *testing.T) *TestHelper {
origUnitTesting := os.Getenv("FOCALBOARD_UNIT_TESTING")
os.Setenv("FOCALBOARD_UNIT_TESTING", "1")
th := &TestHelper{
T: t,
origEnvUnitTesting: origUnitTesting,
}
th.Server = NewTestServerPluginMode(t)
th.Start()
return th
}
func SetupTestHelperLocalMode(t *testing.T) *TestHelper {
origUnitTesting := os.Getenv("FOCALBOARD_UNIT_TESTING")
os.Setenv("FOCALBOARD_UNIT_TESTING", "1")
th := &TestHelper{
T: t,
origEnvUnitTesting: origUnitTesting,
}
th.Server = newTestServerLocalMode(t)
th.Start()
return th
}
func SetupTestHelperWithLicense(t *testing.T, licenseType LicenseType) *TestHelper {
origUnitTesting := os.Getenv("FOCALBOARD_UNIT_TESTING")
os.Setenv("FOCALBOARD_UNIT_TESTING", "1")
th := &TestHelper{
T: t,
origEnvUnitTesting: origUnitTesting,
}
th.Server = newTestServerWithLicense(t, "", licenseType)
th.Client = client.NewClient(th.Server.Config().ServerRoot, "")
th.Client2 = client.NewClient(th.Server.Config().ServerRoot, "")
return th
}
// Start starts the test server and ensures that it's correctly
// responding to requests before returning.
func (th *TestHelper) Start() *TestHelper {
go func() {
if err := th.Server.Start(); err != nil {
panic(err)
}
}()
for {
URL := th.Server.Config().ServerRoot
th.Server.Logger().Info("Polling server", mlog.String("url", URL))
resp, err := http.Get(URL) //nolint:gosec
if err != nil {
th.Server.Logger().Error("Polling failed", mlog.Err(err))
time.Sleep(100 * time.Millisecond)
continue
}
resp.Body.Close()
// Currently returns 404
// if resp.StatusCode != http.StatusOK {
// th.Server.Logger().Error("Not OK", mlog.Int("statusCode", resp.StatusCode))
// continue
// }
// Reached this point: server is up and running!
th.Server.Logger().Info("Server ping OK", mlog.Int("statusCode", resp.StatusCode))
break
}
return th
}
// InitBasic starts the test server and initializes the clients of the
// helper, registering them and logging them into the system.
func (th *TestHelper) InitBasic() *TestHelper {
// Reduce password has strength for unit tests to dramatically speed up account creation and login
auth.PasswordHashStrength = 4
th.Start()
// user1
th.RegisterAndLogin(th.Client, user1Username, "user1@sample.com", password, "")
// get token
team, resp := th.Client.GetTeam(model.GlobalTeamID)
th.CheckOK(resp)
require.NotNil(th.T, team)
require.NotNil(th.T, team.SignupToken)
// user2
th.RegisterAndLogin(th.Client2, user2Username, "user2@sample.com", password, team.SignupToken)
return th
}
var ErrRegisterFail = errors.New("register failed")
func (th *TestHelper) TearDown() {
os.Setenv("FOCALBOARD_UNIT_TESTING", th.origEnvUnitTesting)
logger := th.Server.Logger()
if l, ok := logger.(*mlog.Logger); ok {
defer func() { _ = l.Shutdown() }()
}
err := th.Server.Shutdown()
if err != nil {
panic(err)
}
os.RemoveAll(th.Server.Config().FilesPath)
if err := os.Remove(th.Server.Config().DBConfigString); err == nil {
logger.Debug("Removed test database", mlog.String("file", th.Server.Config().DBConfigString))
}
}
func (th *TestHelper) RegisterAndLogin(client *client.Client, username, email, password, token string) {
req := &model.RegisterRequest{
Username: username,
Email: email,
Password: password,
Token: token,
}
success, resp := th.Client.Register(req)
th.CheckOK(resp)
require.True(th.T, success)
th.Login(client, username, password)
}
func (th *TestHelper) Login(client *client.Client, username, password string) {
req := &model.LoginRequest{
Type: "normal",
Username: username,
Password: password,
}
data, resp := client.Login(req)
th.CheckOK(resp)
require.NotNil(th.T, data)
}
func (th *TestHelper) Login1() {
th.Login(th.Client, user1Username, password)
}
func (th *TestHelper) Login2() {
th.Login(th.Client2, user2Username, password)
}
func (th *TestHelper) Logout(client *client.Client) {
client.Token = ""
}
func (th *TestHelper) Me(client *client.Client) *model.User {
user, resp := client.GetMe()
th.CheckOK(resp)
require.NotNil(th.T, user)
return user
}
func (th *TestHelper) CreateBoard(teamID string, boardType model.BoardType) *model.Board {
newBoard := &model.Board{
TeamID: teamID,
Type: boardType,
}
board, resp := th.Client.CreateBoard(newBoard)
th.CheckOK(resp)
return board
}
func (th *TestHelper) CreateBoards(teamID string, boardType model.BoardType, count int) []*model.Board {
boards := make([]*model.Board, 0, count)
for i := 0; i < count; i++ {
board := th.CreateBoard(teamID, boardType)
boards = append(boards, board)
}
return boards
}
func (th *TestHelper) CreateCategory(category model.Category) *model.Category {
cat, resp := th.Client.CreateCategory(category)
th.CheckOK(resp)
return cat
}
func (th *TestHelper) UpdateCategoryBoard(teamID, categoryID, boardID string) {
response := th.Client.UpdateCategoryBoard(teamID, categoryID, boardID)
th.CheckOK(response)
}
func (th *TestHelper) CreateBoardAndCards(teamdID string, boardType model.BoardType, numCards int) (*model.Board, []*model.Card) {
board := th.CreateBoard(teamdID, boardType)
cards := make([]*model.Card, 0, numCards)
for i := 0; i < numCards; i++ {
card := &model.Card{
Title: fmt.Sprintf("test card %d", i+1),
ContentOrder: []string{utils.NewID(utils.IDTypeBlock), utils.NewID(utils.IDTypeBlock), utils.NewID(utils.IDTypeBlock)},
Icon: "😱",
Properties: th.MakeCardProps(5),
}
newCard, resp := th.Client.CreateCard(board.ID, card, true)
th.CheckOK(resp)
cards = append(cards, newCard)
}
return board, cards
}
func (th *TestHelper) MakeCardProps(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 (th *TestHelper) GetUserCategoryBoards(teamID string) []model.CategoryBoards {
categoryBoards, response := th.Client.GetUserCategoryBoards(teamID)
th.CheckOK(response)
return categoryBoards
}
func (th *TestHelper) DeleteCategory(teamID, categoryID string) {
response := th.Client.DeleteCategory(teamID, categoryID)
th.CheckOK(response)
}
func (th *TestHelper) GetUser1() *model.User {
return th.Me(th.Client)
}
func (th *TestHelper) GetUser2() *model.User {
return th.Me(th.Client2)
}
func (th *TestHelper) CheckOK(r *client.Response) {
require.Equal(th.T, http.StatusOK, r.StatusCode)
require.NoError(th.T, r.Error)
}
func (th *TestHelper) CheckBadRequest(r *client.Response) {
require.Equal(th.T, http.StatusBadRequest, r.StatusCode)
require.Error(th.T, r.Error)
}
func (th *TestHelper) CheckNotFound(r *client.Response) {
require.Equal(th.T, http.StatusNotFound, r.StatusCode)
require.Error(th.T, r.Error)
}
func (th *TestHelper) CheckUnauthorized(r *client.Response) {
require.Equal(th.T, http.StatusUnauthorized, r.StatusCode)
require.Error(th.T, r.Error)
}
func (th *TestHelper) CheckForbidden(r *client.Response) {
require.Equal(th.T, http.StatusForbidden, r.StatusCode)
require.Error(th.T, r.Error)
}
func (th *TestHelper) CheckRequestEntityTooLarge(r *client.Response) {
require.Equal(th.T, http.StatusRequestEntityTooLarge, r.StatusCode)
require.Error(th.T, r.Error)
}
func (th *TestHelper) CheckNotImplemented(r *client.Response) {
require.Equal(th.T, http.StatusNotImplemented, r.StatusCode)
require.Error(th.T, r.Error)
}

Просмотреть файл

@@ -0,0 +1,364 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package integrationtests
import (
"math"
"os"
"strconv"
"testing"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/v6/server/boards/model"
"github.com/mattermost/mattermost-server/v6/server/boards/utils"
)
var (
OneHour int64 = 360000
OneDay int64 = OneHour * 24
OneYear int64 = OneDay * 365
)
func setupTestHelperForCompliance(t *testing.T, complianceLicense bool) (*TestHelper, Clients) {
os.Setenv("FOCALBOARD_UNIT_TESTING_COMPLIANCE", strconv.FormatBool(complianceLicense))
th := SetupTestHelperPluginMode(t)
clients := setupClients(th)
th.Client = clients.TeamMember
th.Client2 = clients.TeamMember
return th, clients
}
func TestGetBoardsForCompliance(t *testing.T) {
t.Run("missing Features.Compliance license should fail", func(t *testing.T) {
th, clients := setupTestHelperForCompliance(t, false)
defer th.TearDown()
_ = th.CreateBoards(testTeamID, model.BoardTypeOpen, 2)
bcr, resp := clients.Admin.GetBoardsForCompliance(testTeamID, 0, 0)
th.CheckNotImplemented(resp)
require.Nil(t, bcr)
})
t.Run("a non authenticated user should be rejected", func(t *testing.T) {
th, clients := setupTestHelperForCompliance(t, true)
defer th.TearDown()
_ = th.CreateBoards(testTeamID, model.BoardTypeOpen, 2)
th.Logout(th.Client)
bcr, resp := clients.Anon.GetBoardsForCompliance(testTeamID, 0, 0)
th.CheckUnauthorized(resp)
require.Nil(t, bcr)
})
t.Run("a user without manage_system permission should be rejected", func(t *testing.T) {
th, clients := setupTestHelperForCompliance(t, true)
defer th.TearDown()
_ = th.CreateBoards(testTeamID, model.BoardTypeOpen, 2)
bcr, resp := clients.TeamMember.GetBoardsForCompliance(testTeamID, 0, 0)
th.CheckUnauthorized(resp)
require.Nil(t, bcr)
})
t.Run("good call", func(t *testing.T) {
th, clients := setupTestHelperForCompliance(t, true)
defer th.TearDown()
const count = 10
_ = th.CreateBoards(testTeamID, model.BoardTypeOpen, count)
bcr, resp := clients.Admin.GetBoardsForCompliance(testTeamID, 0, 0)
th.CheckOK(resp)
require.False(t, bcr.HasNext)
require.Len(t, bcr.Results, count)
})
t.Run("pagination", func(t *testing.T) {
th, clients := setupTestHelperForCompliance(t, true)
defer th.TearDown()
const count = 20
const perPage = 3
_ = th.CreateBoards(testTeamID, model.BoardTypeOpen, count)
boards := make([]*model.Board, 0, count)
page := 0
for {
bcr, resp := clients.Admin.GetBoardsForCompliance(testTeamID, page, perPage)
page++
th.CheckOK(resp)
boards = append(boards, bcr.Results...)
if !bcr.HasNext {
break
}
}
require.Len(t, boards, count)
require.Equal(t, int(math.Floor((count/perPage)+1)), page)
})
t.Run("invalid teamID", func(t *testing.T) {
th, clients := setupTestHelperForCompliance(t, true)
defer th.TearDown()
_ = th.CreateBoards(testTeamID, model.BoardTypeOpen, 2)
bcr, resp := clients.Admin.GetBoardsForCompliance(utils.NewID(utils.IDTypeTeam), 0, 0)
th.CheckBadRequest(resp)
require.Nil(t, bcr)
})
}
func TestGetBoardsComplianceHistory(t *testing.T) {
t.Run("missing Features.Compliance license should fail", func(t *testing.T) {
th, clients := setupTestHelperForCompliance(t, false)
defer th.TearDown()
_ = th.CreateBoards(testTeamID, model.BoardTypeOpen, 2)
bchr, resp := clients.Admin.GetBoardsComplianceHistory(utils.GetMillis()-OneDay, true, testTeamID, 0, 0)
th.CheckNotImplemented(resp)
require.Nil(t, bchr)
})
t.Run("a non authenticated user should be rejected", func(t *testing.T) {
th, clients := setupTestHelperForCompliance(t, true)
defer th.TearDown()
_ = th.CreateBoards(testTeamID, model.BoardTypeOpen, 2)
th.Logout(th.Client)
bchr, resp := clients.Anon.GetBoardsComplianceHistory(utils.GetMillis()-OneDay, true, testTeamID, 0, 0)
th.CheckUnauthorized(resp)
require.Nil(t, bchr)
})
t.Run("a user without manage_system permission should be rejected", func(t *testing.T) {
th, clients := setupTestHelperForCompliance(t, true)
defer th.TearDown()
_ = th.CreateBoards(testTeamID, model.BoardTypeOpen, 2)
bchr, resp := clients.TeamMember.GetBoardsComplianceHistory(utils.GetMillis()-OneDay, true, testTeamID, 0, 0)
th.CheckUnauthorized(resp)
require.Nil(t, bchr)
})
t.Run("good call, exclude deleted", func(t *testing.T) {
th, clients := setupTestHelperForCompliance(t, true)
defer th.TearDown()
const count = 10
boards := th.CreateBoards(testTeamID, model.BoardTypeOpen, count)
deleted, resp := th.Client.DeleteBoard(boards[0].ID)
th.CheckOK(resp)
require.True(t, deleted)
deleted, resp = th.Client.DeleteBoard(boards[1].ID)
th.CheckOK(resp)
require.True(t, deleted)
bchr, resp := clients.Admin.GetBoardsComplianceHistory(utils.GetMillis()-OneDay, false, testTeamID, 0, 0)
th.CheckOK(resp)
require.False(t, bchr.HasNext)
require.Len(t, bchr.Results, count-2) // two boards deleted
})
t.Run("good call, include deleted", func(t *testing.T) {
th, clients := setupTestHelperForCompliance(t, true)
defer th.TearDown()
const count = 10
boards := th.CreateBoards(testTeamID, model.BoardTypeOpen, count)
deleted, resp := th.Client.DeleteBoard(boards[0].ID)
th.CheckOK(resp)
require.True(t, deleted)
deleted, resp = th.Client.DeleteBoard(boards[1].ID)
th.CheckOK(resp)
require.True(t, deleted)
bchr, resp := clients.Admin.GetBoardsComplianceHistory(utils.GetMillis()-OneDay, true, testTeamID, 0, 0)
th.CheckOK(resp)
require.False(t, bchr.HasNext)
require.Len(t, bchr.Results, count+2) // both deleted boards have 2 history records each
})
t.Run("pagination", func(t *testing.T) {
th, clients := setupTestHelperForCompliance(t, true)
defer th.TearDown()
const count = 20
const perPage = 3
_ = th.CreateBoards(testTeamID, model.BoardTypeOpen, count)
boardHistory := make([]*model.BoardHistory, 0, count)
page := 0
for {
bchr, resp := clients.Admin.GetBoardsComplianceHistory(utils.GetMillis()-OneDay, true, testTeamID, page, perPage)
page++
th.CheckOK(resp)
boardHistory = append(boardHistory, bchr.Results...)
if !bchr.HasNext {
break
}
}
require.Len(t, boardHistory, count)
require.Equal(t, int(math.Floor((count/perPage)+1)), page)
})
t.Run("invalid teamID", func(t *testing.T) {
th, clients := setupTestHelperForCompliance(t, true)
defer th.TearDown()
_ = th.CreateBoards(testTeamID, model.BoardTypeOpen, 2)
bchr, resp := clients.Admin.GetBoardsComplianceHistory(utils.GetMillis()-OneDay, true, utils.NewID(utils.IDTypeTeam), 0, 0)
th.CheckBadRequest(resp)
require.Nil(t, bchr)
})
}
func TestGetBlocksComplianceHistory(t *testing.T) {
t.Run("missing Features.Compliance license should fail", func(t *testing.T) {
th, clients := setupTestHelperForCompliance(t, false)
defer th.TearDown()
board, _ := th.CreateBoardAndCards(testTeamID, model.BoardTypeOpen, 2)
bchr, resp := clients.Admin.GetBlocksComplianceHistory(utils.GetMillis()-OneDay, true, testTeamID, board.ID, 0, 0)
th.CheckNotImplemented(resp)
require.Nil(t, bchr)
})
t.Run("a non authenticated user should be rejected", func(t *testing.T) {
th, clients := setupTestHelperForCompliance(t, true)
defer th.TearDown()
board, _ := th.CreateBoardAndCards(testTeamID, model.BoardTypeOpen, 2)
bchr, resp := clients.Anon.GetBlocksComplianceHistory(utils.GetMillis()-OneDay, true, testTeamID, board.ID, 0, 0)
th.CheckUnauthorized(resp)
require.Nil(t, bchr)
})
t.Run("a user without manage_system permission should be rejected", func(t *testing.T) {
th, clients := setupTestHelperForCompliance(t, true)
defer th.TearDown()
board, _ := th.CreateBoardAndCards(testTeamID, model.BoardTypeOpen, 2)
bchr, resp := clients.TeamMember.GetBlocksComplianceHistory(utils.GetMillis()-OneDay, true, testTeamID, board.ID, 0, 0)
th.CheckUnauthorized(resp)
require.Nil(t, bchr)
})
t.Run("good call, exclude deleted", func(t *testing.T) {
th, clients := setupTestHelperForCompliance(t, true)
defer th.TearDown()
const count = 10
board, cards := th.CreateBoardAndCards(testTeamID, model.BoardTypeOpen, count)
deleted, resp := th.Client.DeleteBlock(board.ID, cards[0].ID, true)
th.CheckOK(resp)
require.True(t, deleted)
deleted, resp = th.Client.DeleteBlock(board.ID, cards[1].ID, true)
th.CheckOK(resp)
require.True(t, deleted)
bchr, resp := clients.Admin.GetBlocksComplianceHistory(utils.GetMillis()-OneDay, false, testTeamID, board.ID, 0, 0)
th.CheckOK(resp)
require.False(t, bchr.HasNext)
require.Len(t, bchr.Results, count-2) // 2 blocks deleted
})
t.Run("good call, include deleted", func(t *testing.T) {
th, clients := setupTestHelperForCompliance(t, true)
defer th.TearDown()
const count = 10
board, cards := th.CreateBoardAndCards(testTeamID, model.BoardTypeOpen, count)
deleted, resp := th.Client.DeleteBlock(board.ID, cards[0].ID, true)
th.CheckOK(resp)
require.True(t, deleted)
deleted, resp = th.Client.DeleteBlock(board.ID, cards[1].ID, true)
th.CheckOK(resp)
require.True(t, deleted)
bchr, resp := clients.Admin.GetBlocksComplianceHistory(utils.GetMillis()-OneDay, true, testTeamID, board.ID, 0, 0)
th.CheckOK(resp)
require.False(t, bchr.HasNext)
require.Len(t, bchr.Results, count+2) // both deleted boards have 2 history records each
})
t.Run("pagination", func(t *testing.T) {
th, clients := setupTestHelperForCompliance(t, true)
defer th.TearDown()
const count = 20
const perPage = 3
board, _ := th.CreateBoardAndCards(testTeamID, model.BoardTypeOpen, count)
blockHistory := make([]*model.BlockHistory, 0, count)
page := 0
for {
bchr, resp := clients.Admin.GetBlocksComplianceHistory(utils.GetMillis()-OneDay, true, testTeamID, board.ID, page, perPage)
page++
th.CheckOK(resp)
blockHistory = append(blockHistory, bchr.Results...)
if !bchr.HasNext {
break
}
}
require.Len(t, blockHistory, count)
require.Equal(t, int(math.Floor((count/perPage)+1)), page)
})
t.Run("invalid teamID", func(t *testing.T) {
th, clients := setupTestHelperForCompliance(t, true)
defer th.TearDown()
board, _ := th.CreateBoardAndCards(testTeamID, model.BoardTypeOpen, 2)
bchr, resp := clients.Admin.GetBlocksComplianceHistory(utils.GetMillis()-OneDay, true, utils.NewID(utils.IDTypeTeam), board.ID, 0, 0)
th.CheckBadRequest(resp)
require.Nil(t, bchr)
})
t.Run("invalid boardID", func(t *testing.T) {
th, clients := setupTestHelperForCompliance(t, true)
defer th.TearDown()
_, _ = th.CreateBoardAndCards(testTeamID, model.BoardTypeOpen, 2)
bchr, resp := clients.Admin.GetBlocksComplianceHistory(utils.GetMillis()-OneDay, true, testTeamID, utils.NewID(utils.IDTypeBoard), 0, 0)
th.CheckBadRequest(resp)
require.Nil(t, bchr)
})
}

Просмотреть файл

@@ -0,0 +1,102 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package integrationtests
import (
"testing"
"github.com/golang/mock/gomock"
"github.com/mattermost/mattermost-server/v6/server/boards/model"
"github.com/mattermost/mattermost-server/v6/server/boards/server"
"github.com/mattermost/mattermost-server/v6/server/boards/ws"
mockservicesapi "github.com/mattermost/mattermost-server/v6/server/boards/model/mocks"
mm_model "github.com/mattermost/mattermost-server/v6/model"
"github.com/mattermost/mattermost-server/v6/server/platform/shared/mlog"
"github.com/stretchr/testify/assert"
)
func TestConfigurationNullConfiguration(t *testing.T) {
th := SetupTestHelperPluginMode(t)
defer th.TearDown()
logger := mlog.CreateConsoleTestLogger(true, mlog.LvlError)
boardsApp := server.NewBoardsServiceForTest(th.Server, &FakePluginAdapter{}, nil, logger)
assert.NotNil(t, boardsApp.Config())
}
func TestOnConfigurationChange(t *testing.T) {
stringRef := ""
basePlugins := make(map[string]map[string]interface{})
basePlugins[server.PluginName] = make(map[string]interface{})
basePlugins[server.PluginName][server.SharedBoardsName] = true
baseFeatureFlags := &mm_model.FeatureFlags{
BoardsFeatureFlags: "Feature1-Feature2",
}
basePluginSettings := &mm_model.PluginSettings{
Directory: &stringRef,
Plugins: basePlugins,
}
intRef := 365
baseDataRetentionSettings := &mm_model.DataRetentionSettings{
BoardsRetentionDays: &intRef,
}
usernameRef := "username"
baseTeamSettings := &mm_model.TeamSettings{
TeammateNameDisplay: &usernameRef,
}
falseRef := false
basePrivacySettings := &mm_model.PrivacySettings{
ShowEmailAddress: &falseRef,
ShowFullName: &falseRef,
}
baseConfig := &mm_model.Config{
FeatureFlags: baseFeatureFlags,
PluginSettings: *basePluginSettings,
DataRetentionSettings: *baseDataRetentionSettings,
TeamSettings: *baseTeamSettings,
PrivacySettings: *basePrivacySettings,
}
t.Run("Test Load Plugin Success", func(t *testing.T) {
th := SetupTestHelperPluginMode(t)
defer th.TearDown()
ctrl := gomock.NewController(t)
api := mockservicesapi.NewMockServicesAPI(ctrl)
api.EXPECT().GetConfig().Return(baseConfig)
b := server.NewBoardsServiceForTest(th.Server, &FakePluginAdapter{}, api, mlog.CreateConsoleTestLogger(true, mlog.LvlError))
err := b.OnConfigurationChange()
assert.NoError(t, err)
assert.Equal(t, 1, count)
// make sure both App and Server got updated
assert.True(t, b.Config().EnablePublicSharedBoards)
assert.True(t, b.ClientConfig().EnablePublicSharedBoards)
assert.Equal(t, "true", b.Config().FeatureFlags["Feature1"])
assert.Equal(t, "true", b.Config().FeatureFlags["Feature2"])
assert.Equal(t, "", b.Config().FeatureFlags["Feature3"])
})
}
var count = 0
type FakePluginAdapter struct {
ws.PluginAdapter
}
func (c *FakePluginAdapter) BroadcastConfigChange(clientConfig model.ClientConfig) {
count++
}

Просмотреть файл

@@ -0,0 +1,185 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package integrationtests
import (
"fmt"
"testing"
"github.com/mattermost/mattermost-server/v6/server/boards/model"
"github.com/mattermost/mattermost-server/v6/server/boards/utils"
"github.com/stretchr/testify/require"
)
func TestMoveContentBlock(t *testing.T) {
th := SetupTestHelperWithToken(t).Start()
defer th.TearDown()
board := th.CreateBoard("team-id", model.BoardTypeOpen)
cardID1 := utils.NewID(utils.IDTypeBlock)
cardID2 := utils.NewID(utils.IDTypeBlock)
contentBlockID1 := utils.NewID(utils.IDTypeBlock)
contentBlockID2 := utils.NewID(utils.IDTypeBlock)
contentBlockID3 := utils.NewID(utils.IDTypeBlock)
contentBlockID4 := utils.NewID(utils.IDTypeBlock)
contentBlockID5 := utils.NewID(utils.IDTypeBlock)
contentBlockID6 := utils.NewID(utils.IDTypeBlock)
card1 := &model.Block{
ID: cardID1,
BoardID: board.ID,
CreateAt: 1,
UpdateAt: 1,
Type: model.TypeCard,
Fields: map[string]interface{}{
"contentOrder": []string{contentBlockID1, contentBlockID2, contentBlockID3},
},
}
card2 := &model.Block{
ID: cardID2,
BoardID: board.ID,
CreateAt: 1,
UpdateAt: 1,
Type: model.TypeCard,
Fields: map[string]interface{}{
"contentOrder": []string{contentBlockID4, contentBlockID5, contentBlockID6},
},
}
contentBlock1 := &model.Block{
ID: contentBlockID1,
BoardID: board.ID,
CreateAt: 1,
UpdateAt: 1,
Type: model.TypeCard,
ParentID: cardID1,
}
contentBlock2 := &model.Block{
ID: contentBlockID2,
BoardID: board.ID,
CreateAt: 1,
UpdateAt: 1,
Type: model.TypeCard,
ParentID: cardID1,
}
contentBlock3 := &model.Block{
ID: contentBlockID3,
BoardID: board.ID,
CreateAt: 1,
UpdateAt: 1,
Type: model.TypeCard,
ParentID: cardID1,
}
contentBlock4 := &model.Block{
ID: contentBlockID4,
BoardID: board.ID,
CreateAt: 1,
UpdateAt: 1,
Type: model.TypeCard,
ParentID: cardID2,
}
contentBlock5 := &model.Block{
ID: contentBlockID5,
BoardID: board.ID,
CreateAt: 1,
UpdateAt: 1,
Type: model.TypeCard,
ParentID: cardID2,
}
contentBlock6 := &model.Block{
ID: contentBlockID6,
BoardID: board.ID,
CreateAt: 1,
UpdateAt: 1,
Type: model.TypeCard,
ParentID: cardID2,
}
newBlocks := []*model.Block{
contentBlock1,
contentBlock2,
contentBlock3,
contentBlock4,
contentBlock5,
contentBlock6,
card1,
card2,
}
createdBlocks, resp := th.Client.InsertBlocks(board.ID, newBlocks, false)
require.NoError(t, resp.Error)
require.Len(t, newBlocks, 8)
contentBlock1.ID = createdBlocks[0].ID
contentBlock2.ID = createdBlocks[1].ID
contentBlock3.ID = createdBlocks[2].ID
contentBlock4.ID = createdBlocks[3].ID
contentBlock5.ID = createdBlocks[4].ID
contentBlock6.ID = createdBlocks[5].ID
card1.ID = createdBlocks[6].ID
card2.ID = createdBlocks[7].ID
ttCases := []struct {
name string
srcBlockID string
dstBlockID string
where string
userID string
errorMessage string
expectedContentOrder []interface{}
}{
{
name: "not matching parents",
srcBlockID: contentBlock1.ID,
dstBlockID: contentBlock4.ID,
where: "after",
userID: "user-id",
errorMessage: fmt.Sprintf("payload: {\"error\":\"not matching parent %s and %s\",\"errorCode\":400}", card1.ID, card2.ID),
expectedContentOrder: []interface{}{contentBlock1.ID, contentBlock2.ID, contentBlock3.ID},
},
{
name: "valid request with not real change",
srcBlockID: contentBlock2.ID,
dstBlockID: contentBlock1.ID,
where: "after",
userID: "user-id",
errorMessage: "",
expectedContentOrder: []interface{}{contentBlock1.ID, contentBlock2.ID, contentBlock3.ID},
},
{
name: "valid request changing order with before",
srcBlockID: contentBlock2.ID,
dstBlockID: contentBlock1.ID,
where: "before",
userID: "user-id",
errorMessage: "",
expectedContentOrder: []interface{}{contentBlock2.ID, contentBlock1.ID, contentBlock3.ID},
},
{
name: "valid request changing order with after",
srcBlockID: contentBlock1.ID,
dstBlockID: contentBlock2.ID,
where: "after",
userID: "user-id",
errorMessage: "",
expectedContentOrder: []interface{}{contentBlock2.ID, contentBlock1.ID, contentBlock3.ID},
},
}
for _, tc := range ttCases {
t.Run(tc.name, func(t *testing.T) {
_, resp := th.Client.MoveContentBlock(tc.srcBlockID, tc.dstBlockID, tc.where, tc.userID)
if tc.errorMessage == "" {
require.NoError(t, resp.Error)
} else {
require.EqualError(t, resp.Error, tc.errorMessage)
}
parent, err := th.Server.App().GetBlockByID(card1.ID)
require.NoError(t, err)
require.Equal(t, parent.Fields["contentOrder"], tc.expectedContentOrder)
})
}
}

Просмотреть файл

@@ -0,0 +1,70 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package integrationtests
import (
"bytes"
"testing"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/v6/server/boards/model"
"github.com/mattermost/mattermost-server/v6/server/boards/utils"
)
func TestExportBoard(t *testing.T) {
t.Run("export single board", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
board := &model.Board{
ID: utils.NewID(utils.IDTypeBoard),
TeamID: "test-team",
Title: "Export Test Board",
CreatedBy: th.GetUser1().ID,
Type: model.BoardTypeOpen,
CreateAt: utils.GetMillis(),
UpdateAt: utils.GetMillis(),
}
block := &model.Block{
ID: utils.NewID(utils.IDTypeCard),
ParentID: board.ID,
Type: model.TypeCard,
BoardID: board.ID,
Title: "Test card # for export",
CreatedBy: th.GetUser1().ID,
CreateAt: utils.GetMillis(),
UpdateAt: utils.GetMillis(),
}
babs := &model.BoardsAndBlocks{
Boards: []*model.Board{board},
Blocks: []*model.Block{block},
}
babs, resp := th.Client.CreateBoardsAndBlocks(babs)
th.CheckOK(resp)
// export the board to an in-memory archive file
buf, resp := th.Client.ExportBoardArchive(babs.Boards[0].ID)
th.CheckOK(resp)
require.NotNil(t, buf)
// import the archive file to team 0
resp = th.Client.ImportArchive(model.GlobalTeamID, bytes.NewReader(buf))
th.CheckOK(resp)
require.NoError(t, resp.Error)
// check for test card
boardsImported, err := th.Server.App().GetBoardsForUserAndTeam(th.GetUser1().ID, model.GlobalTeamID, true)
require.NoError(t, err)
require.Len(t, boardsImported, 1)
boardImported := boardsImported[0]
blocksImported, err := th.Server.App().GetBlocksForBoard(boardImported.ID)
require.NoError(t, err)
require.Len(t, blocksImported, 1)
require.Equal(t, block.Title, blocksImported[0].Title)
})
}

91
server/boards/integrationtests/file_test.go Обычный файл
Просмотреть файл

@@ -0,0 +1,91 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package integrationtests
import (
"bytes"
"testing"
"github.com/mattermost/mattermost-server/v6/server/boards/model"
"github.com/stretchr/testify/require"
)
func TestUploadFile(t *testing.T) {
const (
testTeamID = "team-id"
)
t.Run("a non authenticated user should be rejected", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
th.Logout(th.Client)
file, resp := th.Client.TeamUploadFile(testTeamID, "test-board-id", bytes.NewBuffer([]byte("test")))
th.CheckUnauthorized(resp)
require.Nil(t, file)
})
t.Run("upload a file to an existing team and board without permissions", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
file, resp := th.Client.TeamUploadFile(testTeamID, "not-valid-board", bytes.NewBuffer([]byte("test")))
th.CheckForbidden(resp)
require.Nil(t, file)
})
t.Run("upload a file to an existing team and board with permissions", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
testBoard := th.CreateBoard(testTeamID, model.BoardTypeOpen)
file, resp := th.Client.TeamUploadFile(testTeamID, testBoard.ID, bytes.NewBuffer([]byte("test")))
th.CheckOK(resp)
require.NoError(t, resp.Error)
require.NotNil(t, file)
require.NotNil(t, file.FileID)
})
t.Run("upload a file to an existing team and board with permissions but reaching the MaxFileLimit", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
testBoard := th.CreateBoard(testTeamID, model.BoardTypeOpen)
config := th.Server.App().GetConfig()
config.MaxFileSize = 1
th.Server.App().SetConfig(config)
file, resp := th.Client.TeamUploadFile(testTeamID, testBoard.ID, bytes.NewBuffer([]byte("test")))
th.CheckRequestEntityTooLarge(resp)
require.Nil(t, file)
config.MaxFileSize = 100000
th.Server.App().SetConfig(config)
file, resp = th.Client.TeamUploadFile(testTeamID, testBoard.ID, bytes.NewBuffer([]byte("test")))
th.CheckOK(resp)
require.NoError(t, resp.Error)
require.NotNil(t, file)
require.NotNil(t, file.FileID)
})
}
func TestFileInfo(t *testing.T) {
const (
testTeamID = "team-id"
)
t.Run("Retrieving file info", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
testBoard := th.CreateBoard(testTeamID, model.BoardTypeOpen)
fileInfo, resp := th.Client.TeamUploadFileInfo(testTeamID, testBoard.ID, "test")
th.CheckOK(resp)
require.NotNil(t, fileInfo)
require.NotNil(t, fileInfo.Id)
})
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@@ -0,0 +1,324 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package integrationtests
import (
"errors"
"os"
"strconv"
"strings"
"github.com/mattermost/mattermost-server/v6/server/boards/model"
"github.com/mattermost/mattermost-server/v6/server/boards/services/store"
mm_model "github.com/mattermost/mattermost-server/v6/model"
)
var errTestStore = errors.New("plugin test store error")
type PluginTestStore struct {
store.Store
users map[string]*model.User
testTeam *model.Team
otherTeam *model.Team
emptyTeam *model.Team
baseTeam *model.Team
}
func NewPluginTestStore(innerStore store.Store) *PluginTestStore {
return &PluginTestStore{
Store: innerStore,
users: map[string]*model.User{
"no-team-member": {
ID: "no-team-member",
Username: "no-team-member",
Email: "no-team-member@sample.com",
CreateAt: model.GetMillis(),
UpdateAt: model.GetMillis(),
},
"team-member": {
ID: "team-member",
Username: "team-member",
Email: "team-member@sample.com",
CreateAt: model.GetMillis(),
UpdateAt: model.GetMillis(),
},
"viewer": {
ID: "viewer",
Username: "viewer",
Email: "viewer@sample.com",
CreateAt: model.GetMillis(),
UpdateAt: model.GetMillis(),
},
"commenter": {
ID: "commenter",
Username: "commenter",
Email: "commenter@sample.com",
CreateAt: model.GetMillis(),
UpdateAt: model.GetMillis(),
},
"editor": {
ID: "editor",
Username: "editor",
Email: "editor@sample.com",
CreateAt: model.GetMillis(),
UpdateAt: model.GetMillis(),
},
"admin": {
ID: "admin",
Username: "admin",
Email: "admin@sample.com",
CreateAt: model.GetMillis(),
UpdateAt: model.GetMillis(),
},
"guest": {
ID: "guest",
Username: "guest",
Email: "guest@sample.com",
CreateAt: model.GetMillis(),
UpdateAt: model.GetMillis(),
IsGuest: true,
},
},
testTeam: &model.Team{ID: "test-team", Title: "Test Team"},
otherTeam: &model.Team{ID: "other-team", Title: "Other Team"},
emptyTeam: &model.Team{ID: "empty-team", Title: "Empty Team"},
baseTeam: &model.Team{ID: "0", Title: "Base Team"},
}
}
func (s *PluginTestStore) GetTeam(id string) (*model.Team, error) {
switch id {
case "0":
return s.baseTeam, nil
case "other-team":
return s.otherTeam, nil
case "test-team", testTeamID:
return s.testTeam, nil
case "empty-team":
return s.emptyTeam, nil
}
return nil, errTestStore
}
func (s *PluginTestStore) GetTeamsForUser(userID string) ([]*model.Team, error) {
switch userID {
case "no-team-member":
return []*model.Team{}, nil
case "team-member":
return []*model.Team{s.testTeam, s.otherTeam}, nil
case "viewer":
return []*model.Team{s.testTeam, s.otherTeam}, nil
case "commenter":
return []*model.Team{s.testTeam, s.otherTeam}, nil
case "editor":
return []*model.Team{s.testTeam, s.otherTeam}, nil
case "admin":
return []*model.Team{s.testTeam, s.otherTeam}, nil
case "guest":
return []*model.Team{s.testTeam}, nil
}
return nil, errTestStore
}
func (s *PluginTestStore) GetUserByID(userID string) (*model.User, error) {
user := s.users[userID]
if user == nil {
return nil, errTestStore
}
return user, nil
}
func (s *PluginTestStore) GetUserByEmail(email string) (*model.User, error) {
for _, user := range s.users {
if user.Email == email {
return user, nil
}
}
return nil, errTestStore
}
func (s *PluginTestStore) GetUserByUsername(username string) (*model.User, error) {
for _, user := range s.users {
if user.Username == username {
return user, nil
}
}
return nil, errTestStore
}
func (s *PluginTestStore) GetUserPreferences(userID string) (mm_model.Preferences, error) {
if userID == userTeamMember {
return mm_model.Preferences{{
UserId: userTeamMember,
Category: "focalboard",
Name: "test",
Value: "test",
}}, nil
}
return nil, errTestStore
}
func (s *PluginTestStore) GetUsersByTeam(teamID string, asGuestID string, showEmail, showName bool) ([]*model.User, error) {
if asGuestID == "guest" {
return []*model.User{
s.users["viewer"],
s.users["commenter"],
s.users["editor"],
s.users["admin"],
s.users["guest"],
}, nil
}
switch {
case teamID == s.testTeam.ID:
return []*model.User{
s.users["team-member"],
s.users["viewer"],
s.users["commenter"],
s.users["editor"],
s.users["admin"],
s.users["guest"],
}, nil
case teamID == s.otherTeam.ID:
return []*model.User{
s.users["team-member"],
s.users["viewer"],
s.users["commenter"],
s.users["editor"],
s.users["admin"],
}, nil
case teamID == s.emptyTeam.ID:
return []*model.User{}, nil
}
return nil, errTestStore
}
func (s *PluginTestStore) SearchUsersByTeam(teamID string, searchQuery string, asGuestID string, excludeBots bool, showEmail, showName bool) ([]*model.User, error) {
users := []*model.User{}
teamUsers, err := s.GetUsersByTeam(teamID, asGuestID, showEmail, showName)
if err != nil {
return nil, err
}
for _, user := range teamUsers {
if excludeBots && user.IsBot {
continue
}
if strings.Contains(user.Username, searchQuery) {
users = append(users, user)
}
}
return users, nil
}
func (s *PluginTestStore) CanSeeUser(seerID string, seenID string) (bool, error) {
user, err := s.GetUserByID(seerID)
if err != nil {
return false, err
}
if !user.IsGuest {
return true, nil
}
seerMembers, err := s.GetMembersForUser(seerID)
if err != nil {
return false, err
}
seenMembers, err := s.GetMembersForUser(seenID)
if err != nil {
return false, err
}
for _, seerMember := range seerMembers {
for _, seenMember := range seenMembers {
if seerMember.BoardID == seenMember.BoardID {
return true, nil
}
}
}
return false, nil
}
func (s *PluginTestStore) SearchUserChannels(teamID, userID, query string) ([]*mm_model.Channel, error) {
return []*mm_model.Channel{
{
TeamId: teamID,
Id: "valid-channel-id",
DisplayName: "Valid Channel",
Name: "valid-channel",
},
{
TeamId: teamID,
Id: "valid-channel-id-2",
DisplayName: "Valid Channel 2",
Name: "valid-channel-2",
},
}, nil
}
func (s *PluginTestStore) GetChannel(teamID, channel string) (*mm_model.Channel, error) {
if channel == "valid-channel-id" {
return &mm_model.Channel{
TeamId: teamID,
Id: "valid-channel-id",
DisplayName: "Valid Channel",
Name: "valid-channel",
}, nil
} else if channel == "valid-channel-id-2" {
return &mm_model.Channel{
TeamId: teamID,
Id: "valid-channel-id-2",
DisplayName: "Valid Channel 2",
Name: "valid-channel-2",
}, nil
}
return nil, errTestStore
}
func (s *PluginTestStore) SearchBoardsForUser(term string, field model.BoardSearchField, userID string, includePublicBoards bool) ([]*model.Board, error) {
boards, err := s.Store.SearchBoardsForUser(term, field, userID, includePublicBoards)
if err != nil {
return nil, err
}
teams, err := s.GetTeamsForUser(userID)
if err != nil {
return nil, err
}
resultBoards := []*model.Board{}
for _, board := range boards {
for _, team := range teams {
if team.ID == board.TeamID {
resultBoards = append(resultBoards, board)
break
}
}
}
return resultBoards, nil
}
func (s *PluginTestStore) GetLicense() *mm_model.License {
license := s.Store.GetLicense()
if license == nil {
license = &mm_model.License{
Id: mm_model.NewId(),
StartsAt: mm_model.GetMillis() - 2629746000, // 1 month
ExpiresAt: mm_model.GetMillis() + 2629746000, //
IssuedAt: mm_model.GetMillis() - 2629746000,
Features: &mm_model.Features{},
}
license.Features.SetDefaults()
}
complianceLicense := os.Getenv("FOCALBOARD_UNIT_TESTING_COMPLIANCE")
if complianceLicense != "" {
if val, err := strconv.ParseBool(complianceLicense); err == nil {
license.Features.Compliance = mm_model.NewBool(val)
}
}
return license
}

Просмотреть файл

@@ -0,0 +1,98 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package integrationtests
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/v6/server/boards/model"
"github.com/mattermost/mattermost-server/v6/server/boards/utils"
)
func TestSharing(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
var boardID string
token := utils.NewID(utils.IDTypeToken)
t.Run("an unauthenticated client should not be able to get a sharing", func(t *testing.T) {
th.Logout(th.Client)
sharing, resp := th.Client.GetSharing("board-id")
th.CheckUnauthorized(resp)
require.Nil(t, sharing)
})
t.Run("Check no initial sharing", func(t *testing.T) {
th.Login1()
teamID := "0"
newBoard := &model.Board{
TeamID: teamID,
Type: model.BoardTypeOpen,
}
board, err := th.Server.App().CreateBoard(newBoard, th.GetUser1().ID, true)
require.NoError(t, err)
require.NotNil(t, board)
boardID = board.ID
s, err := th.Server.App().GetSharing(boardID)
require.Error(t, err)
require.True(t, model.IsErrNotFound(err))
require.Nil(t, s)
sharing, resp := th.Client.GetSharing(boardID)
th.CheckNotFound(resp)
require.Nil(t, sharing)
})
t.Run("POST sharing, config = false", func(t *testing.T) {
sharing := model.Sharing{
ID: boardID,
Token: token,
Enabled: true,
UpdateAt: 1,
}
// it will fail with default config
success, resp := th.Client.PostSharing(&sharing)
require.False(t, success)
require.Error(t, resp.Error)
t.Run("GET sharing", func(t *testing.T) {
sharing, resp := th.Client.GetSharing(boardID)
// Expect empty sharing object
th.CheckNotFound(resp)
require.Nil(t, sharing)
})
})
t.Run("POST sharing, config = true", func(t *testing.T) {
th.Server.Config().EnablePublicSharedBoards = true
sharing := model.Sharing{
ID: boardID,
Token: token,
Enabled: true,
UpdateAt: 1,
}
// it will succeed with updated config
success, resp := th.Client.PostSharing(&sharing)
require.True(t, success)
require.NoError(t, resp.Error)
t.Run("GET sharing", func(t *testing.T) {
sharing, resp := th.Client.GetSharing(boardID)
require.NoError(t, resp.Error)
require.NotNil(t, sharing)
require.Equal(t, sharing.ID, boardID)
require.True(t, sharing.Enabled)
require.Equal(t, sharing.Token, token)
})
})
}

Просмотреть файл

@@ -0,0 +1,102 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package integrationtests
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/v6/server/boards/model"
)
func TestSidebar(t *testing.T) {
th := SetupTestHelperWithToken(t).Start()
defer th.TearDown()
// we'll create a new board.
// The board should end up in a default "Boards" category
board := th.CreateBoard("team-id", "O")
categoryBoards := th.GetUserCategoryBoards("team-id")
require.Equal(t, 1, len(categoryBoards))
require.Equal(t, "Boards", categoryBoards[0].Name)
require.Equal(t, 1, len(categoryBoards[0].BoardMetadata))
require.Equal(t, board.ID, categoryBoards[0].BoardMetadata[0].BoardID)
// create a new category, a new board
// and move that board into the new category
board2 := th.CreateBoard("team-id", "O")
category := th.CreateCategory(model.Category{
Name: "Category 2",
TeamID: "team-id",
UserID: "single-user",
})
th.UpdateCategoryBoard("team-id", category.ID, board2.ID)
categoryBoards = th.GetUserCategoryBoards("team-id")
// now there should be two categories - boards and the one
// we created just now
require.Equal(t, 2, len(categoryBoards))
// the newly created category should be the first one array
// as new categories end up on top in LHS
require.Equal(t, "Category 2", categoryBoards[0].Name)
require.Equal(t, 1, len(categoryBoards[0].BoardMetadata))
require.Equal(t, board2.ID, categoryBoards[0].BoardMetadata[0].BoardID)
// now we'll delete the custom category we created, "Category 2"
// and all it's boards should get moved to the Boards category
th.DeleteCategory("team-id", category.ID)
categoryBoards = th.GetUserCategoryBoards("team-id")
require.Equal(t, 1, len(categoryBoards))
require.Equal(t, "Boards", categoryBoards[0].Name)
require.Equal(t, 2, len(categoryBoards[0].BoardMetadata))
require.Contains(t, categoryBoards[0].BoardMetadata, model.CategoryBoardMetadata{BoardID: board.ID, Hidden: false})
require.Contains(t, categoryBoards[0].BoardMetadata, model.CategoryBoardMetadata{BoardID: board2.ID, Hidden: false})
}
func TestHideUnhideBoard(t *testing.T) {
th := SetupTestHelperWithToken(t).Start()
defer th.TearDown()
// we'll create a new board.
// The board should end up in a default "Boards" category
th.CreateBoard("team-id", "O")
// the created board should not be hidden
categoryBoards := th.GetUserCategoryBoards("team-id")
require.Equal(t, 1, len(categoryBoards))
require.Equal(t, "Boards", categoryBoards[0].Name)
require.Equal(t, 1, len(categoryBoards[0].BoardMetadata))
require.False(t, categoryBoards[0].BoardMetadata[0].Hidden)
// now we'll hide the board
response := th.Client.HideBoard("team-id", categoryBoards[0].ID, categoryBoards[0].BoardMetadata[0].BoardID)
th.CheckOK(response)
// verifying if the board has been marked as hidden
categoryBoards = th.GetUserCategoryBoards("team-id")
require.True(t, categoryBoards[0].BoardMetadata[0].Hidden)
// trying to hide the already hidden board.This should have no effect
response = th.Client.HideBoard("team-id", categoryBoards[0].ID, categoryBoards[0].BoardMetadata[0].BoardID)
th.CheckOK(response)
categoryBoards = th.GetUserCategoryBoards("team-id")
require.True(t, categoryBoards[0].BoardMetadata[0].Hidden)
// now we'll unhide the board
response = th.Client.UnhideBoard("team-id", categoryBoards[0].ID, categoryBoards[0].BoardMetadata[0].BoardID)
th.CheckOK(response)
// verifying
categoryBoards = th.GetUserCategoryBoards("team-id")
require.False(t, categoryBoards[0].BoardMetadata[0].Hidden)
// trying to unhide the already visible board.This should have no effect
response = th.Client.UnhideBoard("team-id", categoryBoards[0].ID, categoryBoards[0].BoardMetadata[0].BoardID)
th.CheckOK(response)
categoryBoards = th.GetUserCategoryBoards("team-id")
require.False(t, categoryBoards[0].BoardMetadata[0].Hidden)
}

Просмотреть файл

@@ -0,0 +1,59 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package integrationtests
import (
"testing"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/v6/server/boards/client"
"github.com/mattermost/mattermost-server/v6/server/boards/model"
)
func TestStatisticsLocalMode(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
t.Run("an unauthenticated client should not be able to get statistics", func(t *testing.T) {
th.Logout(th.Client)
stats, resp := th.Client.GetStatistics()
th.CheckUnauthorized(resp)
require.Nil(t, stats)
})
t.Run("Check authenticated user, not admin", func(t *testing.T) {
th.Login1()
stats, resp := th.Client.GetStatistics()
th.CheckNotImplemented(resp)
require.Nil(t, stats)
})
}
func TestStatisticsPluginMode(t *testing.T) {
th := SetupTestHelperPluginMode(t)
defer th.TearDown()
// Permissions are tested in permissions_test.go
// This tests the functionality.
t.Run("Check authenticated user, admin", func(t *testing.T) {
th.Client = client.NewClient(th.Server.Config().ServerRoot, "")
th.Client.HTTPHeader["Mattermost-User-Id"] = userAdmin
stats, resp := th.Client.GetStatistics()
th.CheckOK(resp)
require.NotNil(t, stats)
numberCards := 2
th.CreateBoardAndCards("testTeam", model.BoardTypeOpen, numberCards)
stats, resp = th.Client.GetStatistics()
th.CheckOK(resp)
require.NotNil(t, stats)
require.Equal(t, 1, stats.Boards)
require.Equal(t, numberCards, stats.Cards)
})
}

Просмотреть файл

@@ -0,0 +1,156 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package integrationtests
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/v6/server/boards/client"
"github.com/mattermost/mattermost-server/v6/server/boards/model"
"github.com/mattermost/mattermost-server/v6/server/boards/utils"
)
func createTestSubscriptions(client *client.Client, num int) ([]*model.Subscription, string, error) {
newSubs := make([]*model.Subscription, 0, num)
user, resp := client.GetMe()
if resp.Error != nil {
return nil, "", fmt.Errorf("cannot get current user: %w", resp.Error)
}
board := &model.Board{
TeamID: "0",
Type: model.BoardTypeOpen,
CreateAt: 1,
UpdateAt: 1,
}
board, resp = client.CreateBoard(board)
if resp.Error != nil {
return nil, "", fmt.Errorf("cannot insert test board block: %w", resp.Error)
}
for n := 0; n < num; n++ {
newBlock := &model.Block{
ID: utils.NewID(utils.IDTypeCard),
BoardID: board.ID,
CreateAt: 1,
UpdateAt: 1,
Type: model.TypeCard,
}
newBlocks, resp := client.InsertBlocks(board.ID, []*model.Block{newBlock}, false)
if resp.Error != nil {
return nil, "", fmt.Errorf("cannot insert test card block: %w", resp.Error)
}
newBlock = newBlocks[0]
sub := &model.Subscription{
BlockType: newBlock.Type,
BlockID: newBlock.ID,
SubscriberType: model.SubTypeUser,
SubscriberID: user.ID,
}
subNew, resp := client.CreateSubscription(sub)
if resp.Error != nil {
return nil, "", resp.Error
}
newSubs = append(newSubs, subNew)
}
return newSubs, user.ID, nil
}
func TestCreateSubscription(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
t.Run("Create valid subscription", func(t *testing.T) {
subs, userID, err := createTestSubscriptions(th.Client, 5)
require.NoError(t, err)
require.Len(t, subs, 5)
// fetch the newly created subscriptions and compare
subsFound, resp := th.Client.GetSubscriptions(userID)
require.NoError(t, resp.Error)
require.Len(t, subsFound, 5)
assert.ElementsMatch(t, subs, subsFound)
})
t.Run("Create invalid subscription", func(t *testing.T) {
user, resp := th.Client.GetMe()
require.NoError(t, resp.Error)
sub := &model.Subscription{
SubscriberID: user.ID,
}
_, resp = th.Client.CreateSubscription(sub)
require.Error(t, resp.Error)
})
t.Run("Create subscription for another user", func(t *testing.T) {
sub := &model.Subscription{
SubscriberID: utils.NewID(utils.IDTypeUser),
}
_, resp := th.Client.CreateSubscription(sub)
require.Error(t, resp.Error)
})
}
func TestGetSubscriptions(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
t.Run("Get subscriptions for user", func(t *testing.T) {
mySubs, user1ID, err := createTestSubscriptions(th.Client, 5)
require.NoError(t, err)
require.Len(t, mySubs, 5)
// create more subscriptions with different user
otherSubs, _, err := createTestSubscriptions(th.Client2, 10)
require.NoError(t, err)
require.Len(t, otherSubs, 10)
// fetch the newly created subscriptions for current user, making sure only
// the ones created for the current user are returned.
subsFound, resp := th.Client.GetSubscriptions(user1ID)
require.NoError(t, resp.Error)
require.Len(t, subsFound, 5)
assert.ElementsMatch(t, mySubs, subsFound)
})
}
func TestDeleteSubscription(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
t.Run("Delete valid subscription", func(t *testing.T) {
subs, userID, err := createTestSubscriptions(th.Client, 3)
require.NoError(t, err)
require.Len(t, subs, 3)
resp := th.Client.DeleteSubscription(subs[1].BlockID, userID)
require.NoError(t, resp.Error)
// fetch the subscriptions and ensure the list is correct
subsFound, resp := th.Client.GetSubscriptions(userID)
require.NoError(t, resp.Error)
require.Len(t, subsFound, 2)
assert.Contains(t, subsFound, subs[0])
assert.Contains(t, subsFound, subs[2])
assert.NotContains(t, subsFound, subs[1])
})
t.Run("Delete invalid subscription", func(t *testing.T) {
user, resp := th.Client.GetMe()
require.NoError(t, resp.Error)
resp = th.Client.DeleteSubscription("bogus", user.ID)
require.Error(t, resp.Error)
})
}

113
server/boards/integrationtests/teststore.go Обычный файл
Просмотреть файл

@@ -0,0 +1,113 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package integrationtests
import (
"github.com/mattermost/mattermost-server/v6/server/boards/services/store"
mm_model "github.com/mattermost/mattermost-server/v6/model"
)
type TestStore struct {
store.Store
license *mm_model.License
}
func NewTestEnterpriseStore(store store.Store) *TestStore {
usersValue := 10000
trueValue := true
falseValue := false
license := &mm_model.License{
Features: &mm_model.Features{
Users: &usersValue,
LDAP: &trueValue,
LDAPGroups: &trueValue,
MFA: &trueValue,
GoogleOAuth: &trueValue,
Office365OAuth: &trueValue,
OpenId: &trueValue,
Compliance: &trueValue,
Cluster: &trueValue,
Metrics: &trueValue,
MHPNS: &trueValue,
SAML: &trueValue,
Elasticsearch: &trueValue,
Announcement: &trueValue,
ThemeManagement: &trueValue,
EmailNotificationContents: &trueValue,
DataRetention: &trueValue,
MessageExport: &trueValue,
CustomPermissionsSchemes: &trueValue,
CustomTermsOfService: &trueValue,
GuestAccounts: &trueValue,
GuestAccountsPermissions: &trueValue,
IDLoadedPushNotifications: &trueValue,
LockTeammateNameDisplay: &trueValue,
EnterprisePlugins: &trueValue,
AdvancedLogging: &trueValue,
Cloud: &falseValue,
SharedChannels: &trueValue,
RemoteClusterService: &trueValue,
FutureFeatures: &trueValue,
},
}
testStore := &TestStore{
Store: store,
license: license,
}
return testStore
}
func NewTestProfessionalStore(store store.Store) *TestStore {
usersValue := 10000
trueValue := true
falseValue := false
license := &mm_model.License{
Features: &mm_model.Features{
Users: &usersValue,
LDAP: &falseValue,
LDAPGroups: &falseValue,
MFA: &trueValue,
GoogleOAuth: &trueValue,
Office365OAuth: &trueValue,
OpenId: &trueValue,
Compliance: &falseValue,
Cluster: &falseValue,
Metrics: &trueValue,
MHPNS: &trueValue,
SAML: &trueValue,
Elasticsearch: &trueValue,
Announcement: &trueValue,
ThemeManagement: &trueValue,
EmailNotificationContents: &trueValue,
DataRetention: &trueValue,
MessageExport: &trueValue,
CustomPermissionsSchemes: &trueValue,
CustomTermsOfService: &trueValue,
GuestAccounts: &trueValue,
GuestAccountsPermissions: &trueValue,
IDLoadedPushNotifications: &trueValue,
LockTeammateNameDisplay: &trueValue,
EnterprisePlugins: &falseValue,
AdvancedLogging: &trueValue,
Cloud: &falseValue,
SharedChannels: &trueValue,
RemoteClusterService: &falseValue,
FutureFeatures: &trueValue,
},
}
testStore := &TestStore{
Store: store,
license: license,
}
return testStore
}
func (s *TestStore) GetLicense() *mm_model.License {
return s.license
}

271
server/boards/integrationtests/user_test.go Обычный файл
Просмотреть файл

@@ -0,0 +1,271 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package integrationtests
import (
"bytes"
"crypto/rand"
"testing"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/v6/server/boards/model"
"github.com/mattermost/mattermost-server/v6/server/boards/utils"
)
const (
fakeUsername = "fakeUsername"
fakeEmail = "mock@test.com"
)
func TestUserRegister(t *testing.T) {
th := SetupTestHelper(t).Start()
defer th.TearDown()
// register
registerRequest := &model.RegisterRequest{
Username: fakeUsername,
Email: fakeEmail,
Password: utils.NewID(utils.IDTypeNone),
}
success, resp := th.Client.Register(registerRequest)
require.NoError(t, resp.Error)
require.True(t, success)
// register again will fail
success, resp = th.Client.Register(registerRequest)
require.Error(t, resp.Error)
require.False(t, success)
}
func TestUserLogin(t *testing.T) {
th := SetupTestHelper(t).Start()
defer th.TearDown()
t.Run("with nonexist user", func(t *testing.T) {
loginRequest := &model.LoginRequest{
Type: "normal",
Username: "nonexistuser",
Email: "",
Password: utils.NewID(utils.IDTypeNone),
}
data, resp := th.Client.Login(loginRequest)
require.Error(t, resp.Error)
require.Nil(t, data)
})
t.Run("with registered user", func(t *testing.T) {
password := utils.NewID(utils.IDTypeNone)
// register
registerRequest := &model.RegisterRequest{
Username: fakeUsername,
Email: fakeEmail,
Password: password,
}
success, resp := th.Client.Register(registerRequest)
require.NoError(t, resp.Error)
require.True(t, success)
// login
loginRequest := &model.LoginRequest{
Type: "normal",
Username: fakeUsername,
Email: fakeEmail,
Password: password,
}
data, resp := th.Client.Login(loginRequest)
require.NoError(t, resp.Error)
require.NotNil(t, data)
require.NotNil(t, data.Token)
})
}
func TestGetMe(t *testing.T) {
th := SetupTestHelper(t).Start()
defer th.TearDown()
t.Run("not login yet", func(t *testing.T) {
me, resp := th.Client.GetMe()
require.Error(t, resp.Error)
require.Nil(t, me)
})
t.Run("logged in", func(t *testing.T) {
// register
password := utils.NewID(utils.IDTypeNone)
registerRequest := &model.RegisterRequest{
Username: fakeUsername,
Email: fakeEmail,
Password: password,
}
success, resp := th.Client.Register(registerRequest)
require.NoError(t, resp.Error)
require.True(t, success)
// login
loginRequest := &model.LoginRequest{
Type: "normal",
Username: fakeUsername,
Email: fakeEmail,
Password: password,
}
data, resp := th.Client.Login(loginRequest)
require.NoError(t, resp.Error)
require.NotNil(t, data)
require.NotNil(t, data.Token)
// get user me
me, resp := th.Client.GetMe()
require.NoError(t, resp.Error)
require.NotNil(t, me)
require.Equal(t, "", me.Email)
require.Equal(t, registerRequest.Username, me.Username)
})
}
func TestGetUser(t *testing.T) {
th := SetupTestHelper(t).Start()
defer th.TearDown()
// register
password := utils.NewID(utils.IDTypeNone)
registerRequest := &model.RegisterRequest{
Username: fakeUsername,
Email: fakeEmail,
Password: password,
}
success, resp := th.Client.Register(registerRequest)
require.NoError(t, resp.Error)
require.True(t, success)
// login
loginRequest := &model.LoginRequest{
Type: "normal",
Username: fakeUsername,
Email: fakeEmail,
Password: password,
}
data, resp := th.Client.Login(loginRequest)
require.NoError(t, resp.Error)
require.NotNil(t, data)
require.NotNil(t, data.Token)
me, resp := th.Client.GetMe()
require.NoError(t, resp.Error)
require.NotNil(t, me)
t.Run("me's id", func(t *testing.T) {
user, resp := th.Client.GetUser(me.ID)
require.NoError(t, resp.Error)
require.NotNil(t, user)
require.Equal(t, me.ID, user.ID)
require.Equal(t, me.Username, user.Username)
})
t.Run("nonexist user", func(t *testing.T) {
user, resp := th.Client.GetUser("nonexistid")
require.Error(t, resp.Error)
require.Nil(t, user)
})
}
func TestUserChangePassword(t *testing.T) {
th := SetupTestHelper(t).Start()
defer th.TearDown()
// register
password := utils.NewID(utils.IDTypeNone)
registerRequest := &model.RegisterRequest{
Username: fakeUsername,
Email: fakeEmail,
Password: password,
}
success, resp := th.Client.Register(registerRequest)
require.NoError(t, resp.Error)
require.True(t, success)
// login
loginRequest := &model.LoginRequest{
Type: "normal",
Username: fakeUsername,
Email: fakeEmail,
Password: password,
}
data, resp := th.Client.Login(loginRequest)
require.NoError(t, resp.Error)
require.NotNil(t, data)
require.NotNil(t, data.Token)
originalMe, resp := th.Client.GetMe()
require.NoError(t, resp.Error)
require.NotNil(t, originalMe)
// change password
success, resp = th.Client.UserChangePassword(originalMe.ID, &model.ChangePasswordRequest{
OldPassword: password,
NewPassword: utils.NewID(utils.IDTypeNone),
})
require.NoError(t, resp.Error)
require.True(t, success)
}
func randomBytes(t *testing.T, n int) []byte {
bb := make([]byte, n)
_, err := rand.Read(bb)
require.NoError(t, err)
return bb
}
func TestTeamUploadFile(t *testing.T) {
t.Run("no permission", func(t *testing.T) { // native auth, but not login
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
teamID := "0"
boardID := utils.NewID(utils.IDTypeBoard)
data := randomBytes(t, 1024)
result, resp := th.Client.TeamUploadFile(teamID, boardID, bytes.NewReader(data))
require.Error(t, resp.Error)
require.Nil(t, result)
})
t.Run("a board admin should be able to update a file", func(t *testing.T) { // single token auth
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
teamID := "0"
newBoard := &model.Board{
Type: model.BoardTypeOpen,
TeamID: teamID,
}
board, resp := th.Client.CreateBoard(newBoard)
th.CheckOK(resp)
require.NotNil(t, board)
data := randomBytes(t, 1024)
result, resp := th.Client.TeamUploadFile(teamID, board.ID, bytes.NewReader(data))
th.CheckOK(resp)
require.NotNil(t, result)
require.NotEmpty(t, result.FileID)
// TODO get the uploaded file
})
t.Run("user that doesn't belong to the board should not be able to upload a file", func(t *testing.T) {
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
teamID := "0"
newBoard := &model.Board{
Type: model.BoardTypeOpen,
TeamID: teamID,
}
board, resp := th.Client.CreateBoard(newBoard)
th.CheckOK(resp)
require.NotNil(t, board)
data := randomBytes(t, 1024)
// a user that doesn't belong to the board tries to upload the file
result, resp := th.Client2.TeamUploadFile(teamID, board.ID, bytes.NewReader(data))
th.CheckForbidden(resp)
require.Nil(t, result)
})
}

Просмотреть файл

@@ -0,0 +1,60 @@
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
package integrationtests
import (
"testing"
"github.com/stretchr/testify/require"
)
// This test is there to guarantee that the board templates needed for
// the work template are present in the default templates.
// If this fails, you might need to sync with the channels team.
func TestGetTemplatesForWorkTemplate(t *testing.T) {
// map[name]trackingTemplateId
knownInWorkTemplates := map[string]string{
"Company Goals & OKRs": "7ba22ccfdfac391d63dea5c4b8cde0de",
"Competitive Analysis": "06f4bff367a7c2126fab2380c9dec23c",
"Content Calendar": "c75fbd659d2258b5183af2236d176ab4",
"Meeting Agenda ": "54fcf9c610f0ac5e4c522c0657c90602",
"Personal Goals ": "7f32dc8d2ae008cfe56554e9363505cc",
"Personal Tasls ": "dfb70c146a4584b8a21837477c7b5431",
"Project Tasks ": "a4ec399ab4f2088b1051c3cdf1dde4c3",
"Roadmap ": "b728c6ca730e2cfc229741c5a4712b65",
"Sales Pipeline CRM": "ecc250bb7dff0fe02247f1110f097544",
"Sprint Planner ": "99b74e26d2f5d0a9b346d43c0a7bfb09",
"Team Retrospective": "e4f03181c4ced8edd4d53d33d569a086",
"User Research Sessions": "6c345c7f50f6833f78b7d0f08ce450a3",
}
th := SetupTestHelper(t).InitBasic()
defer th.TearDown()
err := th.Server.App().InitTemplates()
require.NoError(t, err, "InitTemplates should not fail")
rBoards, resp := th.Client.GetTemplatesForTeam("0")
th.CheckOK(resp)
require.NotNil(t, rBoards)
trackingTemplateIDs := []string{}
for _, board := range rBoards {
property, _ := board.GetPropertyString("trackingTemplateId")
if property != "" {
trackingTemplateIDs = append(trackingTemplateIDs, property)
}
}
// make sure all known templates are in trackingTemplateIds
for name, ttID := range knownInWorkTemplates {
found := false
for _, trackingTemplateID := range trackingTemplateIDs {
if trackingTemplateID == ttID {
found = true
break
}
}
require.True(t, found, "trackingTemplateId %s for %s not found", ttID, name)
}
}