From 42806ae965b861955235698f247df862fd655d09 Mon Sep 17 00:00:00 2001 From: Dmitry Samuylov Date: Tue, 28 Aug 2018 13:09:32 -0400 Subject: Feature/search after before on (#9219) * initial implementation of after, before, on search flags allowing to restrict the search to a specific day or a date range * missed setting beforeDate in SearchParams in one place * fixed condition when only flags are used for search without any plain terms * changed date format used for after/before/on flags to be in ISO8601 format as suggested in PR comments, added a helper function to pad month and day with zeroes allowing the user user either format, with or without leading zeroes * corrected expected compare to date setting for the TestParseDateFilterToTimeISO8601 test * fixed a bug for the scenario when you only have the date flags without any terms, added a couple of tests for that scenario * updated the date filter logic to use parameters to construct the query instead of simply appending strings together, as suggested in the pull request comments * added search unit test using date flags * added a helper function to create a test post with a createat date manually set, updated the test for search using date flags to create test posts with different createat dates to be able to better test the functionality * MM-11817 Add support for after/before/on search flags with Elasticsearch * add support to search posts to perform the search in context of the client's timezone when filtering by createat date using on: after: before: flags * updated tests to match the new signature --- api4/apitestlib.go | 11 +++++++ api4/post.go | 8 +++++- api4/post_test.go | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 100 insertions(+), 3 deletions(-) (limited to 'api4') diff --git a/api4/apitestlib.go b/api4/apitestlib.go index 652a8f882..6a717faf1 100644 --- a/api4/apitestlib.go +++ b/api4/apitestlib.go @@ -444,6 +444,17 @@ func (me *TestHelper) CreateMessagePostWithClient(client *model.Client4, channel return rpost } +func (me *TestHelper) CreateMessagePostNoClient(channel *model.Channel, message string, createAtTime int64) *model.Post { + post := store.Must(me.App.Srv.Store.Post().Save(&model.Post{ + UserId: me.BasicUser.Id, + ChannelId: channel.Id, + Message: message, + CreateAt: createAtTime, + })).(*model.Post) + + return post +} + func (me *TestHelper) LoginBasic() { me.LoginBasicWithClient(me.Client) } diff --git a/api4/post.go b/api4/post.go index b4edc5124..014174b37 100644 --- a/api4/post.go +++ b/api4/post.go @@ -333,17 +333,23 @@ func searchPosts(c *Context, w http.ResponseWriter, r *http.Request) { includeDeletedChannels := r.URL.Query().Get("include_deleted_channels") == "true" props := model.StringInterfaceFromJson(r.Body) + terms, ok := props["terms"].(string) if !ok || len(terms) == 0 { c.SetInvalidParam("terms") return } + timeZoneOffset, ok := props["time_zone_offset"].(float64) + if !ok { + timeZoneOffset = 0 + } + isOrSearch, _ := props["is_or_search"].(bool) startTime := time.Now() - results, err := c.App.SearchPostsInTeam(terms, c.Session.UserId, c.Params.TeamId, isOrSearch, includeDeletedChannels) + results, err := c.App.SearchPostsInTeam(terms, c.Session.UserId, c.Params.TeamId, isOrSearch, includeDeletedChannels, int(timeZoneOffset)) elapsedTime := float64(time.Since(startTime)) / float64(time.Second) metrics := c.App.Metrics diff --git a/api4/post_test.go b/api4/post_test.go index 910443fef..5f8cb5b31 100644 --- a/api4/post_test.go +++ b/api4/post_test.go @@ -17,6 +17,7 @@ import ( "github.com/mattermost/mattermost-server/app" "github.com/mattermost/mattermost-server/model" + "github.com/mattermost/mattermost-server/utils" ) func TestCreatePost(t *testing.T) { @@ -1302,7 +1303,21 @@ func TestSearchPosts(t *testing.T) { _ = th.CreateMessagePostWithClient(th.Client, archivedChannel, "#hashtag for post3") th.Client.DeleteChannel(archivedChannel.Id) - posts, resp := Client.SearchPosts(th.BasicTeam.Id, "search", false) + terms := "search" + isOrSearch := false + timezoneOffset := 5 + searchParams := model.SearchParameter{ + Terms: &terms, + IsOrSearch: &isOrSearch, + TimeZoneOffset: &timezoneOffset, + } + posts, resp := Client.SearchPostsWithParams(th.BasicTeam.Id, &searchParams) + CheckNoError(t, resp) + if len(posts.Order) != 3 { + t.Fatal("wrong search") + } + + posts, resp = Client.SearchPosts(th.BasicTeam.Id, "search", false) CheckNoError(t, resp) if len(posts.Order) != 3 { t.Fatal("wrong search") @@ -1329,7 +1344,7 @@ func TestSearchPosts(t *testing.T) { th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.ExperimentalViewArchivedChannels = false }) - + posts, resp = Client.SearchPostsIncludeDeletedChannels(th.BasicTeam.Id, "#hashtag", false) CheckNoError(t, resp) if len(posts.Order) != 1 { @@ -1516,6 +1531,71 @@ func TestSearchPostsFromUser(t *testing.T) { } } +func TestSearchPostsWithDateFlags(t *testing.T) { + th := Setup().InitBasic() + defer th.TearDown() + th.LoginBasic() + Client := th.Client + + message := "sgtitlereview\n with return" + createDate := time.Date(2018, 8, 1, 5, 0, 0, 0, time.UTC) + _ = th.CreateMessagePostNoClient(th.BasicChannel, message, utils.MillisFromTime(createDate)) + + message = "other message with no return" + createDate = time.Date(2018, 8, 2, 5, 0, 0, 0, time.UTC) + _ = th.CreateMessagePostNoClient(th.BasicChannel, message, utils.MillisFromTime(createDate)) + + message = "other message with no return" + createDate = time.Date(2018, 8, 3, 5, 0, 0, 0, time.UTC) + _ = th.CreateMessagePostNoClient(th.BasicChannel, message, utils.MillisFromTime(createDate)) + + posts, _ := Client.SearchPosts(th.BasicTeam.Id, "return", false) + if len(posts.Order) != 3 { + t.Fatalf("wrong number of posts returned %v", len(posts.Order)) + } + + posts, _ = Client.SearchPosts(th.BasicTeam.Id, "on:", false) + if len(posts.Order) != 0 { + t.Fatalf("wrong number of posts returned %v", len(posts.Order)) + } + + posts, _ = Client.SearchPosts(th.BasicTeam.Id, "after:", false) + if len(posts.Order) != 0 { + t.Fatalf("wrong number of posts returned %v", len(posts.Order)) + } + + posts, _ = Client.SearchPosts(th.BasicTeam.Id, "before:", false) + if len(posts.Order) != 0 { + t.Fatalf("wrong number of posts returned %v", len(posts.Order)) + } + + posts, _ = Client.SearchPosts(th.BasicTeam.Id, "on:2018-08-01", false) + if len(posts.Order) != 1 { + t.Fatalf("wrong number of posts returned %v", len(posts.Order)) + } + + posts, _ = Client.SearchPosts(th.BasicTeam.Id, "after:2018-08-01", false) + resultCount := 0 + for _, post := range posts.Posts { + if post.UserId == th.BasicUser.Id { + resultCount = resultCount + 1 + } + } + if resultCount != 3 { + t.Fatalf("wrong number of posts returned %v", len(posts.Order)) + } + + posts, _ = Client.SearchPosts(th.BasicTeam.Id, "before:2018-08-02", false) + if len(posts.Order) != 2 { + t.Fatalf("wrong number of posts returned %v", len(posts.Order)) + } + + posts, _ = Client.SearchPosts(th.BasicTeam.Id, "before:2018-08-03 after:2018-08-02", false) + if len(posts.Order) != 2 { + t.Fatalf("wrong number of posts returned %v", len(posts.Order)) + } +} + func TestGetFileInfosForPost(t *testing.T) { th := Setup().InitBasic().InitSystemAdmin() defer th.TearDown() -- cgit v1.2.3-1-g7c22