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