2022-03-31 20:04:20 +02:00
package app
import (
"bytes"
"testing"
2022-10-26 13:08:03 +02:00
"github.com/mattermost/focalboard/server/utils"
2022-03-31 20:04:20 +02:00
"github.com/golang/mock/gomock"
"github.com/mattermost/focalboard/server/model"
"github.com/stretchr/testify/require"
)
func TestApp_ImportArchive ( t * testing . T ) {
th , tearDown := SetupTestHelper ( t )
defer tearDown ( )
board := & model . Board {
ID : "d14b9df9-1f31-4732-8a64-92bc7162cd28" ,
TeamID : "test-team" ,
Title : "Cross-Functional Project Plan" ,
}
2022-10-25 22:46:43 +02:00
block := & model . Block {
2022-03-31 20:04:20 +02:00
ID : "2c1873e0-1484-407d-8b2c-3c3b5a2a9f9e" ,
ParentID : board . ID ,
Type : model . TypeView ,
BoardID : board . ID ,
}
babs := & model . BoardsAndBlocks {
Boards : [ ] * model . Board { board } ,
2022-10-25 22:46:43 +02:00
Blocks : [ ] * model . Block { block } ,
2022-03-31 20:04:20 +02:00
}
boardMember := & model . BoardMember {
BoardID : board . ID ,
UserID : "user" ,
}
t . Run ( "import asana archive" , func ( t * testing . T ) {
r := bytes . NewReader ( [ ] byte ( asana ) )
opts := model . ImportArchiveOptions {
TeamID : "test-team" ,
ModifiedBy : "user" ,
}
th . Store . EXPECT ( ) . CreateBoardsAndBlocks ( gomock . AssignableToTypeOf ( & model . BoardsAndBlocks { } ) , "user" ) . Return ( babs , nil )
th . Store . EXPECT ( ) . GetMembersForBoard ( board . ID ) . AnyTimes ( ) . Return ( [ ] * model . BoardMember { boardMember } , nil )
2023-02-02 00:29:46 +02:00
th . Store . EXPECT ( ) . GetBoard ( board . ID ) . Return ( board , nil )
th . Store . EXPECT ( ) . GetMemberForBoard ( board . ID , "user" ) . Return ( boardMember , nil )
2023-01-24 12:11:54 +02:00
th . Store . EXPECT ( ) . GetUserCategoryBoards ( "user" , "test-team" ) . Return ( [ ] model . CategoryBoards {
{
Category : model . Category {
Type : "default" ,
Name : "Boards" ,
ID : "boards_category_id" ,
} ,
} ,
} , nil )
2022-10-26 13:08:03 +02:00
th . Store . EXPECT ( ) . GetUserCategoryBoards ( "user" , "test-team" )
th . Store . EXPECT ( ) . CreateCategory ( utils . Anything ) . Return ( nil )
th . Store . EXPECT ( ) . GetCategory ( utils . Anything ) . Return ( & model . Category {
ID : "boards_category_id" ,
Name : "Boards" ,
} , nil )
2022-12-14 10:51:53 +02:00
th . Store . EXPECT ( ) . GetBoardsForUserAndTeam ( "user" , "test-team" , false ) . Return ( [ ] * model . Board { } , nil )
2022-11-24 11:30:06 +02:00
th . Store . EXPECT ( ) . GetMembersForUser ( "user" ) . Return ( [ ] * model . BoardMember { } , nil )
2023-01-24 12:11:54 +02:00
th . Store . EXPECT ( ) . AddUpdateCategoryBoard ( "user" , utils . Anything , utils . Anything ) . Return ( nil )
2022-03-31 20:04:20 +02:00
err := th . App . ImportArchive ( r , opts )
require . NoError ( t , err , "import archive should not fail" )
} )
2023-01-19 05:22:14 +02:00
t . Run ( "import board archive" , func ( t * testing . T ) {
r := bytes . NewReader ( [ ] byte ( boardArchive ) )
opts := model . ImportArchiveOptions {
TeamID : "test-team" ,
ModifiedBy : "f1tydgc697fcbp8ampr6881jea" ,
}
bm1 := & model . BoardMember {
BoardID : board . ID ,
UserID : "f1tydgc697fcbp8ampr6881jea" ,
}
bm2 := & model . BoardMember {
BoardID : board . ID ,
UserID : "hxxzooc3ff8cubsgtcmpn8733e" ,
}
bm3 := & model . BoardMember {
BoardID : board . ID ,
UserID : "nto73edn5ir6ifimo5a53y1dwa" ,
}
user1 := & model . User {
ID : "f1tydgc697fcbp8ampr6881jea" ,
}
user2 := & model . User {
ID : "hxxzooc3ff8cubsgtcmpn8733e" ,
}
user3 := & model . User {
ID : "nto73edn5ir6ifimo5a53y1dwa" ,
}
th . Store . EXPECT ( ) . CreateBoardsAndBlocks ( gomock . AssignableToTypeOf ( & model . BoardsAndBlocks { } ) , "f1tydgc697fcbp8ampr6881jea" ) . Return ( babs , nil )
th . Store . EXPECT ( ) . GetMembersForBoard ( board . ID ) . AnyTimes ( ) . Return ( [ ] * model . BoardMember { bm1 , bm2 , bm3 } , nil )
2023-01-24 12:11:54 +02:00
th . Store . EXPECT ( ) . GetUserCategoryBoards ( "f1tydgc697fcbp8ampr6881jea" , "test-team" ) . Return ( [ ] model . CategoryBoards { } , nil )
th . Store . EXPECT ( ) . GetUserCategoryBoards ( "f1tydgc697fcbp8ampr6881jea" , "test-team" ) . Return ( [ ] model . CategoryBoards {
{
Category : model . Category {
ID : "boards_category_id" ,
Name : "Boards" ,
Type : model . CategoryTypeSystem ,
} ,
} ,
} , nil )
2023-01-19 05:22:14 +02:00
th . Store . EXPECT ( ) . CreateCategory ( utils . Anything ) . Return ( nil )
th . Store . EXPECT ( ) . GetCategory ( utils . Anything ) . Return ( & model . Category {
ID : "boards_category_id" ,
Name : "Boards" ,
} , nil )
th . Store . EXPECT ( ) . GetMembersForUser ( "f1tydgc697fcbp8ampr6881jea" ) . Return ( [ ] * model . BoardMember { } , nil )
th . Store . EXPECT ( ) . GetBoardsForUserAndTeam ( "f1tydgc697fcbp8ampr6881jea" , "test-team" , false ) . Return ( [ ] * model . Board { } , nil )
2023-01-24 12:11:54 +02:00
th . Store . EXPECT ( ) . AddUpdateCategoryBoard ( "f1tydgc697fcbp8ampr6881jea" , utils . Anything , utils . Anything ) . Return ( nil )
2023-01-19 05:22:14 +02:00
th . Store . EXPECT ( ) . GetBoard ( board . ID ) . AnyTimes ( ) . Return ( board , nil )
th . Store . EXPECT ( ) . GetMemberForBoard ( board . ID , "f1tydgc697fcbp8ampr6881jea" ) . AnyTimes ( ) . Return ( bm1 , nil )
th . Store . EXPECT ( ) . GetMemberForBoard ( board . ID , "hxxzooc3ff8cubsgtcmpn8733e" ) . AnyTimes ( ) . Return ( bm2 , nil )
th . Store . EXPECT ( ) . GetMemberForBoard ( board . ID , "nto73edn5ir6ifimo5a53y1dwa" ) . AnyTimes ( ) . Return ( bm3 , nil )
th . Store . EXPECT ( ) . GetUserByID ( "f1tydgc697fcbp8ampr6881jea" ) . AnyTimes ( ) . Return ( user1 , nil )
th . Store . EXPECT ( ) . GetUserByID ( "hxxzooc3ff8cubsgtcmpn8733e" ) . AnyTimes ( ) . Return ( user2 , nil )
th . Store . EXPECT ( ) . GetUserByID ( "nto73edn5ir6ifimo5a53y1dwa" ) . AnyTimes ( ) . Return ( user3 , nil )
boardID , err := th . App . ImportBoardJSONL ( r , opts )
require . Equal ( t , board . ID , boardID , "Board ID should be same" )
require . NoError ( t , err , "import archive should not fail" )
} )
2022-03-31 20:04:20 +02:00
}
//nolint:lll
const asana = ` { "version" : 1 , "date" : 1614714686842 }
{ "type" : "block" , "data" : { "id" : "d14b9df9-1f31-4732-8a64-92bc7162cd28" , "fields" : { "icon" : "" , "description" : "" , "cardProperties" : [ { "id" : "3bdcbaeb-bc78-4884-8531-a0323b74676a" , "name" : "Section" , "type" : "select" , "options" : [ { "id" : "d8d94ef1-5e74-40bb-8be5-fc0eb3f47732" , "value" : "Planning" , "color" : "propColorGray" } , { "id" : "454559bb-b788-4ff6-873e-04def8491d2c" , "value" : "Milestones" , "color" : "propColorBrown" } , { "id" : "deaab476-c690-48df-828f-725b064dc476" , "value" : "Next steps" , "color" : "propColorOrange" } , { "id" : "2138305a-3157-461c-8bbe-f19ebb55846d" , "value" : "Comms Plan" , "color" : "propColorYellow" } ] } ] } , "createAt" : 1614714686836 , "updateAt" : 1614714686836 , "deleteAt" : 0 , "schema" : 1 , "parentId" : "" , "rootId" : "d14b9df9-1f31-4732-8a64-92bc7162cd28" , "modifiedBy" : "" , "type" : "board" , "title" : "Cross-Functional Project Plan" } }
{ "type" : "block" , "data" : { "id" : "2c1873e0-1484-407d-8b2c-3c3b5a2a9f9e" , "fields" : { "sortOptions" : [ ] , "visiblePropertyIds" : [ ] , "visibleOptionIds" : [ ] , "hiddenOptionIds" : [ ] , "filter" : { "operation" : "and" , "filters" : [ ] } , "cardOrder" : [ ] , "columnWidths" : { } , "viewType" : "board" } , "createAt" : 1614714686840 , "updateAt" : 1614714686840 , "deleteAt" : 0 , "schema" : 1 , "parentId" : "d14b9df9-1f31-4732-8a64-92bc7162cd28" , "rootId" : "d14b9df9-1f31-4732-8a64-92bc7162cd28" , "modifiedBy" : "" , "type" : "view" , "title" : "Board View" } }
{ "type" : "block" , "data" : { "id" : "520c332b-adf5-4a32-88ab-43655c8b6aa2" , "fields" : { "icon" : "" , "properties" : { "3bdcbaeb-bc78-4884-8531-a0323b74676a" : "d8d94ef1-5e74-40bb-8be5-fc0eb3f47732" } , "contentOrder" : [ "deb3966c-6d56-43b1-8e95-36806877ce81" ] } , "createAt" : 1614714686841 , "updateAt" : 1614714686841 , "deleteAt" : 0 , "schema" : 1 , "parentId" : "d14b9df9-1f31-4732-8a64-92bc7162cd28" , "rootId" : "d14b9df9-1f31-4732-8a64-92bc7162cd28" , "modifiedBy" : "" , "type" : "card" , "title" : "[READ ME] - Instructions for using this template" } }
{ "type" : "block" , "data" : { "id" : "deb3966c-6d56-43b1-8e95-36806877ce81" , "fields" : { } , "createAt" : 1614714686841 , "updateAt" : 1614714686841 , "deleteAt" : 0 , "schema" : 1 , "parentId" : "520c332b-adf5-4a32-88ab-43655c8b6aa2" , "rootId" : "d14b9df9-1f31-4732-8a64-92bc7162cd28" , "modifiedBy" : "" , "type" : "text" , "title" : "This project template is set up in List View with sections and Asana-created Custom Fields to help you track your team's work. We've provided some example content in this template to get you started, but you should add tasks, change task names, add more Custom Fields, and change any other info to make this project your own.\n\nSend feedback about this template: https://asa.na/templatesfeedback" } }
{ "type" : "block" , "data" : { "id" : "be791f66-a5e5-4408-82f6-cb1280f5bc45" , "fields" : { "icon" : "" , "properties" : { "3bdcbaeb-bc78-4884-8531-a0323b74676a" : "d8d94ef1-5e74-40bb-8be5-fc0eb3f47732" } , "contentOrder" : [ "2688b31f-e7ff-4de1-87ae-d4b5570f8712" ] } , "createAt" : 1614714686841 , "updateAt" : 1614714686841 , "deleteAt" : 0 , "schema" : 1 , "parentId" : "d14b9df9-1f31-4732-8a64-92bc7162cd28" , "rootId" : "d14b9df9-1f31-4732-8a64-92bc7162cd28" , "modifiedBy" : "" , "type" : "card" , "title" : "Redesign the landing page of our website" } }
{ "type" : "block" , "data" : { "id" : "2688b31f-e7ff-4de1-87ae-d4b5570f8712" , "fields" : { } , "createAt" : 1614714686841 , "updateAt" : 1614714686841 , "deleteAt" : 0 , "schema" : 1 , "parentId" : "be791f66-a5e5-4408-82f6-cb1280f5bc45" , "rootId" : "d14b9df9-1f31-4732-8a64-92bc7162cd28" , "modifiedBy" : "" , "type" : "text" , "title" : "Redesign the landing page to focus on the main persona." } }
{ "type" : "block" , "data" : { "id" : "98f74948-1700-4a3c-8cc2-8bb632499def" , "fields" : { "icon" : "" , "properties" : { "3bdcbaeb-bc78-4884-8531-a0323b74676a" : "454559bb-b788-4ff6-873e-04def8491d2c" } , "contentOrder" : [ ] } , "createAt" : 1614714686841 , "updateAt" : 1614714686841 , "deleteAt" : 0 , "schema" : 1 , "parentId" : "d14b9df9-1f31-4732-8a64-92bc7162cd28" , "rootId" : "d14b9df9-1f31-4732-8a64-92bc7162cd28" , "modifiedBy" : "" , "type" : "card" , "title" : "[EXAMPLE TASK] Consider trying a new email marketing service" } }
{ "type" : "block" , "data" : { "id" : "142fba5d-05e6-4865-83d9-b3f54d9de96e" , "fields" : { "icon" : "" , "properties" : { "3bdcbaeb-bc78-4884-8531-a0323b74676a" : "454559bb-b788-4ff6-873e-04def8491d2c" } , "contentOrder" : [ ] } , "createAt" : 1614714686841 , "updateAt" : 1614714686841 , "deleteAt" : 0 , "schema" : 1 , "parentId" : "d14b9df9-1f31-4732-8a64-92bc7162cd28" , "rootId" : "d14b9df9-1f31-4732-8a64-92bc7162cd28" , "modifiedBy" : "" , "type" : "card" , "title" : "[EXAMPLE TASK] Budget finalization" } }
{ "type" : "block" , "data" : { "id" : "ca6670b1-b034-4e42-8971-c659b478b9e0" , "fields" : { "icon" : "" , "properties" : { "3bdcbaeb-bc78-4884-8531-a0323b74676a" : "deaab476-c690-48df-828f-725b064dc476" } , "contentOrder" : [ ] } , "createAt" : 1614714686841 , "updateAt" : 1614714686841 , "deleteAt" : 0 , "schema" : 1 , "parentId" : "d14b9df9-1f31-4732-8a64-92bc7162cd28" , "rootId" : "d14b9df9-1f31-4732-8a64-92bc7162cd28" , "modifiedBy" : "" , "type" : "card" , "title" : "[EXAMPLE TASK] Find a venue for the holiday party" } }
{ "type" : "block" , "data" : { "id" : "db1dd596-0999-4741-8b05-72ca8e438e31" , "fields" : { "icon" : "" , "properties" : { "3bdcbaeb-bc78-4884-8531-a0323b74676a" : "deaab476-c690-48df-828f-725b064dc476" } , "contentOrder" : [ ] } , "createAt" : 1614714686841 , "updateAt" : 1614714686841 , "deleteAt" : 0 , "schema" : 1 , "parentId" : "d14b9df9-1f31-4732-8a64-92bc7162cd28" , "rootId" : "d14b9df9-1f31-4732-8a64-92bc7162cd28" , "modifiedBy" : "" , "type" : "card" , "title" : "[EXAMPLE TASK] Approve campaign copy" } }
{ "type" : "block" , "data" : { "id" : "16861c05-f31f-46af-8429-80a87b5aa93a" , "fields" : { "icon" : "" , "properties" : { "3bdcbaeb-bc78-4884-8531-a0323b74676a" : "2138305a-3157-461c-8bbe-f19ebb55846d" } , "contentOrder" : [ ] } , "createAt" : 1614714686841 , "updateAt" : 1614714686841 , "deleteAt" : 0 , "schema" : 1 , "parentId" : "d14b9df9-1f31-4732-8a64-92bc7162cd28" , "rootId" : "d14b9df9-1f31-4732-8a64-92bc7162cd28" , "modifiedBy" : "" , "type" : "card" , "title" : "[EXAMPLE TASK] Send out updated attendee list" } }
`
2023-01-19 05:22:14 +02:00
//nolint:lll
const boardArchive = ` { "type" : "board" , "data" : { "id" : "bfoi6yy6pa3yzika53spj7pq9ee" , "teamId" : "wsmqbtwb5jb35jb3mtp85c8a9h" , "channelId" : "" , "createdBy" : "nto73edn5ir6ifimo5a53y1dwa" , "modifiedBy" : "nto73edn5ir6ifimo5a53y1dwa" , "type" : "P" , "minimumRole" : "" , "title" : "Custom" , "description" : "" , "icon" : "" , "showDescription" : false , "isTemplate" : false , "templateVersion" : 0 , "properties" : { } , "cardProperties" : [ { "id" : "aonihehbifijmx56aqzu3cc7w1r" , "name" : "Status" , "options" : [ ] , "type" : "select" } , { "id" : "aohjkzt769rxhtcz1o9xcoce5to" , "name" : "Person" , "options" : [ ] , "type" : "person" } ] , "createAt" : 1672750481591 , "updateAt" : 1672750481591 , "deleteAt" : 0 } }
{ "type" : "block" , "data" : { "id" : "ckpc3b1dp3pbw7bqntfryy9jbzo" , "parentId" : "bjaqxtbyqz3bu7pgyddpgpms74a" , "createdBy" : "nto73edn5ir6ifimo5a53y1dwa" , "modifiedBy" : "nto73edn5ir6ifimo5a53y1dwa" , "schema" : 1 , "type" : "card" , "title" : "Test" , "fields" : { "contentOrder" : [ ] , "icon" : "" , "isTemplate" : false , "properties" : { "aohjkzt769rxhtcz1o9xcoce5to" : "hxxzooc3ff8cubsgtcmpn8733e" } } , "createAt" : 1672750481612 , "updateAt" : 1672845003530 , "deleteAt" : 0 , "boardId" : "bfoi6yy6pa3yzika53spj7pq9ee" } }
{ "type" : "block" , "data" : { "id" : "v7tdajwpm47r3u8duedk89bhxar" , "parentId" : "bpypang3a3errqstj1agx9kuqay" , "createdBy" : "nto73edn5ir6ifimo5a53y1dwa" , "modifiedBy" : "nto73edn5ir6ifimo5a53y1dwa" , "schema" : 1 , "type" : "view" , "title" : "Board view" , "fields" : { "cardOrder" : [ "crsyw7tbr3pnjznok6ppngmmyya" , "c5titiemp4pgaxbs4jksgybbj4y" ] , "collapsedOptionIds" : [ ] , "columnCalculations" : { } , "columnWidths" : { } , "defaultTemplateId" : "" , "filter" : { "filters" : [ ] , "operation" : "and" } , "hiddenOptionIds" : [ ] , "kanbanCalculations" : { } , "sortOptions" : [ ] , "viewType" : "board" , "visibleOptionIds" : [ ] , "visiblePropertyIds" : [ "aohjkzt769rxhtcz1o9xcoce5to" ] } , "createAt" : 1672750481626 , "updateAt" : 1672750481626 , "deleteAt" : 0 , "boardId" : "bfoi6yy6pa3yzika53spj7pq9ee" } }
{ "type" : "boardMember" , "data" : { "boardId" : "bfoi6yy6pa3yzika53spj7pq9ee" , "userId" : "f1tydgc697fcbp8ampr6881jea" , "roles" : "" , "minimumRole" : "" , "schemeAdmin" : false , "schemeEditor" : false , "schemeCommenter" : false , "schemeViewer" : true , "synthetic" : false } }
{ "type" : "boardMember" , "data" : { "boardId" : "bfoi6yy6pa3yzika53spj7pq9ee" , "userId" : "hxxzooc3ff8cubsgtcmpn8733e" , "roles" : "" , "minimumRole" : "" , "schemeAdmin" : false , "schemeEditor" : false , "schemeCommenter" : false , "schemeViewer" : true , "synthetic" : false } }
{ "type" : "boardMember" , "data" : { "boardId" : "bfoi6yy6pa3yzika53spj7pq9ee" , "userId" : "nto73edn5ir6ifimo5a53y1dwa" , "roles" : "" , "minimumRole" : "" , "schemeAdmin" : true , "schemeEditor" : false , "schemeCommenter" : false , "schemeViewer" : false , "synthetic" : false } }
`