github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/app/export_test.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package app 5 6 import ( 7 "bytes" 8 "os" 9 "sort" 10 "testing" 11 12 "github.com/stretchr/testify/assert" 13 "github.com/stretchr/testify/require" 14 15 "github.com/mattermost/mattermost-server/v5/model" 16 ) 17 18 func TestReactionsOfPost(t *testing.T) { 19 th := Setup(t).InitBasic() 20 defer th.TearDown() 21 22 post := th.BasicPost 23 post.HasReactions = true 24 th.BasicUser2.DeleteAt = 1234 25 reactionObject := model.Reaction{ 26 UserId: th.BasicUser.Id, 27 PostId: post.Id, 28 EmojiName: "emoji", 29 CreateAt: model.GetMillis(), 30 } 31 reactionObjectDeleted := model.Reaction{ 32 UserId: th.BasicUser2.Id, 33 PostId: post.Id, 34 EmojiName: "emoji", 35 CreateAt: model.GetMillis(), 36 } 37 38 th.App.SaveReactionForPost(&reactionObject) 39 th.App.SaveReactionForPost(&reactionObjectDeleted) 40 reactionsOfPost, err := th.App.BuildPostReactions(post.Id) 41 require.Nil(t, err) 42 43 assert.Equal(t, reactionObject.EmojiName, *(*reactionsOfPost)[0].EmojiName) 44 } 45 46 func TestExportUserNotifyProps(t *testing.T) { 47 th := SetupWithStoreMock(t) 48 defer th.TearDown() 49 50 userNotifyProps := model.StringMap{ 51 model.DESKTOP_NOTIFY_PROP: model.USER_NOTIFY_ALL, 52 model.DESKTOP_SOUND_NOTIFY_PROP: "true", 53 model.EMAIL_NOTIFY_PROP: "true", 54 model.PUSH_NOTIFY_PROP: model.USER_NOTIFY_ALL, 55 model.PUSH_STATUS_NOTIFY_PROP: model.STATUS_ONLINE, 56 model.CHANNEL_MENTIONS_NOTIFY_PROP: "true", 57 model.COMMENTS_NOTIFY_PROP: model.COMMENTS_NOTIFY_ROOT, 58 model.MENTION_KEYS_NOTIFY_PROP: "valid,misc", 59 } 60 61 exportNotifyProps := th.App.buildUserNotifyProps(userNotifyProps) 62 63 require.Equal(t, userNotifyProps[model.DESKTOP_NOTIFY_PROP], *exportNotifyProps.Desktop) 64 require.Equal(t, userNotifyProps[model.DESKTOP_SOUND_NOTIFY_PROP], *exportNotifyProps.DesktopSound) 65 require.Equal(t, userNotifyProps[model.EMAIL_NOTIFY_PROP], *exportNotifyProps.Email) 66 require.Equal(t, userNotifyProps[model.PUSH_NOTIFY_PROP], *exportNotifyProps.Mobile) 67 require.Equal(t, userNotifyProps[model.PUSH_STATUS_NOTIFY_PROP], *exportNotifyProps.MobilePushStatus) 68 require.Equal(t, userNotifyProps[model.CHANNEL_MENTIONS_NOTIFY_PROP], *exportNotifyProps.ChannelTrigger) 69 require.Equal(t, userNotifyProps[model.COMMENTS_NOTIFY_PROP], *exportNotifyProps.CommentsTrigger) 70 require.Equal(t, userNotifyProps[model.MENTION_KEYS_NOTIFY_PROP], *exportNotifyProps.MentionKeys) 71 } 72 73 func TestExportUserChannels(t *testing.T) { 74 th := Setup(t).InitBasic() 75 defer th.TearDown() 76 channel := th.BasicChannel 77 user := th.BasicUser 78 team := th.BasicTeam 79 channelName := channel.Name 80 notifyProps := model.StringMap{ 81 model.DESKTOP_NOTIFY_PROP: model.USER_NOTIFY_ALL, 82 model.PUSH_NOTIFY_PROP: model.USER_NOTIFY_NONE, 83 } 84 preference := model.Preference{ 85 UserId: user.Id, 86 Category: model.PREFERENCE_CATEGORY_FAVORITE_CHANNEL, 87 Name: channel.Id, 88 Value: "true", 89 } 90 var preferences model.Preferences 91 preferences = append(preferences, preference) 92 err := th.App.Srv().Store.Preference().Save(&preferences) 93 require.Nil(t, err) 94 95 th.App.UpdateChannelMemberNotifyProps(notifyProps, channel.Id, user.Id) 96 exportData, err := th.App.buildUserChannelMemberships(user.Id, team.Id) 97 require.Nil(t, err) 98 assert.Equal(t, len(*exportData), 3) 99 for _, data := range *exportData { 100 if *data.Name == channelName { 101 assert.Equal(t, *data.NotifyProps.Desktop, "all") 102 assert.Equal(t, *data.NotifyProps.Mobile, "none") 103 assert.Equal(t, *data.NotifyProps.MarkUnread, "all") // default value 104 assert.True(t, *data.Favorite) 105 } else { // default values 106 assert.Equal(t, *data.NotifyProps.Desktop, "default") 107 assert.Equal(t, *data.NotifyProps.Mobile, "default") 108 assert.Equal(t, *data.NotifyProps.MarkUnread, "all") 109 assert.False(t, *data.Favorite) 110 } 111 } 112 } 113 114 func TestDirCreationForEmoji(t *testing.T) { 115 th := SetupWithStoreMock(t) 116 defer th.TearDown() 117 118 pathToDir := th.App.createDirForEmoji("test.json", "exported_emoji_test") 119 defer os.Remove(pathToDir) 120 _, err := os.Stat(pathToDir) 121 require.False(t, os.IsNotExist(err), "Directory exported_emoji_test should exist") 122 } 123 124 func TestCopyEmojiImages(t *testing.T) { 125 th := SetupWithStoreMock(t) 126 defer th.TearDown() 127 128 emoji := &model.Emoji{ 129 Id: model.NewId(), 130 } 131 132 // Creating a dir named `exported_emoji_test` in the root of the repo 133 pathToDir := "../exported_emoji_test" 134 135 os.Mkdir(pathToDir, 0777) 136 defer os.RemoveAll(pathToDir) 137 138 filePath := "../data/emoji/" + emoji.Id 139 emojiImagePath := filePath + "/image" 140 141 var _, err = os.Stat(filePath) 142 if os.IsNotExist(err) { 143 os.MkdirAll(filePath, 0777) 144 } 145 146 // Creating a file with the name `image` to copy it to `exported_emoji_test` 147 os.OpenFile(filePath+"/image", os.O_RDONLY|os.O_CREATE, 0777) 148 defer os.RemoveAll(filePath) 149 150 copyError := th.App.copyEmojiImages(emoji.Id, emojiImagePath, pathToDir) 151 require.Nil(t, copyError) 152 153 _, err = os.Stat(pathToDir + "/" + emoji.Id + "/image") 154 require.False(t, os.IsNotExist(err), "File should exist ") 155 } 156 157 func TestExportCustomEmoji(t *testing.T) { 158 th := Setup(t) 159 defer th.TearDown() 160 161 filePath := "../demo.json" 162 163 fileWriter, err := os.Create(filePath) 164 require.Nil(t, err) 165 defer os.Remove(filePath) 166 167 pathToEmojiDir := "../data/emoji/" 168 dirNameToExportEmoji := "exported_emoji_test" 169 defer os.RemoveAll("../" + dirNameToExportEmoji) 170 171 err = th.App.exportCustomEmoji(fileWriter, filePath, pathToEmojiDir, dirNameToExportEmoji) 172 require.Nil(t, err, "should not have failed") 173 } 174 175 func TestExportAllUsers(t *testing.T) { 176 th1 := Setup(t) 177 defer th1.TearDown() 178 179 // Adding a user and deactivating it to check whether it gets included in bulk export 180 user := th1.CreateUser() 181 _, err := th1.App.UpdateActive(user, false) 182 require.Nil(t, err) 183 184 var b bytes.Buffer 185 err = th1.App.BulkExport(&b, "somefile", "somePath", "someDir") 186 require.Nil(t, err) 187 188 th2 := Setup(t) 189 defer th2.TearDown() 190 err, i := th2.App.BulkImport(&b, false, 5) 191 assert.Nil(t, err) 192 assert.Equal(t, 0, i) 193 194 users1, err := th1.App.GetUsers(&model.UserGetOptions{ 195 Page: 0, 196 PerPage: 10, 197 }) 198 assert.Nil(t, err) 199 users2, err := th2.App.GetUsers(&model.UserGetOptions{ 200 Page: 0, 201 PerPage: 10, 202 }) 203 assert.Nil(t, err) 204 assert.Equal(t, len(users1), len(users2)) 205 assert.ElementsMatch(t, users1, users2) 206 207 // Checking whether deactivated users were included in bulk export 208 deletedUsers1, err := th1.App.GetUsers(&model.UserGetOptions{ 209 Inactive: true, 210 Page: 0, 211 PerPage: 10, 212 }) 213 assert.Nil(t, err) 214 deletedUsers2, err := th1.App.GetUsers(&model.UserGetOptions{ 215 Inactive: true, 216 Page: 0, 217 PerPage: 10, 218 }) 219 assert.Nil(t, err) 220 assert.Equal(t, len(deletedUsers1), len(deletedUsers2)) 221 assert.ElementsMatch(t, deletedUsers1, deletedUsers2) 222 } 223 224 func TestExportDMChannel(t *testing.T) { 225 th1 := Setup(t).InitBasic() 226 227 // DM Channel 228 th1.CreateDmChannel(th1.BasicUser2) 229 230 var b bytes.Buffer 231 err := th1.App.BulkExport(&b, "somefile", "somePath", "someDir") 232 require.Nil(t, err) 233 234 channels, err := th1.App.Srv().Store.Channel().GetAllDirectChannelsForExportAfter(1000, "00000000") 235 require.Nil(t, err) 236 assert.Equal(t, 1, len(channels)) 237 238 th1.TearDown() 239 240 th2 := Setup(t) 241 defer th2.TearDown() 242 243 channels, err = th2.App.Srv().Store.Channel().GetAllDirectChannelsForExportAfter(1000, "00000000") 244 require.Nil(t, err) 245 assert.Equal(t, 0, len(channels)) 246 247 // import the exported channel 248 err, i := th2.App.BulkImport(&b, false, 5) 249 assert.Nil(t, err) 250 assert.Equal(t, 0, i) 251 252 // Ensure the Members of the imported DM channel is the same was from the exported 253 channels, err = th2.App.Srv().Store.Channel().GetAllDirectChannelsForExportAfter(1000, "00000000") 254 require.Nil(t, err) 255 assert.Equal(t, 1, len(channels)) 256 assert.ElementsMatch(t, []string{th1.BasicUser.Username, th1.BasicUser2.Username}, *channels[0].Members) 257 } 258 259 func TestExportDMChannelToSelf(t *testing.T) { 260 th1 := Setup(t).InitBasic() 261 defer th1.TearDown() 262 263 // DM Channel with self (me channel) 264 th1.CreateDmChannel(th1.BasicUser) 265 266 var b bytes.Buffer 267 err := th1.App.BulkExport(&b, "somefile", "somePath", "someDir") 268 require.Nil(t, err) 269 270 channels, err := th1.App.Srv().Store.Channel().GetAllDirectChannelsForExportAfter(1000, "00000000") 271 require.Nil(t, err) 272 assert.Equal(t, 1, len(channels)) 273 274 th2 := Setup(t) 275 defer th2.TearDown() 276 277 channels, err = th2.App.Srv().Store.Channel().GetAllDirectChannelsForExportAfter(1000, "00000000") 278 require.Nil(t, err) 279 assert.Equal(t, 0, len(channels)) 280 281 // import the exported channel 282 err, i := th2.App.BulkImport(&b, false, 5) 283 assert.Nil(t, err) 284 assert.Equal(t, 0, i) 285 286 channels, err = th2.App.Srv().Store.Channel().GetAllDirectChannelsForExportAfter(1000, "00000000") 287 require.Nil(t, err) 288 assert.Equal(t, 1, len(channels)) 289 assert.Equal(t, 1, len((*channels[0].Members))) 290 assert.Equal(t, th1.BasicUser.Username, (*channels[0].Members)[0]) 291 } 292 293 func TestExportGMChannel(t *testing.T) { 294 th1 := Setup(t).InitBasic() 295 296 user1 := th1.CreateUser() 297 th1.LinkUserToTeam(user1, th1.BasicTeam) 298 user2 := th1.CreateUser() 299 th1.LinkUserToTeam(user2, th1.BasicTeam) 300 301 // GM Channel 302 th1.CreateGroupChannel(user1, user2) 303 304 var b bytes.Buffer 305 err := th1.App.BulkExport(&b, "somefile", "somePath", "someDir") 306 require.Nil(t, err) 307 308 channels, err := th1.App.Srv().Store.Channel().GetAllDirectChannelsForExportAfter(1000, "00000000") 309 require.Nil(t, err) 310 assert.Equal(t, 1, len(channels)) 311 312 th1.TearDown() 313 314 th2 := Setup(t) 315 defer th2.TearDown() 316 317 channels, err = th2.App.Srv().Store.Channel().GetAllDirectChannelsForExportAfter(1000, "00000000") 318 require.Nil(t, err) 319 assert.Equal(t, 0, len(channels)) 320 } 321 322 func TestExportGMandDMChannels(t *testing.T) { 323 th1 := Setup(t).InitBasic() 324 325 // DM Channel 326 th1.CreateDmChannel(th1.BasicUser2) 327 328 user1 := th1.CreateUser() 329 th1.LinkUserToTeam(user1, th1.BasicTeam) 330 user2 := th1.CreateUser() 331 th1.LinkUserToTeam(user2, th1.BasicTeam) 332 333 // GM Channel 334 th1.CreateGroupChannel(user1, user2) 335 336 var b bytes.Buffer 337 err := th1.App.BulkExport(&b, "somefile", "somePath", "someDir") 338 require.Nil(t, err) 339 340 channels, err := th1.App.Srv().Store.Channel().GetAllDirectChannelsForExportAfter(1000, "00000000") 341 require.Nil(t, err) 342 assert.Equal(t, 2, len(channels)) 343 344 th1.TearDown() 345 346 th2 := Setup(t) 347 defer th2.TearDown() 348 349 channels, err = th2.App.Srv().Store.Channel().GetAllDirectChannelsForExportAfter(1000, "00000000") 350 require.Nil(t, err) 351 assert.Equal(t, 0, len(channels)) 352 353 // import the exported channel 354 err, i := th2.App.BulkImport(&b, false, 5) 355 assert.Nil(t, err) 356 assert.Equal(t, 0, i) 357 358 // Ensure the Members of the imported GM channel is the same was from the exported 359 channels, err = th2.App.Srv().Store.Channel().GetAllDirectChannelsForExportAfter(1000, "00000000") 360 require.Nil(t, err) 361 362 // Adding some deteminism so its possible to assert on slice index 363 sort.Slice(channels, func(i, j int) bool { return channels[i].Type > channels[j].Type }) 364 assert.Equal(t, 2, len(channels)) 365 assert.ElementsMatch(t, []string{th1.BasicUser.Username, user1.Username, user2.Username}, *channels[0].Members) 366 assert.ElementsMatch(t, []string{th1.BasicUser.Username, th1.BasicUser2.Username}, *channels[1].Members) 367 } 368 369 func TestExportDMandGMPost(t *testing.T) { 370 th1 := Setup(t).InitBasic() 371 372 // DM Channel 373 dmChannel := th1.CreateDmChannel(th1.BasicUser2) 374 dmMembers := []string{th1.BasicUser.Username, th1.BasicUser2.Username} 375 376 user1 := th1.CreateUser() 377 th1.LinkUserToTeam(user1, th1.BasicTeam) 378 user2 := th1.CreateUser() 379 th1.LinkUserToTeam(user2, th1.BasicTeam) 380 381 // GM Channel 382 gmChannel := th1.CreateGroupChannel(user1, user2) 383 gmMembers := []string{th1.BasicUser.Username, user1.Username, user2.Username} 384 385 // DM posts 386 p1 := &model.Post{ 387 ChannelId: dmChannel.Id, 388 Message: "aa" + model.NewId() + "a", 389 UserId: th1.BasicUser.Id, 390 } 391 th1.App.CreatePost(p1, dmChannel, false, true) 392 393 p2 := &model.Post{ 394 ChannelId: dmChannel.Id, 395 Message: "bb" + model.NewId() + "a", 396 UserId: th1.BasicUser.Id, 397 } 398 th1.App.CreatePost(p2, dmChannel, false, true) 399 400 // GM posts 401 p3 := &model.Post{ 402 ChannelId: gmChannel.Id, 403 Message: "cc" + model.NewId() + "a", 404 UserId: th1.BasicUser.Id, 405 } 406 th1.App.CreatePost(p3, gmChannel, false, true) 407 408 p4 := &model.Post{ 409 ChannelId: gmChannel.Id, 410 Message: "dd" + model.NewId() + "a", 411 UserId: th1.BasicUser.Id, 412 } 413 th1.App.CreatePost(p4, gmChannel, false, true) 414 415 posts, err := th1.App.Srv().Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000") 416 require.Nil(t, err) 417 assert.Equal(t, 4, len(posts)) 418 419 var b bytes.Buffer 420 err = th1.App.BulkExport(&b, "somefile", "somePath", "someDir") 421 require.Nil(t, err) 422 423 th1.TearDown() 424 425 th2 := Setup(t) 426 defer th2.TearDown() 427 428 posts, err = th2.App.Srv().Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000") 429 require.Nil(t, err) 430 assert.Equal(t, 0, len(posts)) 431 432 // import the exported posts 433 err, i := th2.App.BulkImport(&b, false, 5) 434 assert.Nil(t, err) 435 assert.Equal(t, 0, i) 436 437 posts, err = th2.App.Srv().Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000") 438 require.Nil(t, err) 439 440 // Adding some deteminism so its possible to assert on slice index 441 sort.Slice(posts, func(i, j int) bool { return posts[i].Message > posts[j].Message }) 442 assert.Equal(t, 4, len(posts)) 443 assert.ElementsMatch(t, gmMembers, *posts[0].ChannelMembers) 444 assert.ElementsMatch(t, gmMembers, *posts[1].ChannelMembers) 445 assert.ElementsMatch(t, dmMembers, *posts[2].ChannelMembers) 446 assert.ElementsMatch(t, dmMembers, *posts[3].ChannelMembers) 447 } 448 449 func TestExportPostWithProps(t *testing.T) { 450 th1 := Setup(t).InitBasic() 451 452 attachments := []*model.SlackAttachment{{Footer: "footer"}} 453 454 // DM Channel 455 dmChannel := th1.CreateDmChannel(th1.BasicUser2) 456 dmMembers := []string{th1.BasicUser.Username, th1.BasicUser2.Username} 457 458 user1 := th1.CreateUser() 459 th1.LinkUserToTeam(user1, th1.BasicTeam) 460 user2 := th1.CreateUser() 461 th1.LinkUserToTeam(user2, th1.BasicTeam) 462 463 // GM Channel 464 gmChannel := th1.CreateGroupChannel(user1, user2) 465 gmMembers := []string{th1.BasicUser.Username, user1.Username, user2.Username} 466 467 // DM posts 468 p1 := &model.Post{ 469 ChannelId: dmChannel.Id, 470 Message: "aa" + model.NewId() + "a", 471 Props: map[string]interface{}{ 472 "attachments": attachments, 473 }, 474 UserId: th1.BasicUser.Id, 475 } 476 th1.App.CreatePost(p1, dmChannel, false, true) 477 478 p2 := &model.Post{ 479 ChannelId: gmChannel.Id, 480 Message: "dd" + model.NewId() + "a", 481 Props: map[string]interface{}{ 482 "attachments": attachments, 483 }, 484 UserId: th1.BasicUser.Id, 485 } 486 th1.App.CreatePost(p2, gmChannel, false, true) 487 488 posts, err := th1.App.Srv().Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000") 489 require.Nil(t, err) 490 assert.Len(t, posts, 2) 491 require.NotEmpty(t, posts[0].Props) 492 require.NotEmpty(t, posts[1].Props) 493 494 var b bytes.Buffer 495 err = th1.App.BulkExport(&b, "somefile", "somePath", "someDir") 496 require.Nil(t, err) 497 498 th1.TearDown() 499 500 th2 := Setup(t) 501 defer th2.TearDown() 502 503 posts, err = th2.App.Srv().Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000") 504 require.Nil(t, err) 505 assert.Len(t, posts, 0) 506 507 // import the exported posts 508 err, i := th2.App.BulkImport(&b, false, 5) 509 assert.Nil(t, err) 510 assert.Equal(t, 0, i) 511 512 posts, err = th2.App.Srv().Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000") 513 require.Nil(t, err) 514 515 // Adding some determinism so its possible to assert on slice index 516 sort.Slice(posts, func(i, j int) bool { return posts[i].Message > posts[j].Message }) 517 assert.Len(t, posts, 2) 518 assert.ElementsMatch(t, gmMembers, *posts[0].ChannelMembers) 519 assert.ElementsMatch(t, dmMembers, *posts[1].ChannelMembers) 520 assert.Contains(t, posts[0].Props["attachments"].([]interface{})[0], "footer") 521 assert.Contains(t, posts[1].Props["attachments"].([]interface{})[0], "footer") 522 } 523 524 func TestExportDMPostWithSelf(t *testing.T) { 525 th1 := Setup(t).InitBasic() 526 527 // DM Channel with self (me channel) 528 dmChannel := th1.CreateDmChannel(th1.BasicUser) 529 530 th1.CreatePost(dmChannel) 531 532 var b bytes.Buffer 533 err := th1.App.BulkExport(&b, "somefile", "somePath", "someDir") 534 require.Nil(t, err) 535 536 posts, err := th1.App.Srv().Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000") 537 require.Nil(t, err) 538 assert.Equal(t, 1, len(posts)) 539 540 th1.TearDown() 541 542 th2 := Setup(t) 543 defer th2.TearDown() 544 545 posts, err = th2.App.Srv().Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000") 546 require.Nil(t, err) 547 assert.Equal(t, 0, len(posts)) 548 549 // import the exported posts 550 err, i := th2.App.BulkImport(&b, false, 5) 551 assert.Nil(t, err) 552 assert.Equal(t, 0, i) 553 554 posts, err = th2.App.Srv().Store.Post().GetDirectPostParentsForExportAfter(1000, "0000000") 555 require.Nil(t, err) 556 assert.Equal(t, 1, len(posts)) 557 assert.Equal(t, 1, len((*posts[0].ChannelMembers))) 558 assert.Equal(t, th1.BasicUser.Username, (*posts[0].ChannelMembers)[0]) 559 }