github.com/haalcala/mattermost-server-change-repo/v5@v5.33.2/store/searchtest/post_layer.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See LICENSE.txt for license information. 3 4 package searchtest 5 6 import ( 7 "testing" 8 "time" 9 10 "github.com/stretchr/testify/require" 11 12 "github.com/mattermost/mattermost-server/v5/model" 13 "github.com/mattermost/mattermost-server/v5/store" 14 ) 15 16 var searchPostStoreTests = []searchTest{ 17 { 18 Name: "Should be able to search posts including results from DMs", 19 Fn: testSearchPostsIncludingDMs, 20 Tags: []string{EngineAll}, 21 }, 22 { 23 Name: "Should be able to search posts using pagination", 24 Fn: testSearchPostsWithPagination, 25 Tags: []string{EngineElasticSearch, EngineBleve}, 26 }, 27 { 28 Name: "Should return pinned and unpinned posts", 29 Fn: testSearchReturnPinnedAndUnpinned, 30 Tags: []string{EngineAll}, 31 }, 32 { 33 Name: "Should be able to search for exact phrases in quotes", 34 Fn: testSearchExactPhraseInQuotes, 35 Tags: []string{EnginePostgres, EngineMySql, EngineElasticSearch}, 36 }, 37 { 38 Name: "Should be able to search for email addresses with or without quotes", 39 Fn: testSearchEmailAddresses, 40 Tags: []string{EngineElasticSearch}, 41 }, 42 { 43 Name: "Should be able to search when markdown underscores are applied", 44 Fn: testSearchMarkdownUnderscores, 45 Tags: []string{EnginePostgres, EngineElasticSearch}, 46 }, 47 { 48 Name: "Should be able to search for non-latin words", 49 Fn: testSearchNonLatinWords, 50 Tags: []string{EngineElasticSearch}, 51 }, 52 { 53 Name: "Should be able to search for alternative spellings of words", 54 Fn: testSearchAlternativeSpellings, 55 Tags: []string{EngineElasticSearch}, 56 }, 57 { 58 Name: "Should be able to search for alternative spellings of words with and without accents", 59 Fn: testSearchAlternativeSpellingsAccents, 60 Tags: []string{EngineElasticSearch}, 61 }, 62 { 63 Name: "Should be able to search or exclude messages written by a specific user", 64 Fn: testSearchOrExcludePostsBySpecificUser, 65 Tags: []string{EngineAll}, 66 }, 67 { 68 Name: "Should be able to search or exclude messages written in a specific channel", 69 Fn: testSearchOrExcludePostsInChannel, 70 Tags: []string{EngineAll}, 71 }, 72 { 73 Name: "Should be able to search or exclude messages written in a DM or GM", 74 Fn: testSearchOrExcludePostsInDMGM, 75 Tags: []string{EngineAll}, 76 }, 77 { 78 Name: "Should be able to filter messages written after a specific date", 79 Fn: testFilterMessagesAfterSpecificDate, 80 Tags: []string{EngineAll}, 81 }, 82 { 83 Name: "Should be able to filter messages written before a specific date", 84 Fn: testFilterMessagesBeforeSpecificDate, 85 Tags: []string{EngineAll}, 86 }, 87 { 88 Name: "Should be able to filter messages written on a specific date", 89 Fn: testFilterMessagesInSpecificDate, 90 Tags: []string{EngineAll}, 91 }, 92 { 93 Name: "Should be able to exclude messages that contain a serch term", 94 Fn: testFilterMessagesWithATerm, 95 Tags: []string{EngineMySql, EnginePostgres}, 96 }, 97 { 98 Name: "Should be able to search using boolean operators", 99 Fn: testSearchUsingBooleanOperators, 100 Tags: []string{EngineMySql, EnginePostgres, EngineElasticSearch}, 101 }, 102 { 103 Name: "Should be able to search with combined filters", 104 Fn: testSearchUsingCombinedFilters, 105 Tags: []string{EngineAll}, 106 }, 107 { 108 Name: "Should be able to ignore stop words", 109 Fn: testSearchIgnoringStopWords, 110 Tags: []string{EngineMySql, EngineElasticSearch}, 111 }, 112 { 113 Name: "Should support search stemming", 114 Fn: testSupportStemming, 115 Tags: []string{EnginePostgres, EngineElasticSearch}, 116 }, 117 { 118 Name: "Should support search with wildcards", 119 Fn: testSupportWildcards, 120 Tags: []string{EngineAll}, 121 }, 122 { 123 Name: "Should not support search with preceding wildcards", 124 Fn: testNotSupportPrecedingWildcards, 125 Tags: []string{EngineAll}, 126 }, 127 { 128 Name: "Should discard a wildcard if it's not placed immediately by text", 129 Fn: testSearchDiscardWildcardAlone, 130 Tags: []string{EngineAll}, 131 }, 132 { 133 Name: "Should support terms with dash", 134 Fn: testSupportTermsWithDash, 135 Tags: []string{EngineAll}, 136 Skip: true, 137 }, 138 { 139 Name: "Should support terms with underscore", 140 Fn: testSupportTermsWithUnderscore, 141 Tags: []string{EngineMySql, EngineElasticSearch}, 142 }, 143 { 144 Name: "Should search or exclude post using hashtags", 145 Fn: testSearchOrExcludePostsWithHashtags, 146 Tags: []string{EngineAll}, 147 }, 148 { 149 Name: "Should support searching for hashtags surrounded by markdown", 150 Fn: testSearchHashtagWithMarkdown, 151 Tags: []string{EngineAll}, 152 }, 153 { 154 Name: "Should support searching for multiple hashtags", 155 Fn: testSearcWithMultipleHashtags, 156 Tags: []string{EngineElasticSearch}, 157 }, 158 { 159 Name: "Should support searching hashtags with dots", 160 Fn: testSearchPostsWithDotsInHashtags, 161 Tags: []string{EngineAll}, 162 }, 163 { 164 Name: "Should be able to search or exclude messages with hashtags in a case insensitive manner", 165 Fn: testSearchHashtagCaseInsensitive, 166 Tags: []string{EngineAll}, 167 }, 168 { 169 Name: "Should be able to search by hashtags with dashes", 170 Fn: testSearchHashtagWithDash, 171 Tags: []string{EngineAll}, 172 }, 173 { 174 Name: "Should be able to search by hashtags with numbers", 175 Fn: testSearchHashtagWithNumbers, 176 Tags: []string{EngineAll}, 177 }, 178 { 179 Name: "Should be able to search by hashtags with dots", 180 Fn: testSearchHashtagWithDots, 181 Tags: []string{EngineAll}, 182 }, 183 { 184 Name: "Should be able to search by hashtags with underscores", 185 Fn: testSearchHashtagWithUnderscores, 186 Tags: []string{EngineAll}, 187 }, 188 { 189 Name: "Should not return system messages", 190 Fn: testSearchShouldExcludeSytemMessages, 191 Tags: []string{EngineAll}, 192 }, 193 { 194 Name: "Should be able to search matching by mentions", 195 Fn: testSearchShouldBeAbleToMatchByMentions, 196 Tags: []string{EngineAll}, 197 }, 198 { 199 Name: "Should be able to search in deleted/archived channels", 200 Fn: testSearchInDeletedOrArchivedChannels, 201 Tags: []string{EngineMySql, EnginePostgres}, 202 }, 203 { 204 Name: "Should be able to search terms with dashes", 205 Fn: testSearchTermsWithDashes, 206 Tags: []string{EngineAll}, 207 Skip: true, 208 SkipMessage: "Not working", 209 }, 210 { 211 Name: "Should be able to search terms with dots", 212 Fn: testSearchTermsWithDots, 213 Tags: []string{EnginePostgres, EngineElasticSearch}, 214 }, 215 { 216 Name: "Should be able to search terms with underscores", 217 Fn: testSearchTermsWithUnderscores, 218 Tags: []string{EngineMySql, EngineElasticSearch}, 219 }, 220 { 221 Name: "Should be able to search posts made by bot accounts", 222 Fn: testSearchBotAccountsPosts, 223 Tags: []string{EngineAll}, 224 }, 225 { 226 Name: "Should be able to combine stemming and wildcards", 227 Fn: testSupportStemmingAndWildcards, 228 Tags: []string{EngineElasticSearch}, 229 }, 230 { 231 Name: "Should support wildcard outside quotes", 232 Fn: testSupportWildcardOutsideQuotes, 233 Tags: []string{EngineElasticSearch}, 234 }, 235 { 236 Name: "Should support hashtags with 3 or more characters", 237 Fn: testHashtagSearchShouldSupportThreeOrMoreCharacters, 238 Tags: []string{EngineAll}, 239 }, 240 { 241 Name: "Should not support slash as character separator", 242 Fn: testSlashShouldNotBeCharSeparator, 243 Tags: []string{EngineMySql, EngineElasticSearch}, 244 }, 245 { 246 Name: "Should be able to search emails without quoting them", 247 Fn: testSearchEmailsWithoutQuotes, 248 Tags: []string{EngineElasticSearch}, 249 }, 250 { 251 Name: "Should be able to search in comments", 252 Fn: testSupportSearchInComments, 253 Tags: []string{EngineAll}, 254 }, 255 { 256 Name: "Should be able to search terms within links", 257 Fn: testSupportSearchTermsWithinLinks, 258 Tags: []string{EngineMySql, EngineElasticSearch}, 259 }, 260 { 261 Name: "Should not return links that are embedded in markdown", 262 Fn: testShouldNotReturnLinksEmbeddedInMarkdown, 263 Tags: []string{EnginePostgres, EngineElasticSearch}, 264 }, 265 } 266 267 func TestSearchPostStore(t *testing.T, s store.Store, testEngine *SearchTestEngine) { 268 th := &SearchTestHelper{ 269 Store: s, 270 } 271 err := th.SetupBasicFixtures() 272 require.NoError(t, err) 273 defer th.CleanFixtures() 274 275 runTestSearch(t, testEngine, searchPostStoreTests, th) 276 } 277 278 func testSearchPostsIncludingDMs(t *testing.T, th *SearchTestHelper) { 279 direct, err := th.createDirectChannel(th.Team.Id, "direct", "direct", []*model.User{th.User, th.User2}) 280 require.NoError(t, err) 281 defer th.deleteChannel(direct) 282 283 p1, err := th.createPost(th.User.Id, direct.Id, "dm test", "", model.POST_DEFAULT, 0, false) 284 require.NoError(t, err) 285 _, err = th.createPost(th.User.Id, direct.Id, "dm other", "", model.POST_DEFAULT, 0, false) 286 require.NoError(t, err) 287 p2, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "channel test", "", model.POST_DEFAULT, 0, false) 288 require.NoError(t, err) 289 defer th.deleteUserPosts(th.User.Id) 290 291 params := &model.SearchParams{Terms: "test"} 292 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 293 require.NoError(t, err) 294 295 require.Len(t, results.Posts, 2) 296 th.checkPostInSearchResults(t, p1.Id, results.Posts) 297 th.checkPostInSearchResults(t, p2.Id, results.Posts) 298 } 299 300 func testSearchPostsWithPagination(t *testing.T, th *SearchTestHelper) { 301 direct, err := th.createDirectChannel(th.Team.Id, "direct", "direct", []*model.User{th.User, th.User2}) 302 require.NoError(t, err) 303 defer th.deleteChannel(direct) 304 305 p1, err := th.createPost(th.User.Id, direct.Id, "dm test", "", model.POST_DEFAULT, 10000, false) 306 require.NoError(t, err) 307 _, err = th.createPost(th.User.Id, direct.Id, "dm other", "", model.POST_DEFAULT, 20000, false) 308 require.NoError(t, err) 309 p2, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "channel test", "", model.POST_DEFAULT, 0, false) 310 require.NoError(t, err) 311 defer th.deleteUserPosts(th.User.Id) 312 313 params := &model.SearchParams{Terms: "test"} 314 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 1) 315 require.NoError(t, err) 316 317 require.Len(t, results.Posts, 1) 318 th.checkPostInSearchResults(t, p2.Id, results.Posts) 319 320 results, err = th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 1, 1) 321 require.NoError(t, err) 322 323 require.Len(t, results.Posts, 1) 324 th.checkPostInSearchResults(t, p1.Id, results.Posts) 325 } 326 327 func testSearchReturnPinnedAndUnpinned(t *testing.T, th *SearchTestHelper) { 328 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "channel test unpinned", "", model.POST_DEFAULT, 0, false) 329 require.NoError(t, err) 330 p2, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "channel test pinned", "", model.POST_DEFAULT, 0, true) 331 require.NoError(t, err) 332 defer th.deleteUserPosts(th.User.Id) 333 334 params := &model.SearchParams{Terms: "test"} 335 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 336 require.NoError(t, err) 337 338 require.Len(t, results.Posts, 2) 339 th.checkPostInSearchResults(t, p1.Id, results.Posts) 340 th.checkPostInSearchResults(t, p2.Id, results.Posts) 341 } 342 343 func testSearchExactPhraseInQuotes(t *testing.T, th *SearchTestHelper) { 344 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "channel test 1 2 3", "", model.POST_DEFAULT, 0, false) 345 require.NoError(t, err) 346 _, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "channel test 123", "", model.POST_DEFAULT, 0, false) 347 require.NoError(t, err) 348 defer th.deleteUserPosts(th.User.Id) 349 350 params := &model.SearchParams{Terms: "\"channel test 1 2 3\""} 351 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 352 require.NoError(t, err) 353 354 require.Len(t, results.Posts, 1) 355 th.checkPostInSearchResults(t, p1.Id, results.Posts) 356 } 357 358 func testSearchEmailAddresses(t *testing.T, th *SearchTestHelper) { 359 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "test email test@test.com", "", model.POST_DEFAULT, 0, false) 360 require.NoError(t, err) 361 _, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "test email test2@test.com", "", model.POST_DEFAULT, 0, false) 362 require.NoError(t, err) 363 defer th.deleteUserPosts(th.User.Id) 364 365 t.Run("Should search email addresses enclosed by quotes", func(t *testing.T) { 366 params := &model.SearchParams{Terms: "\"test@test.com\""} 367 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 368 require.NoError(t, err) 369 370 require.Len(t, results.Posts, 1) 371 th.checkPostInSearchResults(t, p1.Id, results.Posts) 372 }) 373 374 t.Run("Should search email addresses without quotes", func(t *testing.T) { 375 params := &model.SearchParams{Terms: "test@test.com"} 376 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 377 require.NoError(t, err) 378 379 require.Len(t, results.Posts, 1) 380 th.checkPostInSearchResults(t, p1.Id, results.Posts) 381 }) 382 } 383 384 func testSearchMarkdownUnderscores(t *testing.T, th *SearchTestHelper) { 385 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "_start middle end_ _another_", "", model.POST_DEFAULT, 0, false) 386 require.NoError(t, err) 387 defer th.deleteUserPosts(th.User.Id) 388 389 t.Run("Should search the start inside the markdown underscore", func(t *testing.T) { 390 params := &model.SearchParams{Terms: "start"} 391 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 392 require.NoError(t, err) 393 394 require.Len(t, results.Posts, 1) 395 th.checkPostInSearchResults(t, p1.Id, results.Posts) 396 }) 397 398 t.Run("Should search a word in the middle of the markdown underscore", func(t *testing.T) { 399 params := &model.SearchParams{Terms: "middle"} 400 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 401 require.NoError(t, err) 402 403 require.Len(t, results.Posts, 1) 404 th.checkPostInSearchResults(t, p1.Id, results.Posts) 405 }) 406 407 t.Run("Should search in the end of the markdown underscore", func(t *testing.T) { 408 params := &model.SearchParams{Terms: "end"} 409 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 410 require.NoError(t, err) 411 412 require.Len(t, results.Posts, 1) 413 th.checkPostInSearchResults(t, p1.Id, results.Posts) 414 }) 415 416 t.Run("Should search inside markdown underscore", func(t *testing.T) { 417 params := &model.SearchParams{Terms: "another"} 418 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 419 require.NoError(t, err) 420 421 require.Len(t, results.Posts, 1) 422 th.checkPostInSearchResults(t, p1.Id, results.Posts) 423 }) 424 } 425 426 func testSearchNonLatinWords(t *testing.T, th *SearchTestHelper) { 427 t.Run("Should be able to search chinese words", func(t *testing.T) { 428 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "你好", "", model.POST_DEFAULT, 0, false) 429 require.NoError(t, err) 430 p2, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "你", "", model.POST_DEFAULT, 0, false) 431 require.NoError(t, err) 432 defer th.deleteUserPosts(th.User.Id) 433 434 t.Run("Should search one word", func(t *testing.T) { 435 params := &model.SearchParams{Terms: "你"} 436 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 437 require.NoError(t, err) 438 439 require.Len(t, results.Posts, 1) 440 th.checkPostInSearchResults(t, p2.Id, results.Posts) 441 }) 442 t.Run("Should search two words", func(t *testing.T) { 443 params := &model.SearchParams{Terms: "你好"} 444 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 445 require.NoError(t, err) 446 447 require.Len(t, results.Posts, 1) 448 th.checkPostInSearchResults(t, p1.Id, results.Posts) 449 }) 450 t.Run("Should search with wildcard", func(t *testing.T) { 451 params := &model.SearchParams{Terms: "你*"} 452 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 453 require.NoError(t, err) 454 455 require.Len(t, results.Posts, 2) 456 th.checkPostInSearchResults(t, p1.Id, results.Posts) 457 th.checkPostInSearchResults(t, p2.Id, results.Posts) 458 }) 459 }) 460 t.Run("Should be able to search cyrillic words", func(t *testing.T) { 461 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "слово test", "", model.POST_DEFAULT, 0, false) 462 require.NoError(t, err) 463 defer th.deleteUserPosts(th.User.Id) 464 465 t.Run("Should search one word", func(t *testing.T) { 466 params := &model.SearchParams{Terms: "слово"} 467 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 468 require.NoError(t, err) 469 470 require.Len(t, results.Posts, 1) 471 th.checkPostInSearchResults(t, p1.Id, results.Posts) 472 }) 473 t.Run("Should search using wildcard", func(t *testing.T) { 474 params := &model.SearchParams{Terms: "слов*"} 475 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 476 require.NoError(t, err) 477 478 require.Len(t, results.Posts, 1) 479 th.checkPostInSearchResults(t, p1.Id, results.Posts) 480 }) 481 }) 482 483 t.Run("Should be able to search japanese words", func(t *testing.T) { 484 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "本", "", model.POST_DEFAULT, 0, false) 485 require.NoError(t, err) 486 p2, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "本木", "", model.POST_DEFAULT, 0, false) 487 require.NoError(t, err) 488 defer th.deleteUserPosts(th.User.Id) 489 490 t.Run("Should search one word", func(t *testing.T) { 491 params := &model.SearchParams{Terms: "本"} 492 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 493 require.NoError(t, err) 494 495 require.Len(t, results.Posts, 2) 496 th.checkPostInSearchResults(t, p1.Id, results.Posts) 497 th.checkPostInSearchResults(t, p2.Id, results.Posts) 498 }) 499 t.Run("Should search two words", func(t *testing.T) { 500 params := &model.SearchParams{Terms: "本木"} 501 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 502 require.NoError(t, err) 503 504 require.Len(t, results.Posts, 1) 505 th.checkPostInSearchResults(t, p2.Id, results.Posts) 506 }) 507 t.Run("Should search with wildcard", func(t *testing.T) { 508 params := &model.SearchParams{Terms: "本*"} 509 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 510 require.NoError(t, err) 511 512 require.Len(t, results.Posts, 2) 513 th.checkPostInSearchResults(t, p1.Id, results.Posts) 514 th.checkPostInSearchResults(t, p2.Id, results.Posts) 515 }) 516 }) 517 518 t.Run("Should be able to search korean words", func(t *testing.T) { 519 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "불", "", model.POST_DEFAULT, 0, false) 520 require.NoError(t, err) 521 p2, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "불다", "", model.POST_DEFAULT, 0, false) 522 require.NoError(t, err) 523 defer th.deleteUserPosts(th.User.Id) 524 525 t.Run("Should search one word", func(t *testing.T) { 526 params := &model.SearchParams{Terms: "불"} 527 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 528 require.NoError(t, err) 529 530 require.Len(t, results.Posts, 1) 531 th.checkPostInSearchResults(t, p1.Id, results.Posts) 532 }) 533 t.Run("Should search two words", func(t *testing.T) { 534 params := &model.SearchParams{Terms: "불다"} 535 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 536 require.NoError(t, err) 537 538 require.Len(t, results.Posts, 1) 539 th.checkPostInSearchResults(t, p2.Id, results.Posts) 540 }) 541 t.Run("Should search with wildcard", func(t *testing.T) { 542 params := &model.SearchParams{Terms: "불*"} 543 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 544 require.NoError(t, err) 545 546 require.Len(t, results.Posts, 2) 547 th.checkPostInSearchResults(t, p1.Id, results.Posts) 548 th.checkPostInSearchResults(t, p2.Id, results.Posts) 549 }) 550 }) 551 } 552 553 func testSearchAlternativeSpellings(t *testing.T, th *SearchTestHelper) { 554 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "Straße test", "", model.POST_DEFAULT, 0, false) 555 require.NoError(t, err) 556 p2, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "Strasse test", "", model.POST_DEFAULT, 0, false) 557 require.NoError(t, err) 558 defer th.deleteUserPosts(th.User.Id) 559 560 params := &model.SearchParams{Terms: "Straße"} 561 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 562 require.NoError(t, err) 563 564 require.Len(t, results.Posts, 2) 565 th.checkPostInSearchResults(t, p1.Id, results.Posts) 566 th.checkPostInSearchResults(t, p2.Id, results.Posts) 567 568 params = &model.SearchParams{Terms: "Strasse"} 569 results, err = th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 570 require.NoError(t, err) 571 572 require.Len(t, results.Posts, 2) 573 th.checkPostInSearchResults(t, p1.Id, results.Posts) 574 th.checkPostInSearchResults(t, p2.Id, results.Posts) 575 } 576 577 func testSearchAlternativeSpellingsAccents(t *testing.T, th *SearchTestHelper) { 578 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "café", "", model.POST_DEFAULT, 0, false) 579 require.NoError(t, err) 580 p2, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "café", "", model.POST_DEFAULT, 0, false) 581 require.NoError(t, err) 582 defer th.deleteUserPosts(th.User.Id) 583 584 params := &model.SearchParams{Terms: "café"} 585 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 586 require.NoError(t, err) 587 588 require.Len(t, results.Posts, 2) 589 th.checkPostInSearchResults(t, p1.Id, results.Posts) 590 th.checkPostInSearchResults(t, p2.Id, results.Posts) 591 592 params = &model.SearchParams{Terms: "café"} 593 results, err = th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 594 require.NoError(t, err) 595 596 require.Len(t, results.Posts, 2) 597 th.checkPostInSearchResults(t, p1.Id, results.Posts) 598 th.checkPostInSearchResults(t, p2.Id, results.Posts) 599 600 params = &model.SearchParams{Terms: "cafe"} 601 results, err = th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 602 require.NoError(t, err) 603 604 require.Len(t, results.Posts, 0) 605 } 606 607 func testSearchOrExcludePostsBySpecificUser(t *testing.T, th *SearchTestHelper) { 608 p1, err := th.createPost(th.User.Id, th.ChannelPrivate.Id, "test fromuser", "", model.POST_DEFAULT, 0, false) 609 require.NoError(t, err) 610 _, err = th.createPost(th.User2.Id, th.ChannelPrivate.Id, "test fromuser 2", "", model.POST_DEFAULT, 0, false) 611 require.NoError(t, err) 612 defer th.deleteUserPosts(th.User.Id) 613 defer th.deleteUserPosts(th.User2.Id) 614 615 params := &model.SearchParams{ 616 Terms: "fromuser", 617 FromUsers: []string{th.User.Id}, 618 } 619 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 620 require.NoError(t, err) 621 622 require.Len(t, results.Posts, 1) 623 th.checkPostInSearchResults(t, p1.Id, results.Posts) 624 } 625 626 func testSearchOrExcludePostsInChannel(t *testing.T, th *SearchTestHelper) { 627 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "test fromuser", "", model.POST_DEFAULT, 0, false) 628 require.NoError(t, err) 629 _, err = th.createPost(th.User2.Id, th.ChannelPrivate.Id, "test fromuser 2", "", model.POST_DEFAULT, 0, false) 630 require.NoError(t, err) 631 defer th.deleteUserPosts(th.User.Id) 632 defer th.deleteUserPosts(th.User2.Id) 633 634 params := &model.SearchParams{ 635 Terms: "fromuser", 636 InChannels: []string{th.ChannelBasic.Id}, 637 } 638 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 639 require.NoError(t, err) 640 641 require.Len(t, results.Posts, 1) 642 th.checkPostInSearchResults(t, p1.Id, results.Posts) 643 } 644 645 func testSearchOrExcludePostsInDMGM(t *testing.T, th *SearchTestHelper) { 646 direct, err := th.createDirectChannel(th.Team.Id, "direct", "direct", []*model.User{th.User, th.User2}) 647 require.NoError(t, err) 648 defer th.deleteChannel(direct) 649 650 group, err := th.createGroupChannel(th.Team.Id, "test group", []*model.User{th.User, th.User2}) 651 require.NoError(t, err) 652 defer th.deleteChannel(group) 653 654 p1, err := th.createPost(th.User.Id, direct.Id, "test fromuser", "", model.POST_DEFAULT, 0, false) 655 require.NoError(t, err) 656 p2, err := th.createPost(th.User2.Id, group.Id, "test fromuser 2", "", model.POST_DEFAULT, 0, false) 657 require.NoError(t, err) 658 defer th.deleteUserPosts(th.User.Id) 659 defer th.deleteUserPosts(th.User2.Id) 660 661 t.Run("Should be able to search in both DM and GM channels", func(t *testing.T) { 662 params := &model.SearchParams{ 663 Terms: "fromuser", 664 InChannels: []string{direct.Id, group.Id}, 665 } 666 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 667 require.NoError(t, err) 668 669 require.Len(t, results.Posts, 2) 670 th.checkPostInSearchResults(t, p1.Id, results.Posts) 671 th.checkPostInSearchResults(t, p2.Id, results.Posts) 672 }) 673 674 t.Run("Should be able to search only in DM channel", func(t *testing.T) { 675 params := &model.SearchParams{ 676 Terms: "fromuser", 677 InChannels: []string{direct.Id}, 678 } 679 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 680 require.NoError(t, err) 681 682 require.Len(t, results.Posts, 1) 683 th.checkPostInSearchResults(t, p1.Id, results.Posts) 684 }) 685 686 t.Run("Should be able to search only in GM channel", func(t *testing.T) { 687 params := &model.SearchParams{ 688 Terms: "fromuser", 689 InChannels: []string{group.Id}, 690 } 691 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 692 require.NoError(t, err) 693 694 require.Len(t, results.Posts, 1) 695 th.checkPostInSearchResults(t, p2.Id, results.Posts) 696 }) 697 } 698 699 func testFilterMessagesInSpecificDate(t *testing.T, th *SearchTestHelper) { 700 creationDate := model.GetMillisForTime(time.Date(2020, 03, 22, 12, 0, 0, 0, time.UTC)) 701 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "test in specific date", "", model.POST_DEFAULT, creationDate, false) 702 require.NoError(t, err) 703 creationDate2 := model.GetMillisForTime(time.Date(2020, 03, 23, 0, 0, 0, 0, time.UTC)) 704 p2, err := th.createPost(th.User.Id, th.ChannelPrivate.Id, "test in the present", "", model.POST_DEFAULT, creationDate2, false) 705 require.NoError(t, err) 706 creationDate3 := model.GetMillisForTime(time.Date(2020, 03, 21, 23, 59, 59, 0, time.UTC)) 707 p3, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "test in the present", "", model.POST_DEFAULT, creationDate3, false) 708 require.NoError(t, err) 709 defer th.deleteUserPosts(th.User.Id) 710 711 t.Run("Should be able to search posts on date", func(t *testing.T) { 712 params := &model.SearchParams{ 713 Terms: "test", 714 OnDate: "2020-03-22", 715 } 716 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 717 require.NoError(t, err) 718 719 require.Len(t, results.Posts, 1) 720 th.checkPostInSearchResults(t, p1.Id, results.Posts) 721 }) 722 t.Run("Should be able to exclude posts on date", func(t *testing.T) { 723 params := &model.SearchParams{ 724 Terms: "test", 725 ExcludedDate: "2020-03-22", 726 } 727 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 728 require.NoError(t, err) 729 730 require.Len(t, results.Posts, 2) 731 th.checkPostInSearchResults(t, p2.Id, results.Posts) 732 th.checkPostInSearchResults(t, p3.Id, results.Posts) 733 }) 734 } 735 736 func testFilterMessagesBeforeSpecificDate(t *testing.T, th *SearchTestHelper) { 737 creationDate := model.GetMillisForTime(time.Date(2020, 03, 01, 12, 0, 0, 0, time.UTC)) 738 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "test in specific date", "", model.POST_DEFAULT, creationDate, false) 739 require.NoError(t, err) 740 creationDate2 := model.GetMillisForTime(time.Date(2020, 03, 22, 23, 59, 59, 0, time.UTC)) 741 p2, err := th.createPost(th.User.Id, th.ChannelPrivate.Id, "test in specific date 2", "", model.POST_DEFAULT, creationDate2, false) 742 require.NoError(t, err) 743 creationDate3 := model.GetMillisForTime(time.Date(2020, 03, 26, 16, 55, 0, 0, time.UTC)) 744 p3, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "test in the present", "", model.POST_DEFAULT, creationDate3, false) 745 require.NoError(t, err) 746 defer th.deleteUserPosts(th.User.Id) 747 748 t.Run("Should be able to search posts before a date", func(t *testing.T) { 749 params := &model.SearchParams{ 750 Terms: "test", 751 BeforeDate: "2020-03-23", 752 } 753 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 754 require.NoError(t, err) 755 756 require.Len(t, results.Posts, 2) 757 th.checkPostInSearchResults(t, p1.Id, results.Posts) 758 th.checkPostInSearchResults(t, p2.Id, results.Posts) 759 }) 760 761 t.Run("Should be able to exclude posts before a date", func(t *testing.T) { 762 params := &model.SearchParams{ 763 Terms: "test", 764 ExcludedBeforeDate: "2020-03-23", 765 } 766 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 767 require.NoError(t, err) 768 769 require.Len(t, results.Posts, 1) 770 th.checkPostInSearchResults(t, p3.Id, results.Posts) 771 }) 772 } 773 774 func testFilterMessagesAfterSpecificDate(t *testing.T, th *SearchTestHelper) { 775 creationDate := model.GetMillisForTime(time.Date(2020, 03, 01, 12, 0, 0, 0, time.UTC)) 776 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "test in specific date", "", model.POST_DEFAULT, creationDate, false) 777 require.NoError(t, err) 778 creationDate2 := model.GetMillisForTime(time.Date(2020, 03, 22, 23, 59, 59, 0, time.UTC)) 779 p2, err := th.createPost(th.User.Id, th.ChannelPrivate.Id, "test in specific date 2", "", model.POST_DEFAULT, creationDate2, false) 780 require.NoError(t, err) 781 creationDate3 := model.GetMillisForTime(time.Date(2020, 03, 26, 16, 55, 0, 0, time.UTC)) 782 p3, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "test in the present", "", model.POST_DEFAULT, creationDate3, false) 783 require.NoError(t, err) 784 defer th.deleteUserPosts(th.User.Id) 785 786 t.Run("Should be able to search posts after a date", func(t *testing.T) { 787 params := &model.SearchParams{ 788 Terms: "test", 789 AfterDate: "2020-03-23", 790 } 791 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 792 require.NoError(t, err) 793 794 require.Len(t, results.Posts, 1) 795 th.checkPostInSearchResults(t, p3.Id, results.Posts) 796 }) 797 798 t.Run("Should be able to exclude posts after a date", func(t *testing.T) { 799 params := &model.SearchParams{ 800 Terms: "test", 801 ExcludedAfterDate: "2020-03-23", 802 } 803 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 804 require.NoError(t, err) 805 806 require.Len(t, results.Posts, 2) 807 th.checkPostInSearchResults(t, p1.Id, results.Posts) 808 th.checkPostInSearchResults(t, p2.Id, results.Posts) 809 }) 810 } 811 812 func testFilterMessagesWithATerm(t *testing.T, th *SearchTestHelper) { 813 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "one two three", "", model.POST_DEFAULT, 0, false) 814 require.NoError(t, err) 815 p2, err := th.createPost(th.User.Id, th.ChannelPrivate.Id, "one four five six", "", model.POST_DEFAULT, 0, false) 816 require.NoError(t, err) 817 _, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "one seven eight nine", "", model.POST_DEFAULT, 0, false) 818 require.NoError(t, err) 819 defer th.deleteUserPosts(th.User.Id) 820 821 t.Run("Should exclude terms", func(t *testing.T) { 822 params := &model.SearchParams{ 823 Terms: "one", 824 ExcludedTerms: "five eight", 825 } 826 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 827 require.NoError(t, err) 828 829 require.Len(t, results.Posts, 1) 830 th.checkPostInSearchResults(t, p1.Id, results.Posts) 831 }) 832 833 t.Run("Should exclude quoted terms", func(t *testing.T) { 834 params := &model.SearchParams{ 835 Terms: "one", 836 ExcludedTerms: "\"eight nine\"", 837 } 838 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 839 require.NoError(t, err) 840 841 require.Len(t, results.Posts, 2) 842 th.checkPostInSearchResults(t, p1.Id, results.Posts) 843 th.checkPostInSearchResults(t, p2.Id, results.Posts) 844 }) 845 } 846 847 func testSearchUsingBooleanOperators(t *testing.T, th *SearchTestHelper) { 848 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "one two three message", "", model.POST_DEFAULT, 0, false) 849 require.NoError(t, err) 850 p2, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "two messages", "", model.POST_DEFAULT, 0, false) 851 require.NoError(t, err) 852 _, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "another message", "", model.POST_DEFAULT, 0, false) 853 require.NoError(t, err) 854 defer th.deleteUserPosts(th.User.Id) 855 856 t.Run("Should search posts using OR operator", func(t *testing.T) { 857 params := &model.SearchParams{ 858 Terms: "one two", 859 OrTerms: true, 860 } 861 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 862 require.NoError(t, err) 863 864 require.Len(t, results.Posts, 2) 865 th.checkPostInSearchResults(t, p1.Id, results.Posts) 866 th.checkPostInSearchResults(t, p2.Id, results.Posts) 867 }) 868 869 t.Run("Should search posts using AND operator", func(t *testing.T) { 870 params := &model.SearchParams{ 871 Terms: "one two", 872 OrTerms: false, 873 } 874 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 875 require.NoError(t, err) 876 877 require.Len(t, results.Posts, 1) 878 th.checkPostInSearchResults(t, p1.Id, results.Posts) 879 }) 880 } 881 882 func testSearchUsingCombinedFilters(t *testing.T, th *SearchTestHelper) { 883 creationDate := model.GetMillisForTime(time.Date(2020, 03, 01, 12, 0, 0, 0, time.UTC)) 884 p1, err := th.createPost(th.User.Id, th.ChannelPrivate.Id, "one two three message", "", model.POST_DEFAULT, creationDate, false) 885 require.NoError(t, err) 886 creationDate2 := model.GetMillisForTime(time.Date(2020, 03, 10, 12, 0, 0, 0, time.UTC)) 887 p2, err := th.createPost(th.User2.Id, th.ChannelPrivate.Id, "two messages", "", model.POST_DEFAULT, creationDate2, false) 888 require.NoError(t, err) 889 creationDate3 := model.GetMillisForTime(time.Date(2020, 03, 20, 12, 0, 0, 0, time.UTC)) 890 p3, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "two another message", "", model.POST_DEFAULT, creationDate3, false) 891 require.NoError(t, err) 892 defer th.deleteUserPosts(th.User.Id) 893 defer th.deleteUserPosts(th.User2.Id) 894 895 t.Run("Should search combining from user and in channel filters", func(t *testing.T) { 896 params := &model.SearchParams{ 897 Terms: "two", 898 FromUsers: []string{th.User2.Id}, 899 InChannels: []string{th.ChannelPrivate.Id}, 900 } 901 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 902 require.NoError(t, err) 903 904 require.Len(t, results.Posts, 1) 905 th.checkPostInSearchResults(t, p2.Id, results.Posts) 906 }) 907 908 t.Run("Should search combining excluding users and in channel filters", func(t *testing.T) { 909 params := &model.SearchParams{ 910 Terms: "two", 911 ExcludedUsers: []string{th.User2.Id}, 912 InChannels: []string{th.ChannelPrivate.Id}, 913 } 914 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 915 require.NoError(t, err) 916 917 require.Len(t, results.Posts, 1) 918 th.checkPostInSearchResults(t, p1.Id, results.Posts) 919 }) 920 921 t.Run("Should search combining excluding dates and in channel filters", func(t *testing.T) { 922 params := &model.SearchParams{ 923 Terms: "two", 924 ExcludedBeforeDate: "2020-03-09", 925 ExcludedAfterDate: "2020-03-11", 926 InChannels: []string{th.ChannelPrivate.Id}, 927 } 928 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 929 require.NoError(t, err) 930 931 require.Len(t, results.Posts, 1) 932 th.checkPostInSearchResults(t, p2.Id, results.Posts) 933 }) 934 t.Run("Should search combining excluding dates and in channel filters", func(t *testing.T) { 935 params := &model.SearchParams{ 936 Terms: "two", 937 AfterDate: "2020-03-11", 938 ExcludedChannels: []string{th.ChannelPrivate.Id}, 939 } 940 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 941 require.NoError(t, err) 942 943 require.Len(t, results.Posts, 1) 944 th.checkPostInSearchResults(t, p3.Id, results.Posts) 945 }) 946 } 947 948 func testSearchIgnoringStopWords(t *testing.T, th *SearchTestHelper) { 949 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "the search for a bunch of stop words", "", model.POST_DEFAULT, 0, false) 950 require.NoError(t, err) 951 p2, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "the objective is to avoid a bunch of stop words", "", model.POST_DEFAULT, 0, false) 952 require.NoError(t, err) 953 p3, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "in the a on to where you", "", model.POST_DEFAULT, 0, false) 954 require.NoError(t, err) 955 p4, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "where is the car?", "", model.POST_DEFAULT, 0, false) 956 require.NoError(t, err) 957 defer th.deleteUserPosts(th.User.Id) 958 959 t.Run("Should avoid stop word 'the'", func(t *testing.T) { 960 params := &model.SearchParams{ 961 Terms: "the search", 962 } 963 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 964 require.NoError(t, err) 965 966 require.Len(t, results.Posts, 1) 967 th.checkPostInSearchResults(t, p1.Id, results.Posts) 968 }) 969 970 t.Run("Should avoid stop word 'a'", func(t *testing.T) { 971 params := &model.SearchParams{ 972 Terms: "a avoid", 973 } 974 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 975 require.NoError(t, err) 976 977 require.Len(t, results.Posts, 1) 978 th.checkPostInSearchResults(t, p2.Id, results.Posts) 979 }) 980 981 t.Run("Should avoid stop word 'in'", func(t *testing.T) { 982 params := &model.SearchParams{ 983 Terms: "in where you", 984 } 985 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 986 require.NoError(t, err) 987 988 require.Len(t, results.Posts, 1) 989 th.checkPostInSearchResults(t, p3.Id, results.Posts) 990 }) 991 992 t.Run("Should avoid stop words 'where', 'is' and 'the'", func(t *testing.T) { 993 results, err := th.Store.Post().Search(th.Team.Id, th.User.Id, &model.SearchParams{Terms: "where is the car"}) 994 require.NoError(t, err) 995 require.Len(t, results.Posts, 1) 996 th.checkPostInSearchResults(t, p4.Id, results.Posts) 997 }) 998 999 t.Run("Should remove all terms and return empty list", func(t *testing.T) { 1000 results, err := th.Store.Post().Search(th.Team.Id, th.User.Id, &model.SearchParams{Terms: "where is the"}) 1001 require.NoError(t, err) 1002 require.Empty(t, results.Posts) 1003 }) 1004 } 1005 1006 func testSupportStemming(t *testing.T, th *SearchTestHelper) { 1007 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "search post", "", model.POST_DEFAULT, 0, false) 1008 require.NoError(t, err) 1009 p2, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "searching post", "", model.POST_DEFAULT, 0, false) 1010 require.NoError(t, err) 1011 _, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "another post", "", model.POST_DEFAULT, 0, false) 1012 require.NoError(t, err) 1013 defer th.deleteUserPosts(th.User.Id) 1014 1015 params := &model.SearchParams{ 1016 Terms: "search", 1017 } 1018 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1019 require.NoError(t, err) 1020 1021 require.Len(t, results.Posts, 2) 1022 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1023 th.checkPostInSearchResults(t, p2.Id, results.Posts) 1024 } 1025 1026 func testSupportWildcards(t *testing.T, th *SearchTestHelper) { 1027 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "search post", "", model.POST_DEFAULT, 0, false) 1028 require.NoError(t, err) 1029 p2, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "searching", "", model.POST_DEFAULT, 0, false) 1030 require.NoError(t, err) 1031 _, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "another post", "", model.POST_DEFAULT, 0, false) 1032 require.NoError(t, err) 1033 defer th.deleteUserPosts(th.User.Id) 1034 1035 t.Run("Simple wildcard-only search", func(t *testing.T) { 1036 params := &model.SearchParams{ 1037 Terms: "search*", 1038 } 1039 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1040 require.NoError(t, err) 1041 1042 require.Len(t, results.Posts, 2) 1043 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1044 th.checkPostInSearchResults(t, p2.Id, results.Posts) 1045 }) 1046 1047 t.Run("Wildcard search with another term placed after", func(t *testing.T) { 1048 params := &model.SearchParams{ 1049 Terms: "sear* post", 1050 } 1051 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1052 require.NoError(t, err) 1053 1054 require.Len(t, results.Posts, 1) 1055 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1056 }) 1057 } 1058 1059 func testNotSupportPrecedingWildcards(t *testing.T, th *SearchTestHelper) { 1060 _, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "search post", "", model.POST_DEFAULT, 0, false) 1061 require.NoError(t, err) 1062 _, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "searching post", "", model.POST_DEFAULT, 0, false) 1063 require.NoError(t, err) 1064 _, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "another post", "", model.POST_DEFAULT, 0, false) 1065 require.NoError(t, err) 1066 defer th.deleteUserPosts(th.User.Id) 1067 1068 params := &model.SearchParams{ 1069 Terms: "*earch", 1070 } 1071 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1072 require.NoError(t, err) 1073 1074 require.Len(t, results.Posts, 0) 1075 } 1076 1077 func testSearchDiscardWildcardAlone(t *testing.T, th *SearchTestHelper) { 1078 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "qwerty", "", model.POST_DEFAULT, 0, false) 1079 require.NoError(t, err) 1080 _, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "qwertyjkl", "", model.POST_DEFAULT, 0, false) 1081 require.NoError(t, err) 1082 defer th.deleteUserPosts(th.User.Id) 1083 1084 params := &model.SearchParams{ 1085 Terms: "qwerty *", 1086 } 1087 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1088 require.NoError(t, err) 1089 1090 require.Len(t, results.Posts, 1) 1091 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1092 } 1093 1094 func testSupportTermsWithDash(t *testing.T, th *SearchTestHelper) { 1095 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "search term-with-dash", "", model.POST_DEFAULT, 0, false) 1096 require.NoError(t, err) 1097 _, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "searching term with dash", "", model.POST_DEFAULT, 0, false) 1098 require.NoError(t, err) 1099 defer th.deleteUserPosts(th.User.Id) 1100 1101 t.Run("Should search terms with dash", func(t *testing.T) { 1102 params := &model.SearchParams{ 1103 Terms: "term-with-dash", 1104 } 1105 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1106 require.NoError(t, err) 1107 1108 require.Len(t, results.Posts, 1) 1109 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1110 }) 1111 1112 t.Run("Should search terms with dash using quotes", func(t *testing.T) { 1113 params := &model.SearchParams{ 1114 Terms: "\"term-with-dash\"", 1115 } 1116 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1117 require.NoError(t, err) 1118 1119 require.Len(t, results.Posts, 1) 1120 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1121 }) 1122 } 1123 1124 func testSupportTermsWithUnderscore(t *testing.T, th *SearchTestHelper) { 1125 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "search term_with_underscore", "", model.POST_DEFAULT, 0, false) 1126 require.NoError(t, err) 1127 _, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "searching term with underscore", "", model.POST_DEFAULT, 0, false) 1128 require.NoError(t, err) 1129 defer th.deleteUserPosts(th.User.Id) 1130 1131 t.Run("Should search terms with underscore", func(t *testing.T) { 1132 params := &model.SearchParams{ 1133 Terms: "term_with_underscore", 1134 } 1135 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1136 require.NoError(t, err) 1137 1138 require.Len(t, results.Posts, 1) 1139 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1140 }) 1141 1142 t.Run("Should search terms with underscore using quotes", func(t *testing.T) { 1143 params := &model.SearchParams{ 1144 Terms: "\"term_with_underscore\"", 1145 } 1146 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1147 require.NoError(t, err) 1148 1149 require.Len(t, results.Posts, 1) 1150 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1151 }) 1152 } 1153 1154 func testSearchOrExcludePostsWithHashtags(t *testing.T, th *SearchTestHelper) { 1155 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "search post with #hashtag", "#hashtag", model.POST_DEFAULT, 0, false) 1156 require.NoError(t, err) 1157 p2, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "searching term with hashtag", "", model.POST_DEFAULT, 0, false) 1158 require.NoError(t, err) 1159 p3, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "searching term with", "#hashtag", model.POST_DEFAULT, 0, false) 1160 require.NoError(t, err) 1161 defer th.deleteUserPosts(th.User.Id) 1162 1163 t.Run("Should search terms with hashtags", func(t *testing.T) { 1164 params := &model.SearchParams{ 1165 Terms: "#hashtag", 1166 IsHashtag: true, 1167 } 1168 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1169 require.NoError(t, err) 1170 1171 require.Len(t, results.Posts, 2) 1172 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1173 th.checkPostInSearchResults(t, p3.Id, results.Posts) 1174 }) 1175 1176 t.Run("Should search hashtag terms without hashtag option", func(t *testing.T) { 1177 params := &model.SearchParams{ 1178 Terms: "#hashtag", 1179 IsHashtag: false, 1180 } 1181 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1182 require.NoError(t, err) 1183 1184 require.Len(t, results.Posts, 2) 1185 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1186 th.checkPostInSearchResults(t, p2.Id, results.Posts) 1187 }) 1188 } 1189 1190 func testSearchHashtagWithMarkdown(t *testing.T, th *SearchTestHelper) { 1191 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "searching hashtag #hashtag", "#hashtag", model.POST_DEFAULT, 0, false) 1192 require.NoError(t, err) 1193 p2, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "searching term with `#hashtag`", "#hashtag", model.POST_DEFAULT, 0, false) 1194 require.NoError(t, err) 1195 p3, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "searching term with **#hashtag**", "#hashtag", model.POST_DEFAULT, 0, false) 1196 require.NoError(t, err) 1197 p4, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "searching term with ~~#hashtag~~", "#hashtag", model.POST_DEFAULT, 0, false) 1198 require.NoError(t, err) 1199 p5, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "searching term with _#hashtag_", "#hashtag", model.POST_DEFAULT, 0, false) 1200 require.NoError(t, err) 1201 defer th.deleteUserPosts(th.User.Id) 1202 1203 params := &model.SearchParams{ 1204 Terms: "#hashtag", 1205 IsHashtag: true, 1206 } 1207 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1208 require.NoError(t, err) 1209 1210 require.Len(t, results.Posts, 5) 1211 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1212 th.checkPostInSearchResults(t, p2.Id, results.Posts) 1213 th.checkPostInSearchResults(t, p3.Id, results.Posts) 1214 th.checkPostInSearchResults(t, p4.Id, results.Posts) 1215 th.checkPostInSearchResults(t, p5.Id, results.Posts) 1216 } 1217 1218 func testSearcWithMultipleHashtags(t *testing.T, th *SearchTestHelper) { 1219 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "searching hashtag #hashtag", "#hashtwo #hashone", model.POST_DEFAULT, 0, false) 1220 require.NoError(t, err) 1221 p2, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "searching term with `#hashtag`", "#hashtwo #hashthree", model.POST_DEFAULT, 0, false) 1222 require.NoError(t, err) 1223 defer th.deleteUserPosts(th.User.Id) 1224 1225 t.Run("Should search posts with multiple hashtags", func(t *testing.T) { 1226 params := &model.SearchParams{ 1227 Terms: "#hashone #hashtwo", 1228 IsHashtag: true, 1229 } 1230 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1231 require.NoError(t, err) 1232 1233 require.Len(t, results.Posts, 1) 1234 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1235 }) 1236 1237 t.Run("Should search posts with multiple hashtags using OR", func(t *testing.T) { 1238 params := &model.SearchParams{ 1239 Terms: "#hashone #hashtwo", 1240 IsHashtag: true, 1241 OrTerms: true, 1242 } 1243 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1244 require.NoError(t, err) 1245 1246 require.Len(t, results.Posts, 2) 1247 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1248 th.checkPostInSearchResults(t, p2.Id, results.Posts) 1249 }) 1250 } 1251 1252 func testSearchPostsWithDotsInHashtags(t *testing.T, th *SearchTestHelper) { 1253 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "searching hashtag #hashtag.dot", "#hashtag.dot", model.POST_DEFAULT, 0, false) 1254 require.NoError(t, err) 1255 defer th.deleteUserPosts(th.User.Id) 1256 1257 params := &model.SearchParams{ 1258 Terms: "#hashtag.dot", 1259 IsHashtag: true, 1260 } 1261 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1262 require.NoError(t, err) 1263 1264 require.Len(t, results.Posts, 1) 1265 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1266 } 1267 1268 func testSearchHashtagCaseInsensitive(t *testing.T, th *SearchTestHelper) { 1269 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "searching hashtag #HaShTaG", "#HaShTaG", model.POST_DEFAULT, 0, false) 1270 require.NoError(t, err) 1271 p2, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "searching hashtag #hashtag", "#hashtag", model.POST_DEFAULT, 0, false) 1272 require.NoError(t, err) 1273 p3, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "searching hashtag #HASHTAG", "#HASHTAG", model.POST_DEFAULT, 0, false) 1274 require.NoError(t, err) 1275 defer th.deleteUserPosts(th.User.Id) 1276 1277 t.Run("Lower case hashtag", func(t *testing.T) { 1278 params := &model.SearchParams{ 1279 Terms: "#hashtag", 1280 IsHashtag: true, 1281 } 1282 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1283 require.NoError(t, err) 1284 1285 require.Len(t, results.Posts, 3) 1286 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1287 th.checkPostInSearchResults(t, p2.Id, results.Posts) 1288 th.checkPostInSearchResults(t, p3.Id, results.Posts) 1289 }) 1290 1291 t.Run("Upper case hashtag", func(t *testing.T) { 1292 params := &model.SearchParams{ 1293 Terms: "#HASHTAG", 1294 IsHashtag: true, 1295 } 1296 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1297 require.NoError(t, err) 1298 1299 require.Len(t, results.Posts, 3) 1300 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1301 th.checkPostInSearchResults(t, p2.Id, results.Posts) 1302 th.checkPostInSearchResults(t, p3.Id, results.Posts) 1303 }) 1304 1305 t.Run("Mixed case hashtag", func(t *testing.T) { 1306 params := &model.SearchParams{ 1307 Terms: "#HaShTaG", 1308 IsHashtag: true, 1309 } 1310 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1311 require.NoError(t, err) 1312 1313 require.Len(t, results.Posts, 3) 1314 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1315 th.checkPostInSearchResults(t, p2.Id, results.Posts) 1316 th.checkPostInSearchResults(t, p3.Id, results.Posts) 1317 }) 1318 } 1319 1320 func testSearchHashtagWithDash(t *testing.T, th *SearchTestHelper) { 1321 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "searching hashtag #hashtag-test", "#hashtag-test", model.POST_DEFAULT, 0, false) 1322 require.NoError(t, err) 1323 _, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "searching hashtag #hashtagtest", "#hashtagtest", model.POST_DEFAULT, 0, false) 1324 require.NoError(t, err) 1325 defer th.deleteUserPosts(th.User.Id) 1326 1327 params := &model.SearchParams{ 1328 Terms: "#hashtag-test", 1329 IsHashtag: true, 1330 } 1331 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1332 require.NoError(t, err) 1333 1334 require.Len(t, results.Posts, 1) 1335 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1336 } 1337 1338 func testSearchHashtagWithNumbers(t *testing.T, th *SearchTestHelper) { 1339 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "searching hashtag #h4sht4g", "#h4sht4g", model.POST_DEFAULT, 0, false) 1340 require.NoError(t, err) 1341 _, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "searching hashtag #hashtag", "#hashtag", model.POST_DEFAULT, 0, false) 1342 require.NoError(t, err) 1343 defer th.deleteUserPosts(th.User.Id) 1344 1345 params := &model.SearchParams{ 1346 Terms: "#h4sht4g", 1347 IsHashtag: true, 1348 } 1349 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1350 require.NoError(t, err) 1351 1352 require.Len(t, results.Posts, 1) 1353 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1354 } 1355 1356 func testSearchHashtagWithDots(t *testing.T, th *SearchTestHelper) { 1357 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "searching hashtag #hashtag.test", "#hashtag.test", model.POST_DEFAULT, 0, false) 1358 require.NoError(t, err) 1359 _, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "searching hashtag #hashtagtest", "#hashtagtest", model.POST_DEFAULT, 0, false) 1360 require.NoError(t, err) 1361 defer th.deleteUserPosts(th.User.Id) 1362 1363 params := &model.SearchParams{ 1364 Terms: "#hashtag.test", 1365 IsHashtag: true, 1366 } 1367 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1368 require.NoError(t, err) 1369 1370 require.Len(t, results.Posts, 1) 1371 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1372 } 1373 1374 func testSearchHashtagWithUnderscores(t *testing.T, th *SearchTestHelper) { 1375 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "searching hashtag #hashtag_test", "#hashtag_test", model.POST_DEFAULT, 0, false) 1376 require.NoError(t, err) 1377 _, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "searching hashtag #hashtagtest", "#hashtagtest", model.POST_DEFAULT, 0, false) 1378 require.NoError(t, err) 1379 defer th.deleteUserPosts(th.User.Id) 1380 1381 params := &model.SearchParams{ 1382 Terms: "#hashtag_test", 1383 IsHashtag: true, 1384 } 1385 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1386 require.NoError(t, err) 1387 1388 require.Len(t, results.Posts, 1) 1389 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1390 } 1391 1392 func testSearchShouldExcludeSytemMessages(t *testing.T, th *SearchTestHelper) { 1393 _, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "test system message one", "", model.POST_JOIN_CHANNEL, 0, false) 1394 require.NoError(t, err) 1395 _, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "test system message two", "", model.POST_LEAVE_CHANNEL, 0, false) 1396 require.NoError(t, err) 1397 _, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "test system message three", "", model.POST_LEAVE_TEAM, 0, false) 1398 require.NoError(t, err) 1399 _, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "test system message four", "", model.POST_ADD_TO_CHANNEL, 0, false) 1400 require.NoError(t, err) 1401 _, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "test system message five", "", model.POST_ADD_TO_TEAM, 0, false) 1402 require.NoError(t, err) 1403 _, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "test system message six", "", model.POST_HEADER_CHANGE, 0, false) 1404 require.NoError(t, err) 1405 defer th.deleteUserPosts(th.User.Id) 1406 1407 params := &model.SearchParams{Terms: "test system"} 1408 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1409 require.NoError(t, err) 1410 1411 require.Len(t, results.Posts, 0) 1412 } 1413 1414 func testSearchShouldBeAbleToMatchByMentions(t *testing.T, th *SearchTestHelper) { 1415 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "test system @testuser", "", model.POST_DEFAULT, 0, false) 1416 require.NoError(t, err) 1417 p2, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "test system testuser", "", model.POST_DEFAULT, 0, false) 1418 require.NoError(t, err) 1419 p3, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "test system #testuser", "#testuser", model.POST_DEFAULT, 0, false) 1420 require.NoError(t, err) 1421 defer th.deleteUserPosts(th.User.Id) 1422 1423 params := &model.SearchParams{Terms: "@testuser"} 1424 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1425 require.NoError(t, err) 1426 1427 require.Len(t, results.Posts, 3) 1428 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1429 th.checkPostInSearchResults(t, p2.Id, results.Posts) 1430 th.checkPostInSearchResults(t, p3.Id, results.Posts) 1431 } 1432 1433 func testSearchInDeletedOrArchivedChannels(t *testing.T, th *SearchTestHelper) { 1434 p1, err := th.createPost(th.User.Id, th.ChannelDeleted.Id, "message in deleted channel", "", model.POST_DEFAULT, 0, false) 1435 require.NoError(t, err) 1436 p2, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "message in regular channel", "", model.POST_DEFAULT, 0, false) 1437 require.NoError(t, err) 1438 p3, err := th.createPost(th.User.Id, th.ChannelPrivate.Id, "message in private channel", "", model.POST_DEFAULT, 0, false) 1439 require.NoError(t, err) 1440 defer th.deleteUserPosts(th.User.Id) 1441 1442 t.Run("Doesn't include posts in deleted channels", func(t *testing.T) { 1443 params := &model.SearchParams{Terms: "message", IncludeDeletedChannels: false} 1444 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1445 require.NoError(t, err) 1446 1447 require.Len(t, results.Posts, 2) 1448 th.checkPostInSearchResults(t, p2.Id, results.Posts) 1449 th.checkPostInSearchResults(t, p3.Id, results.Posts) 1450 }) 1451 1452 t.Run("Include posts in deleted channels", func(t *testing.T) { 1453 params := &model.SearchParams{Terms: "message", IncludeDeletedChannels: true} 1454 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1455 require.NoError(t, err) 1456 1457 require.Len(t, results.Posts, 3) 1458 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1459 th.checkPostInSearchResults(t, p2.Id, results.Posts) 1460 th.checkPostInSearchResults(t, p3.Id, results.Posts) 1461 }) 1462 1463 t.Run("Include posts in deleted channels using multiple terms", func(t *testing.T) { 1464 params := &model.SearchParams{Terms: "message channel", IncludeDeletedChannels: true} 1465 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1466 require.NoError(t, err) 1467 1468 require.Len(t, results.Posts, 3) 1469 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1470 th.checkPostInSearchResults(t, p2.Id, results.Posts) 1471 th.checkPostInSearchResults(t, p3.Id, results.Posts) 1472 }) 1473 1474 t.Run("Include posts in deleted channels using multiple OR terms", func(t *testing.T) { 1475 params := &model.SearchParams{ 1476 Terms: "message channel", 1477 IncludeDeletedChannels: true, 1478 OrTerms: true, 1479 } 1480 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1481 require.NoError(t, err) 1482 1483 require.Len(t, results.Posts, 3) 1484 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1485 th.checkPostInSearchResults(t, p2.Id, results.Posts) 1486 th.checkPostInSearchResults(t, p3.Id, results.Posts) 1487 }) 1488 1489 t.Run("All IncludeDeletedChannels params should have same value if multiple SearchParams provided", func(t *testing.T) { 1490 params1 := &model.SearchParams{ 1491 Terms: "message channel", 1492 IncludeDeletedChannels: true, 1493 } 1494 params2 := &model.SearchParams{ 1495 Terms: "#hashtag", 1496 IncludeDeletedChannels: false, 1497 } 1498 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params1, params2}, th.User.Id, th.Team.Id, 0, 20) 1499 require.Nil(t, results) 1500 require.Error(t, err) 1501 }) 1502 } 1503 1504 func testSearchTermsWithDashes(t *testing.T, th *SearchTestHelper) { 1505 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "message with-dash-term", "", model.POST_DEFAULT, 0, false) 1506 require.NoError(t, err) 1507 p2, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "message with dash term", "", model.POST_DEFAULT, 0, false) 1508 require.NoError(t, err) 1509 defer th.deleteUserPosts(th.User.Id) 1510 1511 t.Run("Search for terms with dash", func(t *testing.T) { 1512 params := &model.SearchParams{Terms: "with-dash-term"} 1513 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1514 require.NoError(t, err) 1515 1516 require.Len(t, results.Posts, 1) 1517 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1518 }) 1519 1520 t.Run("Search for terms with quoted dash", func(t *testing.T) { 1521 params := &model.SearchParams{Terms: "\"with-dash-term\""} 1522 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1523 require.NoError(t, err) 1524 1525 require.Len(t, results.Posts, 1) 1526 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1527 }) 1528 1529 t.Run("Search for multiple terms with one having dash", func(t *testing.T) { 1530 params := &model.SearchParams{Terms: "with-dash-term message"} 1531 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1532 require.NoError(t, err) 1533 1534 require.Len(t, results.Posts, 1) 1535 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1536 }) 1537 1538 t.Run("Search for multiple OR terms with one having dash", func(t *testing.T) { 1539 params := &model.SearchParams{Terms: "with-dash-term message", OrTerms: true} 1540 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1541 require.NoError(t, err) 1542 1543 require.Len(t, results.Posts, 2) 1544 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1545 th.checkPostInSearchResults(t, p2.Id, results.Posts) 1546 }) 1547 } 1548 1549 func testSearchTermsWithDots(t *testing.T, th *SearchTestHelper) { 1550 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "message with.dots.term", "", model.POST_DEFAULT, 0, false) 1551 require.NoError(t, err) 1552 p2, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "message with dots term", "", model.POST_DEFAULT, 0, false) 1553 require.NoError(t, err) 1554 defer th.deleteUserPosts(th.User.Id) 1555 1556 t.Run("Search for terms with dots", func(t *testing.T) { 1557 params := &model.SearchParams{Terms: "with.dots.term"} 1558 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1559 require.NoError(t, err) 1560 1561 require.Len(t, results.Posts, 1) 1562 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1563 }) 1564 1565 t.Run("Search for terms with quoted dots", func(t *testing.T) { 1566 params := &model.SearchParams{Terms: "\"with.dots.term\""} 1567 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1568 require.NoError(t, err) 1569 1570 require.Len(t, results.Posts, 1) 1571 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1572 }) 1573 1574 t.Run("Search for multiple terms with one having dots", func(t *testing.T) { 1575 params := &model.SearchParams{Terms: "with.dots.term message"} 1576 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1577 require.NoError(t, err) 1578 1579 require.Len(t, results.Posts, 1) 1580 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1581 }) 1582 1583 t.Run("Search for multiple OR terms with one having dots", func(t *testing.T) { 1584 params := &model.SearchParams{Terms: "with.dots.term message", OrTerms: true} 1585 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1586 require.NoError(t, err) 1587 1588 require.Len(t, results.Posts, 2) 1589 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1590 th.checkPostInSearchResults(t, p2.Id, results.Posts) 1591 }) 1592 } 1593 1594 func testSearchTermsWithUnderscores(t *testing.T, th *SearchTestHelper) { 1595 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "message with_underscores_term", "", model.POST_DEFAULT, 0, false) 1596 require.NoError(t, err) 1597 p2, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "message with underscores term", "", model.POST_DEFAULT, 0, false) 1598 require.NoError(t, err) 1599 defer th.deleteUserPosts(th.User.Id) 1600 1601 t.Run("Search for terms with underscores", func(t *testing.T) { 1602 params := &model.SearchParams{Terms: "with_underscores_term"} 1603 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1604 require.NoError(t, err) 1605 1606 require.Len(t, results.Posts, 1) 1607 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1608 }) 1609 1610 t.Run("Search for terms with quoted underscores", func(t *testing.T) { 1611 params := &model.SearchParams{Terms: "\"with_underscores_term\""} 1612 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1613 require.NoError(t, err) 1614 1615 require.Len(t, results.Posts, 1) 1616 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1617 }) 1618 1619 t.Run("Search for multiple terms with one having underscores", func(t *testing.T) { 1620 params := &model.SearchParams{Terms: "with_underscores_term message"} 1621 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1622 require.NoError(t, err) 1623 1624 require.Len(t, results.Posts, 1) 1625 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1626 }) 1627 1628 t.Run("Search for multiple OR terms with one having underscores", func(t *testing.T) { 1629 params := &model.SearchParams{Terms: "with_underscores_term message", OrTerms: true} 1630 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1631 require.NoError(t, err) 1632 1633 require.Len(t, results.Posts, 2) 1634 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1635 th.checkPostInSearchResults(t, p2.Id, results.Posts) 1636 }) 1637 } 1638 1639 func testSearchBotAccountsPosts(t *testing.T, th *SearchTestHelper) { 1640 bot, err := th.createBot("testbot", "Test Bot", th.User.Id) 1641 require.NoError(t, err) 1642 defer th.deleteBot(bot.UserId) 1643 err = th.addUserToTeams(model.UserFromBot(bot), []string{th.Team.Id}) 1644 require.NoError(t, err) 1645 p1, err := th.createPost(bot.UserId, th.ChannelBasic.Id, "bot test message", "", model.POST_DEFAULT, 0, false) 1646 require.NoError(t, err) 1647 p2, err := th.createPost(bot.UserId, th.ChannelPrivate.Id, "bot test message in private", "", model.POST_DEFAULT, 0, false) 1648 require.NoError(t, err) 1649 defer th.deleteUserPosts(bot.UserId) 1650 1651 params := &model.SearchParams{Terms: "bot"} 1652 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1653 require.NoError(t, err) 1654 1655 require.Len(t, results.Posts, 2) 1656 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1657 th.checkPostInSearchResults(t, p2.Id, results.Posts) 1658 } 1659 1660 func testSupportStemmingAndWildcards(t *testing.T, th *SearchTestHelper) { 1661 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "approve", "", model.POST_DEFAULT, 0, false) 1662 require.NoError(t, err) 1663 p2, err := th.createPost(th.User.Id, th.ChannelPrivate.Id, "approved", "", model.POST_DEFAULT, 0, false) 1664 require.NoError(t, err) 1665 p3, err := th.createPost(th.User.Id, th.ChannelPrivate.Id, "approvedz", "", model.POST_DEFAULT, 0, false) 1666 require.NoError(t, err) 1667 defer th.deleteUserPosts(th.User.Id) 1668 1669 t.Run("Should stem appr", func(t *testing.T) { 1670 params := &model.SearchParams{Terms: "appr*"} 1671 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1672 require.NoError(t, err) 1673 1674 require.Len(t, results.Posts, 3) 1675 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1676 th.checkPostInSearchResults(t, p2.Id, results.Posts) 1677 th.checkPostInSearchResults(t, p3.Id, results.Posts) 1678 }) 1679 1680 t.Run("Should stem approve", func(t *testing.T) { 1681 params := &model.SearchParams{Terms: "approve*"} 1682 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1683 require.NoError(t, err) 1684 1685 require.Len(t, results.Posts, 1) 1686 th.checkPostInSearchResults(t, p3.Id, results.Posts) 1687 }) 1688 } 1689 1690 func testSupportWildcardOutsideQuotes(t *testing.T, th *SearchTestHelper) { 1691 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "hello world", "", model.POST_DEFAULT, 0, false) 1692 require.NoError(t, err) 1693 p2, err := th.createPost(th.User.Id, th.ChannelPrivate.Id, "hell or heaven", "", model.POST_DEFAULT, 0, false) 1694 require.NoError(t, err) 1695 defer th.deleteUserPosts(th.User.Id) 1696 1697 t.Run("Should return results without quotes", func(t *testing.T) { 1698 params := &model.SearchParams{Terms: "hell*"} 1699 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1700 require.NoError(t, err) 1701 1702 require.Len(t, results.Posts, 2) 1703 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1704 th.checkPostInSearchResults(t, p2.Id, results.Posts) 1705 }) 1706 1707 t.Run("Should return just one result with quotes", func(t *testing.T) { 1708 params := &model.SearchParams{Terms: "\"hell\"*"} 1709 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1710 require.NoError(t, err) 1711 1712 require.Len(t, results.Posts, 1) 1713 th.checkPostInSearchResults(t, p2.Id, results.Posts) 1714 }) 1715 1716 } 1717 1718 func testHashtagSearchShouldSupportThreeOrMoreCharacters(t *testing.T, th *SearchTestHelper) { 1719 _, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "one char hashtag #1", "#1", model.POST_DEFAULT, 0, false) 1720 require.NoError(t, err) 1721 _, err = th.createPost(th.User.Id, th.ChannelPrivate.Id, "two chars hashtag #12", "#12", model.POST_DEFAULT, 0, false) 1722 require.NoError(t, err) 1723 p3, err := th.createPost(th.User.Id, th.ChannelPrivate.Id, "three chars hashtag #123", "#123", model.POST_DEFAULT, 0, false) 1724 require.NoError(t, err) 1725 defer th.deleteUserPosts(th.User.Id) 1726 1727 params := &model.SearchParams{Terms: "#123", IsHashtag: true} 1728 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1729 require.NoError(t, err) 1730 1731 require.Len(t, results.Posts, 1) 1732 th.checkPostInSearchResults(t, p3.Id, results.Posts) 1733 } 1734 1735 func testSlashShouldNotBeCharSeparator(t *testing.T, th *SearchTestHelper) { 1736 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "alpha/beta gamma, theta", "", model.POST_DEFAULT, 0, false) 1737 require.NoError(t, err) 1738 defer th.deleteUserPosts(th.User.Id) 1739 1740 params := &model.SearchParams{Terms: "gamma"} 1741 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1742 require.NoError(t, err) 1743 1744 require.Len(t, results.Posts, 1) 1745 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1746 1747 params = &model.SearchParams{Terms: "beta"} 1748 results, err = th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1749 require.NoError(t, err) 1750 1751 require.Len(t, results.Posts, 1) 1752 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1753 1754 params = &model.SearchParams{Terms: "alpha"} 1755 results, err = th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1756 require.NoError(t, err) 1757 1758 require.Len(t, results.Posts, 1) 1759 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1760 } 1761 1762 func testSearchEmailsWithoutQuotes(t *testing.T, th *SearchTestHelper) { 1763 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "message test@test.com", "", model.POST_DEFAULT, 0, false) 1764 require.NoError(t, err) 1765 _, err = th.createPost(th.User.Id, th.ChannelBasic.Id, "message test2@test.com", "", model.POST_DEFAULT, 0, false) 1766 require.NoError(t, err) 1767 defer th.deleteUserPosts(th.User.Id) 1768 1769 params := &model.SearchParams{Terms: "test@test.com"} 1770 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1771 require.NoError(t, err) 1772 1773 require.Len(t, results.Posts, 1) 1774 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1775 } 1776 1777 func testSupportSearchInComments(t *testing.T, th *SearchTestHelper) { 1778 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "message test@test.com", "", model.POST_DEFAULT, 0, false) 1779 require.NoError(t, err) 1780 r1, err := th.createReply(th.User.Id, "reply check", "", p1, 0, false) 1781 require.NoError(t, err) 1782 defer th.deleteUserPosts(th.User.Id) 1783 1784 params := &model.SearchParams{Terms: "reply"} 1785 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1786 require.NoError(t, err) 1787 1788 require.Len(t, results.Posts, 1) 1789 th.checkPostInSearchResults(t, r1.Id, results.Posts) 1790 } 1791 1792 func testSupportSearchTermsWithinLinks(t *testing.T, th *SearchTestHelper) { 1793 p1, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "message with link http://www.wikipedia.org/dolphins", "", model.POST_DEFAULT, 0, false) 1794 require.NoError(t, err) 1795 defer th.deleteUserPosts(th.User.Id) 1796 1797 params := &model.SearchParams{Terms: "wikipedia"} 1798 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1799 require.NoError(t, err) 1800 1801 require.Len(t, results.Posts, 1) 1802 th.checkPostInSearchResults(t, p1.Id, results.Posts) 1803 } 1804 1805 func testShouldNotReturnLinksEmbeddedInMarkdown(t *testing.T, th *SearchTestHelper) { 1806 _, err := th.createPost(th.User.Id, th.ChannelBasic.Id, "message with link [here](http://www.wikipedia.org/dolphins)", "", model.POST_DEFAULT, 0, false) 1807 require.NoError(t, err) 1808 defer th.deleteUserPosts(th.User.Id) 1809 1810 params := &model.SearchParams{Terms: "wikipedia"} 1811 results, err := th.Store.Post().SearchPostsInTeamForUser([]*model.SearchParams{params}, th.User.Id, th.Team.Id, 0, 20) 1812 require.NoError(t, err) 1813 1814 require.Len(t, results.Posts, 0) 1815 }