github.com/demisto/mattermost-server@v4.9.0-rc3+incompatible/api4/post_test.go (about) 1 // Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package api4 5 6 import ( 7 "encoding/json" 8 "fmt" 9 "net/http" 10 "net/http/httptest" 11 "net/url" 12 "reflect" 13 "strconv" 14 "strings" 15 "testing" 16 "time" 17 18 "github.com/mattermost/mattermost-server/app" 19 "github.com/mattermost/mattermost-server/model" 20 ) 21 22 func TestCreatePost(t *testing.T) { 23 th := Setup().InitBasic().InitSystemAdmin() 24 defer th.TearDown() 25 Client := th.Client 26 27 post := &model.Post{ChannelId: th.BasicChannel.Id, Message: "#hashtag a" + model.NewId() + "a", Props: model.StringInterface{model.PROPS_ADD_CHANNEL_MEMBER: "no good"}} 28 rpost, resp := Client.CreatePost(post) 29 CheckNoError(t, resp) 30 CheckCreatedStatus(t, resp) 31 32 if rpost.Message != post.Message { 33 t.Fatal("message didn't match") 34 } 35 36 if rpost.Hashtags != "#hashtag" { 37 t.Fatal("hashtag didn't match") 38 } 39 40 if len(rpost.FileIds) != 0 { 41 t.Fatal("shouldn't have files") 42 } 43 44 if rpost.EditAt != 0 { 45 t.Fatal("newly created post shouldn't have EditAt set") 46 } 47 48 if rpost.Props[model.PROPS_ADD_CHANNEL_MEMBER] != nil { 49 t.Fatal("newly created post shouldn't have Props['add_channel_member'] set") 50 } 51 52 post.RootId = rpost.Id 53 post.ParentId = rpost.Id 54 _, resp = Client.CreatePost(post) 55 CheckNoError(t, resp) 56 57 post.RootId = "junk" 58 _, resp = Client.CreatePost(post) 59 CheckBadRequestStatus(t, resp) 60 61 post.RootId = rpost.Id 62 post.ParentId = "junk" 63 _, resp = Client.CreatePost(post) 64 CheckBadRequestStatus(t, resp) 65 66 post2 := &model.Post{ChannelId: th.BasicChannel2.Id, Message: "zz" + model.NewId() + "a", CreateAt: 123} 67 rpost2, resp := Client.CreatePost(post2) 68 69 if rpost2.CreateAt == post2.CreateAt { 70 t.Fatal("create at should not match") 71 } 72 73 post.RootId = "" 74 post.ParentId = "" 75 post.Type = model.POST_SYSTEM_GENERIC 76 _, resp = Client.CreatePost(post) 77 CheckBadRequestStatus(t, resp) 78 79 post.Type = "" 80 post.RootId = rpost2.Id 81 post.ParentId = rpost2.Id 82 _, resp = Client.CreatePost(post) 83 CheckBadRequestStatus(t, resp) 84 85 post.RootId = "" 86 post.ParentId = "" 87 post.ChannelId = "junk" 88 _, resp = Client.CreatePost(post) 89 CheckForbiddenStatus(t, resp) 90 91 post.ChannelId = model.NewId() 92 _, resp = Client.CreatePost(post) 93 CheckForbiddenStatus(t, resp) 94 95 if r, err := Client.DoApiPost("/posts", "garbage"); err == nil { 96 t.Fatal("should have errored") 97 } else { 98 if r.StatusCode != http.StatusBadRequest { 99 t.Log("actual: " + strconv.Itoa(r.StatusCode)) 100 t.Log("expected: " + strconv.Itoa(http.StatusBadRequest)) 101 t.Fatal("wrong status code") 102 } 103 } 104 105 Client.Logout() 106 _, resp = Client.CreatePost(post) 107 CheckUnauthorizedStatus(t, resp) 108 109 post.ChannelId = th.BasicChannel.Id 110 post.CreateAt = 123 111 rpost, resp = th.SystemAdminClient.CreatePost(post) 112 CheckNoError(t, resp) 113 114 if rpost.CreateAt != post.CreateAt { 115 t.Fatal("create at should match") 116 } 117 } 118 119 func testCreatePostWithOutgoingHook( 120 t *testing.T, 121 hookContentType, expectedContentType, message, triggerWord string, 122 fileIds []string, 123 triggerWhen int, 124 commentPostType bool, 125 ) { 126 th := Setup().InitBasic().InitSystemAdmin() 127 defer th.TearDown() 128 user := th.SystemAdminUser 129 team := th.BasicTeam 130 channel := th.BasicChannel 131 132 th.App.UpdateConfig(func(cfg *model.Config) { cfg.ServiceSettings.EnableOutgoingWebhooks = true }) 133 th.App.UpdateConfig(func(cfg *model.Config) { 134 *cfg.ServiceSettings.AllowedUntrustedInternalConnections = "localhost 127.0.0.1" 135 }) 136 137 var hook *model.OutgoingWebhook 138 var post *model.Post 139 140 // Create a test server that is the target of the outgoing webhook. It will 141 // validate the webhook body fields and write to the success channel on 142 // success/failure. 143 success := make(chan bool) 144 wait := make(chan bool, 1) 145 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 146 <-wait 147 148 requestContentType := r.Header.Get("Content-Type") 149 if requestContentType != expectedContentType { 150 t.Logf("Content-Type is %s, should be %s", requestContentType, expectedContentType) 151 success <- false 152 return 153 } 154 155 expectedPayload := &model.OutgoingWebhookPayload{ 156 Token: hook.Token, 157 TeamId: hook.TeamId, 158 TeamDomain: team.Name, 159 ChannelId: post.ChannelId, 160 ChannelName: channel.Name, 161 Timestamp: post.CreateAt, 162 UserId: post.UserId, 163 UserName: user.Username, 164 PostId: post.Id, 165 Text: post.Message, 166 TriggerWord: triggerWord, 167 FileIds: strings.Join(post.FileIds, ","), 168 } 169 170 // depending on the Content-Type, we expect to find a JSON or form encoded payload 171 if requestContentType == "application/json" { 172 decoder := json.NewDecoder(r.Body) 173 o := &model.OutgoingWebhookPayload{} 174 decoder.Decode(&o) 175 176 if !reflect.DeepEqual(expectedPayload, o) { 177 t.Logf("JSON payload is %+v, should be %+v", o, expectedPayload) 178 success <- false 179 return 180 } 181 } else { 182 err := r.ParseForm() 183 if err != nil { 184 t.Logf("Error parsing form: %q", err) 185 success <- false 186 return 187 } 188 189 expectedFormValues, _ := url.ParseQuery(expectedPayload.ToFormValues()) 190 191 if !reflect.DeepEqual(expectedFormValues, r.Form) { 192 t.Logf("Form values are: %q\n, should be: %q\n", r.Form, expectedFormValues) 193 success <- false 194 return 195 } 196 } 197 198 respPostType := "" //if is empty or post will do a normal post. 199 if commentPostType { 200 respPostType = model.OUTGOING_HOOK_RESPONSE_TYPE_COMMENT 201 } 202 203 outGoingHookResponse := &model.OutgoingWebhookResponse{ 204 Text: model.NewString("some test text"), 205 Username: "TestCommandServer", 206 IconURL: "https://www.mattermost.org/wp-content/uploads/2016/04/icon.png", 207 Type: "custom_as", 208 ResponseType: respPostType, 209 } 210 211 fmt.Fprintf(w, outGoingHookResponse.ToJson()) 212 success <- true 213 })) 214 defer ts.Close() 215 216 // create an outgoing webhook, passing it the test server URL 217 var triggerWords []string 218 if triggerWord != "" { 219 triggerWords = []string{triggerWord} 220 } 221 222 hook = &model.OutgoingWebhook{ 223 ChannelId: channel.Id, 224 TeamId: team.Id, 225 ContentType: hookContentType, 226 TriggerWords: triggerWords, 227 TriggerWhen: triggerWhen, 228 CallbackURLs: []string{ts.URL}, 229 } 230 231 hook, resp := th.SystemAdminClient.CreateOutgoingWebhook(hook) 232 CheckNoError(t, resp) 233 234 // create a post to trigger the webhook 235 post = &model.Post{ 236 ChannelId: channel.Id, 237 Message: message, 238 FileIds: fileIds, 239 } 240 241 post, resp = th.SystemAdminClient.CreatePost(post) 242 CheckNoError(t, resp) 243 244 wait <- true 245 246 // We wait for the test server to write to the success channel and we make 247 // the test fail if that doesn't happen before the timeout. 248 select { 249 case ok := <-success: 250 if !ok { 251 t.Fatal("Test server did send an invalid webhook.") 252 } 253 case <-time.After(time.Second): 254 t.Fatal("Timeout, test server did not send the webhook.") 255 } 256 257 if commentPostType { 258 time.Sleep(time.Millisecond * 100) 259 postList, resp := th.SystemAdminClient.GetPostThread(post.Id, "") 260 CheckNoError(t, resp) 261 if postList.Order[0] != post.Id { 262 t.Fatal("wrong order") 263 } 264 265 if _, ok := postList.Posts[post.Id]; !ok { 266 t.Fatal("should have had post") 267 } 268 269 if len(postList.Posts) != 2 { 270 t.Fatal("should have 2 posts") 271 } 272 273 } 274 } 275 276 func TestCreatePostWithOutgoingHook_form_urlencoded(t *testing.T) { 277 testCreatePostWithOutgoingHook(t, "application/x-www-form-urlencoded", "application/x-www-form-urlencoded", "triggerword lorem ipsum", "triggerword", []string{"file_id_1"}, app.TRIGGERWORDS_EXACT_MATCH, false) 278 testCreatePostWithOutgoingHook(t, "application/x-www-form-urlencoded", "application/x-www-form-urlencoded", "triggerwordaaazzz lorem ipsum", "triggerword", []string{"file_id_1"}, app.TRIGGERWORDS_STARTS_WITH, false) 279 testCreatePostWithOutgoingHook(t, "application/x-www-form-urlencoded", "application/x-www-form-urlencoded", "", "", []string{"file_id_1"}, app.TRIGGERWORDS_EXACT_MATCH, false) 280 testCreatePostWithOutgoingHook(t, "application/x-www-form-urlencoded", "application/x-www-form-urlencoded", "", "", []string{"file_id_1"}, app.TRIGGERWORDS_STARTS_WITH, false) 281 testCreatePostWithOutgoingHook(t, "application/x-www-form-urlencoded", "application/x-www-form-urlencoded", "triggerword lorem ipsum", "triggerword", []string{"file_id_1"}, app.TRIGGERWORDS_EXACT_MATCH, true) 282 testCreatePostWithOutgoingHook(t, "application/x-www-form-urlencoded", "application/x-www-form-urlencoded", "triggerwordaaazzz lorem ipsum", "triggerword", []string{"file_id_1"}, app.TRIGGERWORDS_STARTS_WITH, true) 283 } 284 285 func TestCreatePostWithOutgoingHook_json(t *testing.T) { 286 testCreatePostWithOutgoingHook(t, "application/json", "application/json", "triggerword lorem ipsum", "triggerword", []string{"file_id_1, file_id_2"}, app.TRIGGERWORDS_EXACT_MATCH, false) 287 testCreatePostWithOutgoingHook(t, "application/json", "application/json", "triggerwordaaazzz lorem ipsum", "triggerword", []string{"file_id_1, file_id_2"}, app.TRIGGERWORDS_STARTS_WITH, false) 288 testCreatePostWithOutgoingHook(t, "application/json", "application/json", "triggerword lorem ipsum", "", []string{"file_id_1"}, app.TRIGGERWORDS_EXACT_MATCH, false) 289 testCreatePostWithOutgoingHook(t, "application/json", "application/json", "triggerwordaaazzz lorem ipsum", "", []string{"file_id_1"}, app.TRIGGERWORDS_STARTS_WITH, false) 290 testCreatePostWithOutgoingHook(t, "application/json", "application/json", "triggerword lorem ipsum", "triggerword", []string{"file_id_1, file_id_2"}, app.TRIGGERWORDS_EXACT_MATCH, true) 291 testCreatePostWithOutgoingHook(t, "application/json", "application/json", "triggerwordaaazzz lorem ipsum", "", []string{"file_id_1"}, app.TRIGGERWORDS_STARTS_WITH, true) 292 } 293 294 // hooks created before we added the ContentType field should be considered as 295 // application/x-www-form-urlencoded 296 func TestCreatePostWithOutgoingHook_no_content_type(t *testing.T) { 297 testCreatePostWithOutgoingHook(t, "", "application/x-www-form-urlencoded", "triggerword lorem ipsum", "triggerword", []string{"file_id_1"}, app.TRIGGERWORDS_EXACT_MATCH, false) 298 testCreatePostWithOutgoingHook(t, "", "application/x-www-form-urlencoded", "triggerwordaaazzz lorem ipsum", "triggerword", []string{"file_id_1"}, app.TRIGGERWORDS_STARTS_WITH, false) 299 testCreatePostWithOutgoingHook(t, "", "application/x-www-form-urlencoded", "triggerword lorem ipsum", "", []string{"file_id_1, file_id_2"}, app.TRIGGERWORDS_EXACT_MATCH, false) 300 testCreatePostWithOutgoingHook(t, "", "application/x-www-form-urlencoded", "triggerwordaaazzz lorem ipsum", "", []string{"file_id_1, file_id_2"}, app.TRIGGERWORDS_STARTS_WITH, false) 301 testCreatePostWithOutgoingHook(t, "", "application/x-www-form-urlencoded", "triggerword lorem ipsum", "triggerword", []string{"file_id_1"}, app.TRIGGERWORDS_EXACT_MATCH, true) 302 testCreatePostWithOutgoingHook(t, "", "application/x-www-form-urlencoded", "triggerword lorem ipsum", "", []string{"file_id_1, file_id_2"}, app.TRIGGERWORDS_EXACT_MATCH, true) 303 } 304 305 func TestCreatePostPublic(t *testing.T) { 306 th := Setup().InitBasic().InitSystemAdmin() 307 defer th.TearDown() 308 Client := th.Client 309 310 post := &model.Post{ChannelId: th.BasicChannel.Id, Message: "#hashtag a" + model.NewId() + "a"} 311 312 user := model.User{Email: th.GenerateTestEmail(), Nickname: "Joram Wilander", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_USER_ROLE_ID} 313 314 ruser, resp := Client.CreateUser(&user) 315 CheckNoError(t, resp) 316 317 Client.Login(user.Email, user.Password) 318 319 _, resp = Client.CreatePost(post) 320 CheckForbiddenStatus(t, resp) 321 322 th.App.UpdateUserRoles(ruser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.SYSTEM_POST_ALL_PUBLIC_ROLE_ID, false) 323 th.App.InvalidateAllCaches() 324 325 Client.Login(user.Email, user.Password) 326 327 _, resp = Client.CreatePost(post) 328 CheckNoError(t, resp) 329 330 post.ChannelId = th.BasicPrivateChannel.Id 331 _, resp = Client.CreatePost(post) 332 CheckForbiddenStatus(t, resp) 333 334 th.App.UpdateUserRoles(ruser.Id, model.SYSTEM_USER_ROLE_ID, false) 335 th.App.JoinUserToTeam(th.BasicTeam, ruser, "") 336 th.App.UpdateTeamMemberRoles(th.BasicTeam.Id, ruser.Id, model.TEAM_USER_ROLE_ID+" "+model.TEAM_POST_ALL_PUBLIC_ROLE_ID) 337 th.App.InvalidateAllCaches() 338 339 Client.Login(user.Email, user.Password) 340 341 post.ChannelId = th.BasicPrivateChannel.Id 342 _, resp = Client.CreatePost(post) 343 CheckForbiddenStatus(t, resp) 344 345 post.ChannelId = th.BasicChannel.Id 346 _, resp = Client.CreatePost(post) 347 CheckNoError(t, resp) 348 } 349 350 func TestCreatePostAll(t *testing.T) { 351 th := Setup().InitBasic().InitSystemAdmin() 352 defer th.TearDown() 353 Client := th.Client 354 355 post := &model.Post{ChannelId: th.BasicChannel.Id, Message: "#hashtag a" + model.NewId() + "a"} 356 357 user := model.User{Email: th.GenerateTestEmail(), Nickname: "Joram Wilander", Password: "hello1", Username: GenerateTestUsername(), Roles: model.SYSTEM_USER_ROLE_ID} 358 359 directChannel, _ := th.App.CreateDirectChannel(th.BasicUser.Id, th.BasicUser2.Id) 360 361 ruser, resp := Client.CreateUser(&user) 362 CheckNoError(t, resp) 363 364 Client.Login(user.Email, user.Password) 365 366 _, resp = Client.CreatePost(post) 367 CheckForbiddenStatus(t, resp) 368 369 th.App.UpdateUserRoles(ruser.Id, model.SYSTEM_USER_ROLE_ID+" "+model.SYSTEM_POST_ALL_ROLE_ID, false) 370 th.App.InvalidateAllCaches() 371 372 Client.Login(user.Email, user.Password) 373 374 _, resp = Client.CreatePost(post) 375 CheckNoError(t, resp) 376 377 post.ChannelId = th.BasicPrivateChannel.Id 378 _, resp = Client.CreatePost(post) 379 CheckNoError(t, resp) 380 381 post.ChannelId = directChannel.Id 382 _, resp = Client.CreatePost(post) 383 CheckNoError(t, resp) 384 385 th.App.UpdateUserRoles(ruser.Id, model.SYSTEM_USER_ROLE_ID, false) 386 th.App.JoinUserToTeam(th.BasicTeam, ruser, "") 387 th.App.UpdateTeamMemberRoles(th.BasicTeam.Id, ruser.Id, model.TEAM_USER_ROLE_ID+" "+model.TEAM_POST_ALL_ROLE_ID) 388 th.App.InvalidateAllCaches() 389 390 Client.Login(user.Email, user.Password) 391 392 post.ChannelId = th.BasicPrivateChannel.Id 393 _, resp = Client.CreatePost(post) 394 CheckNoError(t, resp) 395 396 post.ChannelId = th.BasicChannel.Id 397 _, resp = Client.CreatePost(post) 398 CheckNoError(t, resp) 399 400 post.ChannelId = directChannel.Id 401 _, resp = Client.CreatePost(post) 402 CheckForbiddenStatus(t, resp) 403 } 404 405 func TestCreatePostSendOutOfChannelMentions(t *testing.T) { 406 th := Setup().InitBasic().InitSystemAdmin() 407 defer th.TearDown() 408 Client := th.Client 409 410 WebSocketClient, err := th.CreateWebSocketClient() 411 if err != nil { 412 t.Fatal(err) 413 } 414 WebSocketClient.Listen() 415 416 inChannelUser := th.CreateUser() 417 th.LinkUserToTeam(inChannelUser, th.BasicTeam) 418 th.App.AddUserToChannel(inChannelUser, th.BasicChannel) 419 420 post1 := &model.Post{ChannelId: th.BasicChannel.Id, Message: "@" + inChannelUser.Username} 421 _, resp := Client.CreatePost(post1) 422 CheckNoError(t, resp) 423 CheckCreatedStatus(t, resp) 424 425 timeout := time.After(300 * time.Millisecond) 426 waiting := true 427 for waiting { 428 select { 429 case event := <-WebSocketClient.EventChannel: 430 if event.Event == model.WEBSOCKET_EVENT_EPHEMERAL_MESSAGE { 431 t.Fatal("should not have ephemeral message event") 432 } 433 434 case <-timeout: 435 waiting = false 436 } 437 } 438 439 outOfChannelUser := th.CreateUser() 440 th.LinkUserToTeam(outOfChannelUser, th.BasicTeam) 441 442 post2 := &model.Post{ChannelId: th.BasicChannel.Id, Message: "@" + outOfChannelUser.Username} 443 _, resp = Client.CreatePost(post2) 444 CheckNoError(t, resp) 445 CheckCreatedStatus(t, resp) 446 447 timeout = time.After(300 * time.Millisecond) 448 waiting = true 449 for waiting { 450 select { 451 case event := <-WebSocketClient.EventChannel: 452 if event.Event != model.WEBSOCKET_EVENT_EPHEMERAL_MESSAGE { 453 // Ignore any other events 454 continue 455 } 456 457 wpost := model.PostFromJson(strings.NewReader(event.Data["post"].(string))) 458 if acm, ok := wpost.Props[model.PROPS_ADD_CHANNEL_MEMBER].(map[string]interface{}); !ok { 459 t.Fatal("should have received ephemeral post with 'add_channel_member' in props") 460 } else { 461 if acm["post_id"] == nil || acm["user_ids"] == nil || acm["usernames"] == nil { 462 t.Fatal("should not be nil") 463 } 464 } 465 waiting = false 466 case <-timeout: 467 t.Fatal("timed out waiting for ephemeral message event") 468 } 469 } 470 } 471 472 func TestUpdatePost(t *testing.T) { 473 th := Setup().InitBasic().InitSystemAdmin() 474 defer th.TearDown() 475 Client := th.Client 476 channel := th.BasicChannel 477 478 th.App.SetLicense(model.NewTestLicense()) 479 480 post := &model.Post{ChannelId: channel.Id, Message: "zz" + model.NewId() + "a"} 481 rpost, resp := Client.CreatePost(post) 482 CheckNoError(t, resp) 483 484 if rpost.Message != post.Message { 485 t.Fatal("full name didn't match") 486 } 487 488 if rpost.EditAt != 0 { 489 t.Fatal("Newly created post shouldn't have EditAt set") 490 } 491 492 msg := "zz" + model.NewId() + " update post" 493 rpost.Message = msg 494 rpost.UserId = "" 495 496 rupost, resp := Client.UpdatePost(rpost.Id, rpost) 497 CheckNoError(t, resp) 498 499 if rupost.Message != msg { 500 t.Fatal("failed to updates") 501 } 502 if rupost.EditAt == 0 { 503 t.Fatal("EditAt not updated for post") 504 } 505 506 msg1 := "#hashtag a" + model.NewId() + " update post again" 507 rpost.Message = msg1 508 rpost.Props[model.PROPS_ADD_CHANNEL_MEMBER] = "no good" 509 rrupost, resp := Client.UpdatePost(rpost.Id, rpost) 510 CheckNoError(t, resp) 511 512 if rrupost.Message != msg1 && rrupost.Hashtags != "#hashtag" { 513 t.Fatal("failed to updates") 514 } 515 516 if rrupost.Props[model.PROPS_ADD_CHANNEL_MEMBER] != nil { 517 t.Fatal("failed to sanitize Props['add_channel_member'], should be nil") 518 } 519 520 rpost2, err := th.App.CreatePost(&model.Post{ChannelId: channel.Id, Message: "zz" + model.NewId() + "a", Type: model.POST_JOIN_LEAVE, UserId: th.BasicUser.Id}, channel, false) 521 if err != nil { 522 t.Fatal(err) 523 } 524 525 up2 := &model.Post{Id: rpost2.Id, ChannelId: channel.Id, Message: "zz" + model.NewId() + " update post 2"} 526 _, resp = Client.UpdatePost(rpost2.Id, up2) 527 CheckBadRequestStatus(t, resp) 528 529 Client.Logout() 530 _, resp = Client.UpdatePost(rpost.Id, rpost) 531 CheckUnauthorizedStatus(t, resp) 532 533 th.LoginBasic2() 534 _, resp = Client.UpdatePost(rpost.Id, rpost) 535 CheckForbiddenStatus(t, resp) 536 537 Client.Logout() 538 539 _, resp = th.SystemAdminClient.UpdatePost(rpost.Id, rpost) 540 CheckNoError(t, resp) 541 } 542 543 func TestPatchPost(t *testing.T) { 544 th := Setup().InitBasic().InitSystemAdmin() 545 defer th.TearDown() 546 Client := th.Client 547 channel := th.BasicChannel 548 549 th.App.SetLicense(model.NewTestLicense()) 550 551 post := &model.Post{ 552 ChannelId: channel.Id, 553 IsPinned: true, 554 Message: "#hashtag a message", 555 Props: model.StringInterface{"channel_header": "old_header"}, 556 FileIds: model.StringArray{"file1", "file2"}, 557 HasReactions: true, 558 } 559 post, _ = Client.CreatePost(post) 560 561 patch := &model.PostPatch{} 562 563 patch.IsPinned = model.NewBool(false) 564 patch.Message = model.NewString("#otherhashtag other message") 565 patch.Props = new(model.StringInterface) 566 *patch.Props = model.StringInterface{"channel_header": "new_header"} 567 patch.FileIds = new(model.StringArray) 568 *patch.FileIds = model.StringArray{"file1", "otherfile2", "otherfile3"} 569 patch.HasReactions = model.NewBool(false) 570 571 rpost, resp := Client.PatchPost(post.Id, patch) 572 CheckNoError(t, resp) 573 574 if rpost.IsPinned { 575 t.Fatal("IsPinned did not update properly") 576 } 577 if rpost.Message != "#otherhashtag other message" { 578 t.Fatal("Message did not update properly") 579 } 580 if len(rpost.Props) != 1 { 581 t.Fatal("Props did not update properly") 582 } 583 if !reflect.DeepEqual(rpost.Props, *patch.Props) { 584 t.Fatal("Props did not update properly") 585 } 586 if rpost.Hashtags != "#otherhashtag" { 587 t.Fatal("Message did not update properly") 588 } 589 if len(rpost.FileIds) != 3 { 590 t.Fatal("FileIds did not update properly") 591 } 592 if !reflect.DeepEqual(rpost.FileIds, *patch.FileIds) { 593 t.Fatal("FileIds did not update properly") 594 } 595 if rpost.HasReactions { 596 t.Fatal("HasReactions did not update properly") 597 } 598 599 if r, err := Client.DoApiPut("/posts/"+post.Id+"/patch", "garbage"); err == nil { 600 t.Fatal("should have errored") 601 } else { 602 if r.StatusCode != http.StatusBadRequest { 603 t.Log("actual: " + strconv.Itoa(r.StatusCode)) 604 t.Log("expected: " + strconv.Itoa(http.StatusBadRequest)) 605 t.Fatal("wrong status code") 606 } 607 } 608 609 _, resp = Client.PatchPost("junk", patch) 610 CheckBadRequestStatus(t, resp) 611 612 _, resp = Client.PatchPost(GenerateTestId(), patch) 613 CheckForbiddenStatus(t, resp) 614 615 Client.Logout() 616 _, resp = Client.PatchPost(post.Id, patch) 617 CheckUnauthorizedStatus(t, resp) 618 619 th.LoginBasic2() 620 _, resp = Client.PatchPost(post.Id, patch) 621 CheckForbiddenStatus(t, resp) 622 623 th.LoginTeamAdmin() 624 _, resp = Client.PatchPost(post.Id, patch) 625 CheckNoError(t, resp) 626 627 _, resp = th.SystemAdminClient.PatchPost(post.Id, patch) 628 CheckNoError(t, resp) 629 } 630 631 func TestPinPost(t *testing.T) { 632 th := Setup().InitBasic().InitSystemAdmin() 633 defer th.TearDown() 634 Client := th.Client 635 636 post := th.BasicPost 637 pass, resp := Client.PinPost(post.Id) 638 CheckNoError(t, resp) 639 640 if !pass { 641 t.Fatal("should have passed") 642 } 643 644 if rpost, err := th.App.GetSinglePost(post.Id); err != nil && !rpost.IsPinned { 645 t.Fatal("failed to pin post") 646 } 647 648 pass, resp = Client.PinPost("junk") 649 CheckBadRequestStatus(t, resp) 650 651 if pass { 652 t.Fatal("should have failed") 653 } 654 655 _, resp = Client.PinPost(GenerateTestId()) 656 CheckForbiddenStatus(t, resp) 657 658 Client.Logout() 659 _, resp = Client.PinPost(post.Id) 660 CheckUnauthorizedStatus(t, resp) 661 662 _, resp = th.SystemAdminClient.PinPost(post.Id) 663 CheckNoError(t, resp) 664 } 665 666 func TestUnpinPost(t *testing.T) { 667 th := Setup().InitBasic().InitSystemAdmin() 668 defer th.TearDown() 669 Client := th.Client 670 671 pinnedPost := th.CreatePinnedPost() 672 pass, resp := Client.UnpinPost(pinnedPost.Id) 673 CheckNoError(t, resp) 674 675 if !pass { 676 t.Fatal("should have passed") 677 } 678 679 if rpost, err := th.App.GetSinglePost(pinnedPost.Id); err != nil && rpost.IsPinned { 680 t.Fatal("failed to pin post") 681 } 682 683 pass, resp = Client.UnpinPost("junk") 684 CheckBadRequestStatus(t, resp) 685 686 if pass { 687 t.Fatal("should have failed") 688 } 689 690 _, resp = Client.UnpinPost(GenerateTestId()) 691 CheckForbiddenStatus(t, resp) 692 693 Client.Logout() 694 _, resp = Client.UnpinPost(pinnedPost.Id) 695 CheckUnauthorizedStatus(t, resp) 696 697 _, resp = th.SystemAdminClient.UnpinPost(pinnedPost.Id) 698 CheckNoError(t, resp) 699 } 700 701 func TestGetPostsForChannel(t *testing.T) { 702 th := Setup().InitBasic().InitSystemAdmin() 703 defer th.TearDown() 704 Client := th.Client 705 706 post1 := th.CreatePost() 707 post2 := th.CreatePost() 708 post3 := &model.Post{ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a", RootId: post1.Id} 709 post3, _ = Client.CreatePost(post3) 710 711 time.Sleep(300 * time.Millisecond) 712 since := model.GetMillis() 713 time.Sleep(300 * time.Millisecond) 714 715 post4 := th.CreatePost() 716 717 posts, resp := Client.GetPostsForChannel(th.BasicChannel.Id, 0, 60, "") 718 CheckNoError(t, resp) 719 720 if posts.Order[0] != post4.Id { 721 t.Fatal("wrong order") 722 } 723 724 if posts.Order[1] != post3.Id { 725 t.Fatal("wrong order") 726 } 727 728 if posts.Order[2] != post2.Id { 729 t.Fatal("wrong order") 730 } 731 732 if posts.Order[3] != post1.Id { 733 t.Fatal("wrong order") 734 } 735 736 posts, resp = Client.GetPostsForChannel(th.BasicChannel.Id, 0, 3, resp.Etag) 737 CheckEtag(t, posts, resp) 738 739 posts, resp = Client.GetPostsForChannel(th.BasicChannel.Id, 0, 3, "") 740 CheckNoError(t, resp) 741 742 if len(posts.Order) != 3 { 743 t.Fatal("wrong number returned") 744 } 745 746 if _, ok := posts.Posts[post3.Id]; !ok { 747 t.Fatal("missing comment") 748 } 749 750 if _, ok := posts.Posts[post1.Id]; !ok { 751 t.Fatal("missing root post") 752 } 753 754 posts, resp = Client.GetPostsForChannel(th.BasicChannel.Id, 1, 1, "") 755 CheckNoError(t, resp) 756 757 if posts.Order[0] != post3.Id { 758 t.Fatal("wrong order") 759 } 760 761 posts, resp = Client.GetPostsForChannel(th.BasicChannel.Id, 10000, 10000, "") 762 CheckNoError(t, resp) 763 764 if len(posts.Order) != 0 { 765 t.Fatal("should be no posts") 766 } 767 768 post5 := th.CreatePost() 769 770 posts, resp = Client.GetPostsSince(th.BasicChannel.Id, since) 771 CheckNoError(t, resp) 772 773 if len(posts.Posts) != 2 { 774 t.Log(posts.Posts) 775 t.Fatal("should return 2 posts") 776 } 777 778 found := make([]bool, 2) 779 for _, p := range posts.Posts { 780 if p.CreateAt < since { 781 t.Fatal("bad create at for post returned") 782 } 783 if p.Id == post4.Id { 784 found[0] = true 785 } else if p.Id == post5.Id { 786 found[1] = true 787 } 788 } 789 790 for _, f := range found { 791 if !f { 792 t.Fatal("missing post") 793 } 794 } 795 796 _, resp = Client.GetPostsForChannel("", 0, 60, "") 797 CheckBadRequestStatus(t, resp) 798 799 _, resp = Client.GetPostsForChannel("junk", 0, 60, "") 800 CheckBadRequestStatus(t, resp) 801 802 _, resp = Client.GetPostsForChannel(model.NewId(), 0, 60, "") 803 CheckForbiddenStatus(t, resp) 804 805 Client.Logout() 806 _, resp = Client.GetPostsForChannel(model.NewId(), 0, 60, "") 807 CheckUnauthorizedStatus(t, resp) 808 809 _, resp = th.SystemAdminClient.GetPostsForChannel(th.BasicChannel.Id, 0, 60, "") 810 CheckNoError(t, resp) 811 } 812 813 func TestGetFlaggedPostsForUser(t *testing.T) { 814 th := Setup().InitBasic().InitSystemAdmin() 815 defer th.TearDown() 816 Client := th.Client 817 user := th.BasicUser 818 team1 := th.BasicTeam 819 channel1 := th.BasicChannel 820 post1 := th.CreatePost() 821 channel2 := th.CreatePublicChannel() 822 post2 := th.CreatePostWithClient(Client, channel2) 823 824 preference := model.Preference{ 825 UserId: user.Id, 826 Category: model.PREFERENCE_CATEGORY_FLAGGED_POST, 827 Name: post1.Id, 828 Value: "true", 829 } 830 Client.UpdatePreferences(user.Id, &model.Preferences{preference}) 831 preference.Name = post2.Id 832 Client.UpdatePreferences(user.Id, &model.Preferences{preference}) 833 834 opl := model.NewPostList() 835 opl.AddPost(post1) 836 opl.AddOrder(post1.Id) 837 838 rpl, resp := Client.GetFlaggedPostsForUserInChannel(user.Id, channel1.Id, 0, 10) 839 CheckNoError(t, resp) 840 841 if len(rpl.Posts) != 1 { 842 t.Fatal("should have returned 1 post") 843 } 844 845 if !reflect.DeepEqual(rpl.Posts, opl.Posts) { 846 t.Fatal("posts should have matched") 847 } 848 849 rpl, resp = Client.GetFlaggedPostsForUserInChannel(user.Id, channel1.Id, 0, 1) 850 CheckNoError(t, resp) 851 852 if len(rpl.Posts) != 1 { 853 t.Fatal("should have returned 1 post") 854 } 855 856 rpl, resp = Client.GetFlaggedPostsForUserInChannel(user.Id, channel1.Id, 1, 1) 857 CheckNoError(t, resp) 858 859 if len(rpl.Posts) != 0 { 860 t.Fatal("should be empty") 861 } 862 863 rpl, resp = Client.GetFlaggedPostsForUserInChannel(user.Id, GenerateTestId(), 0, 10) 864 CheckNoError(t, resp) 865 866 if len(rpl.Posts) != 0 { 867 t.Fatal("should be empty") 868 } 869 870 rpl, resp = Client.GetFlaggedPostsForUserInChannel(user.Id, "junk", 0, 10) 871 CheckBadRequestStatus(t, resp) 872 873 if rpl != nil { 874 t.Fatal("should be nil") 875 } 876 877 opl.AddPost(post2) 878 opl.AddOrder(post2.Id) 879 880 rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 0, 10) 881 CheckNoError(t, resp) 882 883 if len(rpl.Posts) != 2 { 884 t.Fatal("should have returned 2 posts") 885 } 886 887 if !reflect.DeepEqual(rpl.Posts, opl.Posts) { 888 t.Fatal("posts should have matched") 889 } 890 891 rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 0, 1) 892 CheckNoError(t, resp) 893 894 if len(rpl.Posts) != 1 { 895 t.Fatal("should have returned 1 post") 896 } 897 898 rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 1, 1) 899 CheckNoError(t, resp) 900 901 if len(rpl.Posts) != 1 { 902 t.Fatal("should have returned 1 post") 903 } 904 905 rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 1000, 10) 906 CheckNoError(t, resp) 907 908 if len(rpl.Posts) != 0 { 909 t.Fatal("should be empty") 910 } 911 912 rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, GenerateTestId(), 0, 10) 913 CheckNoError(t, resp) 914 915 if len(rpl.Posts) != 0 { 916 t.Fatal("should be empty") 917 } 918 919 rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, "junk", 0, 10) 920 CheckBadRequestStatus(t, resp) 921 922 if rpl != nil { 923 t.Fatal("should be nil") 924 } 925 926 channel3 := th.CreatePrivateChannel() 927 post4 := th.CreatePostWithClient(Client, channel3) 928 929 preference.Name = post4.Id 930 Client.UpdatePreferences(user.Id, &model.Preferences{preference}) 931 932 opl.AddPost(post4) 933 opl.AddOrder(post4.Id) 934 935 rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 0, 10) 936 CheckNoError(t, resp) 937 938 if len(rpl.Posts) != 3 { 939 t.Fatal("should have returned 3 posts") 940 } 941 942 if !reflect.DeepEqual(rpl.Posts, opl.Posts) { 943 t.Fatal("posts should have matched") 944 } 945 946 rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 0, 2) 947 CheckNoError(t, resp) 948 949 if len(rpl.Posts) != 2 { 950 t.Fatal("should have returned 2 posts") 951 } 952 953 rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 2, 2) 954 CheckNoError(t, resp) 955 956 if len(rpl.Posts) != 1 { 957 t.Fatal("should have returned 1 post") 958 } 959 960 rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 1000, 10) 961 CheckNoError(t, resp) 962 963 if len(rpl.Posts) != 0 { 964 t.Fatal("should be empty") 965 } 966 967 _, resp = Client.GetFlaggedPostsForUser("junk", 0, 10) 968 CheckBadRequestStatus(t, resp) 969 970 _, resp = Client.GetFlaggedPostsForUser(GenerateTestId(), 0, 10) 971 CheckForbiddenStatus(t, resp) 972 973 Client.Logout() 974 975 rpl, resp = Client.GetFlaggedPostsForUserInChannel(user.Id, channel1.Id, 0, 10) 976 CheckUnauthorizedStatus(t, resp) 977 978 rpl, resp = Client.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 0, 10) 979 CheckUnauthorizedStatus(t, resp) 980 981 rpl, resp = Client.GetFlaggedPostsForUser(user.Id, 0, 10) 982 CheckUnauthorizedStatus(t, resp) 983 984 rpl, resp = th.SystemAdminClient.GetFlaggedPostsForUserInChannel(user.Id, channel1.Id, 0, 10) 985 CheckNoError(t, resp) 986 987 rpl, resp = th.SystemAdminClient.GetFlaggedPostsForUserInTeam(user.Id, team1.Id, 0, 10) 988 CheckNoError(t, resp) 989 990 rpl, resp = th.SystemAdminClient.GetFlaggedPostsForUser(user.Id, 0, 10) 991 CheckNoError(t, resp) 992 } 993 994 func TestGetPostsAfterAndBefore(t *testing.T) { 995 th := Setup().InitBasic() 996 defer th.TearDown() 997 Client := th.Client 998 999 post1 := th.CreatePost() 1000 post2 := th.CreatePost() 1001 post3 := th.CreatePost() 1002 post4 := th.CreatePost() 1003 post5 := th.CreatePost() 1004 1005 posts, resp := Client.GetPostsBefore(th.BasicChannel.Id, post3.Id, 0, 100, "") 1006 CheckNoError(t, resp) 1007 1008 found := make([]bool, 2) 1009 for _, p := range posts.Posts { 1010 if p.Id == post1.Id { 1011 found[0] = true 1012 } else if p.Id == post2.Id { 1013 found[1] = true 1014 } 1015 1016 if p.Id == post4.Id || p.Id == post5.Id { 1017 t.Fatal("returned posts after") 1018 } 1019 } 1020 1021 for _, f := range found { 1022 if !f { 1023 t.Fatal("missing post") 1024 } 1025 } 1026 1027 posts, resp = Client.GetPostsBefore(th.BasicChannel.Id, post3.Id, 1, 1, "") 1028 CheckNoError(t, resp) 1029 1030 if len(posts.Posts) != 1 { 1031 t.Fatal("too many posts returned") 1032 } 1033 1034 posts, resp = Client.GetPostsBefore(th.BasicChannel.Id, "junk", 1, 1, "") 1035 CheckNoError(t, resp) 1036 1037 if len(posts.Posts) != 0 { 1038 t.Fatal("should have no posts") 1039 } 1040 1041 posts, resp = Client.GetPostsAfter(th.BasicChannel.Id, post3.Id, 0, 100, "") 1042 CheckNoError(t, resp) 1043 1044 found = make([]bool, 2) 1045 for _, p := range posts.Posts { 1046 if p.Id == post4.Id { 1047 found[0] = true 1048 } else if p.Id == post5.Id { 1049 found[1] = true 1050 } 1051 1052 if p.Id == post1.Id || p.Id == post2.Id { 1053 t.Fatal("returned posts before") 1054 } 1055 } 1056 1057 for _, f := range found { 1058 if !f { 1059 t.Fatal("missing post") 1060 } 1061 } 1062 1063 posts, resp = Client.GetPostsAfter(th.BasicChannel.Id, post3.Id, 1, 1, "") 1064 CheckNoError(t, resp) 1065 1066 if len(posts.Posts) != 1 { 1067 t.Fatal("too many posts returned") 1068 } 1069 1070 posts, resp = Client.GetPostsAfter(th.BasicChannel.Id, "junk", 1, 1, "") 1071 CheckNoError(t, resp) 1072 1073 if len(posts.Posts) != 0 { 1074 t.Fatal("should have no posts") 1075 } 1076 } 1077 1078 func TestGetPost(t *testing.T) { 1079 th := Setup().InitBasic().InitSystemAdmin() 1080 defer th.TearDown() 1081 Client := th.Client 1082 1083 post, resp := Client.GetPost(th.BasicPost.Id, "") 1084 CheckNoError(t, resp) 1085 1086 if post.Id != th.BasicPost.Id { 1087 t.Fatal("post ids don't match") 1088 } 1089 1090 post, resp = Client.GetPost(th.BasicPost.Id, resp.Etag) 1091 CheckEtag(t, post, resp) 1092 1093 _, resp = Client.GetPost("", "") 1094 CheckNotFoundStatus(t, resp) 1095 1096 _, resp = Client.GetPost("junk", "") 1097 CheckBadRequestStatus(t, resp) 1098 1099 _, resp = Client.GetPost(model.NewId(), "") 1100 CheckNotFoundStatus(t, resp) 1101 1102 Client.RemoveUserFromChannel(th.BasicChannel.Id, th.BasicUser.Id) 1103 1104 // Channel is public, should be able to read post 1105 post, resp = Client.GetPost(th.BasicPost.Id, "") 1106 CheckNoError(t, resp) 1107 1108 privatePost := th.CreatePostWithClient(Client, th.BasicPrivateChannel) 1109 1110 post, resp = Client.GetPost(privatePost.Id, "") 1111 CheckNoError(t, resp) 1112 1113 Client.RemoveUserFromChannel(th.BasicPrivateChannel.Id, th.BasicUser.Id) 1114 1115 // Channel is private, should not be able to read post 1116 post, resp = Client.GetPost(privatePost.Id, "") 1117 CheckForbiddenStatus(t, resp) 1118 1119 Client.Logout() 1120 _, resp = Client.GetPost(model.NewId(), "") 1121 CheckUnauthorizedStatus(t, resp) 1122 1123 post, resp = th.SystemAdminClient.GetPost(th.BasicPost.Id, "") 1124 CheckNoError(t, resp) 1125 } 1126 1127 func TestDeletePost(t *testing.T) { 1128 th := Setup().InitBasic().InitSystemAdmin() 1129 defer th.TearDown() 1130 Client := th.Client 1131 1132 _, resp := Client.DeletePost("") 1133 CheckNotFoundStatus(t, resp) 1134 1135 _, resp = Client.DeletePost("junk") 1136 CheckBadRequestStatus(t, resp) 1137 1138 _, resp = Client.DeletePost(th.BasicPost.Id) 1139 CheckForbiddenStatus(t, resp) 1140 1141 Client.Login(th.TeamAdminUser.Email, th.TeamAdminUser.Password) 1142 _, resp = Client.DeletePost(th.BasicPost.Id) 1143 CheckNoError(t, resp) 1144 1145 post := th.CreatePost() 1146 user := th.CreateUser() 1147 1148 Client.Logout() 1149 Client.Login(user.Email, user.Password) 1150 1151 _, resp = Client.DeletePost(post.Id) 1152 CheckForbiddenStatus(t, resp) 1153 1154 Client.Logout() 1155 _, resp = Client.DeletePost(model.NewId()) 1156 CheckUnauthorizedStatus(t, resp) 1157 1158 status, resp := th.SystemAdminClient.DeletePost(post.Id) 1159 if !status { 1160 t.Fatal("post should return status OK") 1161 } 1162 CheckNoError(t, resp) 1163 } 1164 1165 func TestGetPostThread(t *testing.T) { 1166 th := Setup().InitBasic().InitSystemAdmin() 1167 defer th.TearDown() 1168 Client := th.Client 1169 1170 post := &model.Post{ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a", RootId: th.BasicPost.Id} 1171 post, _ = Client.CreatePost(post) 1172 1173 list, resp := Client.GetPostThread(th.BasicPost.Id, "") 1174 CheckNoError(t, resp) 1175 1176 var list2 *model.PostList 1177 list2, resp = Client.GetPostThread(th.BasicPost.Id, resp.Etag) 1178 CheckEtag(t, list2, resp) 1179 1180 if list.Order[0] != th.BasicPost.Id { 1181 t.Fatal("wrong order") 1182 } 1183 1184 if _, ok := list.Posts[th.BasicPost.Id]; !ok { 1185 t.Fatal("should have had post") 1186 } 1187 1188 if _, ok := list.Posts[post.Id]; !ok { 1189 t.Fatal("should have had post") 1190 } 1191 1192 _, resp = Client.GetPostThread("junk", "") 1193 CheckBadRequestStatus(t, resp) 1194 1195 _, resp = Client.GetPostThread(model.NewId(), "") 1196 CheckNotFoundStatus(t, resp) 1197 1198 Client.RemoveUserFromChannel(th.BasicChannel.Id, th.BasicUser.Id) 1199 1200 // Channel is public, should be able to read post 1201 _, resp = Client.GetPostThread(th.BasicPost.Id, "") 1202 CheckNoError(t, resp) 1203 1204 privatePost := th.CreatePostWithClient(Client, th.BasicPrivateChannel) 1205 1206 _, resp = Client.GetPostThread(privatePost.Id, "") 1207 CheckNoError(t, resp) 1208 1209 Client.RemoveUserFromChannel(th.BasicPrivateChannel.Id, th.BasicUser.Id) 1210 1211 // Channel is private, should not be able to read post 1212 _, resp = Client.GetPostThread(privatePost.Id, "") 1213 CheckForbiddenStatus(t, resp) 1214 1215 Client.Logout() 1216 _, resp = Client.GetPostThread(model.NewId(), "") 1217 CheckUnauthorizedStatus(t, resp) 1218 1219 list, resp = th.SystemAdminClient.GetPostThread(th.BasicPost.Id, "") 1220 CheckNoError(t, resp) 1221 } 1222 1223 func TestSearchPosts(t *testing.T) { 1224 th := Setup().InitBasic() 1225 defer th.TearDown() 1226 th.LoginBasic() 1227 Client := th.Client 1228 1229 message := "search for post1" 1230 _ = th.CreateMessagePost(message) 1231 1232 message = "search for post2" 1233 post2 := th.CreateMessagePost(message) 1234 1235 message = "#hashtag search for post3" 1236 post3 := th.CreateMessagePost(message) 1237 1238 message = "hashtag for post4" 1239 _ = th.CreateMessagePost(message) 1240 1241 posts, resp := Client.SearchPosts(th.BasicTeam.Id, "search", false) 1242 CheckNoError(t, resp) 1243 if len(posts.Order) != 3 { 1244 t.Fatal("wrong search") 1245 } 1246 1247 posts, resp = Client.SearchPosts(th.BasicTeam.Id, "post2", false) 1248 CheckNoError(t, resp) 1249 if len(posts.Order) != 1 && posts.Order[0] == post2.Id { 1250 t.Fatal("wrong search") 1251 } 1252 1253 posts, resp = Client.SearchPosts(th.BasicTeam.Id, "#hashtag", false) 1254 CheckNoError(t, resp) 1255 if len(posts.Order) != 1 && posts.Order[0] == post3.Id { 1256 t.Fatal("wrong search") 1257 } 1258 1259 if posts, resp = Client.SearchPosts(th.BasicTeam.Id, "*", false); len(posts.Order) != 0 { 1260 t.Fatal("searching for just * shouldn't return any results") 1261 } 1262 1263 posts, resp = Client.SearchPosts(th.BasicTeam.Id, "post1 post2", true) 1264 CheckNoError(t, resp) 1265 if len(posts.Order) != 2 { 1266 t.Fatal("wrong search results") 1267 } 1268 1269 _, resp = Client.SearchPosts("junk", "#sgtitlereview", false) 1270 CheckBadRequestStatus(t, resp) 1271 1272 _, resp = Client.SearchPosts(model.NewId(), "#sgtitlereview", false) 1273 CheckForbiddenStatus(t, resp) 1274 1275 _, resp = Client.SearchPosts(th.BasicTeam.Id, "", false) 1276 CheckBadRequestStatus(t, resp) 1277 1278 Client.Logout() 1279 _, resp = Client.SearchPosts(th.BasicTeam.Id, "#sgtitlereview", false) 1280 CheckUnauthorizedStatus(t, resp) 1281 1282 } 1283 1284 func TestSearchHashtagPosts(t *testing.T) { 1285 th := Setup().InitBasic() 1286 defer th.TearDown() 1287 th.LoginBasic() 1288 Client := th.Client 1289 1290 message := "#sgtitlereview with space" 1291 _ = th.CreateMessagePost(message) 1292 1293 message = "#sgtitlereview\n with return" 1294 _ = th.CreateMessagePost(message) 1295 1296 message = "no hashtag" 1297 _ = th.CreateMessagePost(message) 1298 1299 posts, resp := Client.SearchPosts(th.BasicTeam.Id, "#sgtitlereview", false) 1300 CheckNoError(t, resp) 1301 if len(posts.Order) != 2 { 1302 t.Fatal("wrong search results") 1303 } 1304 1305 Client.Logout() 1306 _, resp = Client.SearchPosts(th.BasicTeam.Id, "#sgtitlereview", false) 1307 CheckUnauthorizedStatus(t, resp) 1308 } 1309 1310 func TestSearchPostsInChannel(t *testing.T) { 1311 th := Setup().InitBasic() 1312 defer th.TearDown() 1313 th.LoginBasic() 1314 Client := th.Client 1315 1316 channel := th.CreatePublicChannel() 1317 1318 message := "sgtitlereview with space" 1319 _ = th.CreateMessagePost(message) 1320 1321 message = "sgtitlereview\n with return" 1322 _ = th.CreateMessagePostWithClient(Client, th.BasicChannel2, message) 1323 1324 message = "other message with no return" 1325 _ = th.CreateMessagePostWithClient(Client, th.BasicChannel2, message) 1326 1327 message = "other message with no return" 1328 _ = th.CreateMessagePostWithClient(Client, channel, message) 1329 1330 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "channel:", false); len(posts.Order) != 0 { 1331 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1332 } 1333 1334 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "in:", false); len(posts.Order) != 0 { 1335 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1336 } 1337 1338 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "channel:"+th.BasicChannel.Name, false); len(posts.Order) != 2 { 1339 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1340 } 1341 1342 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "in:"+th.BasicChannel2.Name, false); len(posts.Order) != 2 { 1343 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1344 } 1345 1346 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "channel:"+th.BasicChannel2.Name, false); len(posts.Order) != 2 { 1347 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1348 } 1349 1350 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "ChAnNeL:"+th.BasicChannel2.Name, false); len(posts.Order) != 2 { 1351 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1352 } 1353 1354 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "sgtitlereview", false); len(posts.Order) != 2 { 1355 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1356 } 1357 1358 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "sgtitlereview channel:"+th.BasicChannel.Name, false); len(posts.Order) != 1 { 1359 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1360 } 1361 1362 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "sgtitlereview in: "+th.BasicChannel2.Name, false); len(posts.Order) != 1 { 1363 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1364 } 1365 1366 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "sgtitlereview channel: "+th.BasicChannel2.Name, false); len(posts.Order) != 1 { 1367 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1368 } 1369 1370 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "channel: "+th.BasicChannel2.Name+" channel: "+channel.Name, false); len(posts.Order) != 3 { 1371 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1372 } 1373 1374 } 1375 1376 func TestSearchPostsFromUser(t *testing.T) { 1377 th := Setup().InitBasic() 1378 defer th.TearDown() 1379 Client := th.Client 1380 1381 th.LoginTeamAdmin() 1382 user := th.CreateUser() 1383 th.LinkUserToTeam(user, th.BasicTeam) 1384 th.App.AddUserToChannel(user, th.BasicChannel) 1385 th.App.AddUserToChannel(user, th.BasicChannel2) 1386 1387 message := "sgtitlereview with space" 1388 _ = th.CreateMessagePost(message) 1389 1390 Client.Logout() 1391 th.LoginBasic2() 1392 1393 message = "sgtitlereview\n with return" 1394 _ = th.CreateMessagePostWithClient(Client, th.BasicChannel2, message) 1395 1396 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.TeamAdminUser.Username, false); len(posts.Order) != 2 { 1397 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1398 } 1399 1400 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.BasicUser2.Username, false); len(posts.Order) != 1 { 1401 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1402 } 1403 1404 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.BasicUser2.Username+" sgtitlereview", false); len(posts.Order) != 1 { 1405 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1406 } 1407 1408 message = "hullo" 1409 _ = th.CreateMessagePost(message) 1410 1411 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.BasicUser2.Username+" in:"+th.BasicChannel.Name, false); len(posts.Order) != 1 { 1412 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1413 } 1414 1415 Client.Login(user.Email, user.Password) 1416 1417 // wait for the join/leave messages to be created for user3 since they're done asynchronously 1418 time.Sleep(100 * time.Millisecond) 1419 1420 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.BasicUser2.Username, false); len(posts.Order) != 2 { 1421 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1422 } 1423 1424 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.BasicUser2.Username+" from: "+user.Username, false); len(posts.Order) != 2 { 1425 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1426 } 1427 1428 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.BasicUser2.Username+" from: "+user.Username+" in:"+th.BasicChannel2.Name, false); len(posts.Order) != 1 { 1429 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1430 } 1431 1432 message = "coconut" 1433 _ = th.CreateMessagePostWithClient(Client, th.BasicChannel2, message) 1434 1435 if posts, _ := Client.SearchPosts(th.BasicTeam.Id, "from: "+th.BasicUser2.Username+" from: "+user.Username+" in:"+th.BasicChannel2.Name+" coconut", false); len(posts.Order) != 1 { 1436 t.Fatalf("wrong number of posts returned %v", len(posts.Order)) 1437 } 1438 } 1439 1440 func TestGetFileInfosForPost(t *testing.T) { 1441 th := Setup().InitBasic().InitSystemAdmin() 1442 defer th.TearDown() 1443 Client := th.Client 1444 1445 fileIds := make([]string, 3) 1446 if data, err := readTestFile("test.png"); err != nil { 1447 t.Fatal(err) 1448 } else { 1449 for i := 0; i < 3; i++ { 1450 fileResp, _ := Client.UploadFile(data, th.BasicChannel.Id, "test.png") 1451 fileIds[i] = fileResp.FileInfos[0].Id 1452 } 1453 } 1454 1455 post := &model.Post{ChannelId: th.BasicChannel.Id, Message: "zz" + model.NewId() + "a", FileIds: fileIds} 1456 post, _ = Client.CreatePost(post) 1457 1458 infos, resp := Client.GetFileInfosForPost(post.Id, "") 1459 CheckNoError(t, resp) 1460 1461 if len(infos) != 3 { 1462 t.Fatal("missing file infos") 1463 } 1464 1465 found := false 1466 for _, info := range infos { 1467 if info.Id == fileIds[0] { 1468 found = true 1469 } 1470 } 1471 1472 if !found { 1473 t.Fatal("missing file info") 1474 } 1475 1476 infos, resp = Client.GetFileInfosForPost(post.Id, resp.Etag) 1477 CheckEtag(t, infos, resp) 1478 1479 infos, resp = Client.GetFileInfosForPost(th.BasicPost.Id, "") 1480 CheckNoError(t, resp) 1481 1482 if len(infos) != 0 { 1483 t.Fatal("should have no file infos") 1484 } 1485 1486 _, resp = Client.GetFileInfosForPost("junk", "") 1487 CheckBadRequestStatus(t, resp) 1488 1489 _, resp = Client.GetFileInfosForPost(model.NewId(), "") 1490 CheckForbiddenStatus(t, resp) 1491 1492 Client.Logout() 1493 _, resp = Client.GetFileInfosForPost(model.NewId(), "") 1494 CheckUnauthorizedStatus(t, resp) 1495 1496 _, resp = th.SystemAdminClient.GetFileInfosForPost(th.BasicPost.Id, "") 1497 CheckNoError(t, resp) 1498 }