From 031375ef5e0e3a7c9c1330e1a9d86523d4c7c6fb Mon Sep 17 00:00:00 2001 From: Eric Schubert Date: Fri, 24 May 2024 14:06:32 +0200 Subject: [PATCH] Rework query to be able to have any kind of query attributes --- components/requests/query.go | 52 ++++++++++++------ components/requests/query_test.go | 55 +++++++++++++++++-- .../resources/notifications/functions.go | 2 +- components/resources/users/functions.go | 4 +- components/resources/work_packages/read.go | 2 +- 5 files changed, 88 insertions(+), 27 deletions(-) diff --git a/components/requests/query.go b/components/requests/query.go index 36ef6cb..b9ddcd1 100644 --- a/components/requests/query.go +++ b/components/requests/query.go @@ -7,8 +7,8 @@ import ( ) type Query struct { - pageSize int - filters []Filter + filters []Filter + attributes map[string]string } type Filter struct { @@ -27,29 +27,47 @@ func (filter Filter) String() string { } func (query Query) String() string { - var filtersQuery = "" - if len(query.filters) > 0 { - var fStr = make([]string, len(query.filters)) - for idx, f := range query.filters { - fStr[idx] = f.String() + queryStr := filtersQueryAttribute(query.filters) + for key, value := range query.attributes { + if len(queryStr) > 0 { + queryStr += "&" } - filtersString := fmt.Sprintf("[%s]", strings.Join(fStr, ",")) - filtersQuery = fmt.Sprintf("&filters=%s", url.QueryEscape(filtersString)) + queryStr += fmt.Sprintf("%s=%s", key, url.QueryEscape(value)) } - return fmt.Sprintf("pageSize=%d%s", query.pageSize, filtersQuery) + return queryStr } -func NewQuery(filters []Filter) Query { - return Query{ - pageSize: 100, - filters: filters, +func filtersQueryAttribute(filters []Filter) string { + if len(filters) == 0 { + return "" } + + var fStr = make([]string, len(filters)) + for idx, f := range filters { + fStr[idx] = f.String() + } + + filtersString := fmt.Sprintf("[%s]", strings.Join(fStr, ",")) + return fmt.Sprintf("filters=%s", url.QueryEscape(filtersString)) +} + +func NewQuery(attributes map[string]string, filters []Filter) Query { + return Query{attributes: attributes, filters: filters} +} + +func NewFilterQuery(filters []Filter) Query { + attributes := map[string]string{ + "pageSize": "100", + } + + return Query{attributes: attributes, filters: filters} } func NewPagedQuery(pageSize int, filters []Filter) Query { - return Query{ - pageSize: pageSize, - filters: filters, + attributes := map[string]string{ + "pageSize": fmt.Sprintf("%d", pageSize), } + + return Query{attributes: attributes, filters: filters} } diff --git a/components/requests/query_test.go b/components/requests/query_test.go index 3ea7549..99714c8 100644 --- a/components/requests/query_test.go +++ b/components/requests/query_test.go @@ -3,15 +3,16 @@ package requests_test import ( "github.com/opf/openproject-cli/components/resources/notifications" "github.com/opf/openproject-cli/components/resources/work_packages" + "strings" "testing" "github.com/opf/openproject-cli/components/requests" ) -func TestQuery_String_WithFilters(t *testing.T) { - expectedString := "pageSize=100&filters=%5B%7B%22readIAN%22%3A%7B%22operator%22%3A%22%3D%22%2C%22values%22%3A%5B%22f%22%5D%7D%7D%2C%7B%22reason%22%3A%7B%22operator%22%3A%22%3D%22%2C%22values%22%3A%5B%22assigned%22%5D%7D%7D%5D" +func TestFilterQuery_String_WithFilters(t *testing.T) { + expectedString := "filters=%5B%7B%22readIAN%22%3A%7B%22operator%22%3A%22%3D%22%2C%22values%22%3A%5B%22f%22%5D%7D%7D%2C%7B%22reason%22%3A%7B%22operator%22%3A%22%3D%22%2C%22values%22%3A%5B%22assigned%22%5D%7D%7D%5D&pageSize=100" - queryString := requests.NewQuery([]requests.Filter{ + queryString := requests.NewFilterQuery([]requests.Filter{ notifications.ReadFilter(false), notifications.ReasonFilter("assigned"), }).String() @@ -21,10 +22,10 @@ func TestQuery_String_WithFilters(t *testing.T) { } } -func TestQuery_String_WithoutFilters(t *testing.T) { +func TestFilterQuery_String_WithoutFilters(t *testing.T) { expectedString := "pageSize=100" - queryString := requests.NewQuery([]requests.Filter{}).String() + queryString := requests.NewFilterQuery([]requests.Filter{}).String() if queryString != expectedString { t.Errorf("Expected %s, but got %s", expectedString, queryString) @@ -32,7 +33,7 @@ func TestQuery_String_WithoutFilters(t *testing.T) { } func TestPagedQuery_String_WithFilters(t *testing.T) { - expectedString := "pageSize=-1&filters=%5B%7B%22status%22%3A%7B%22operator%22%3A%22%3D%22%2C%22values%22%3A%5B%221%22%2C%223%22%5D%7D%7D%5D" + expectedString := "filters=%5B%7B%22status%22%3A%7B%22operator%22%3A%22%3D%22%2C%22values%22%3A%5B%221%22%2C%223%22%5D%7D%7D%5D&pageSize=-1" filters := []requests.Filter{ work_packages.StatusFilter("1,3"), @@ -43,3 +44,45 @@ func TestPagedQuery_String_WithFilters(t *testing.T) { t.Errorf("Expected %s, but got %s", expectedString, queryString) } } + +func TestQuery_String(t *testing.T) { + attributes := map[string]string{ + "pageSize": "20", + "includeSubprojects": "true", + "timestamps": "PT0S", + } + + filters := []requests.Filter{ + work_packages.StatusFilter("1,3"), + work_packages.TypeFilter("!1"), + } + queryString := requests.NewQuery(attributes, filters).String() + + if strings.Count(queryString, "&") != 3 { + t.Errorf("Expected %s to contain 3 delimiter '&'.", queryString) + } + + expected := "pageSize=20" + contained := strings.Contains(queryString, expected) + if !contained { + t.Errorf("Expected %s to contain %s", queryString, expected) + } + + expected = "includeSubprojects=true" + contained = strings.Contains(queryString, expected) + if !contained { + t.Errorf("Expected %s to contain %s", queryString, expected) + } + + expected = "timestamps=PT0S" + contained = strings.Contains(queryString, expected) + if !contained { + t.Errorf("Expected %s to contain %s", queryString, expected) + } + + expected = "filters=%5B%7B%22status%22%3A%7B%22operator%22%3A%22%3D%22%2C%22values%22%3A%5B%221%22%2C%223%22%5D%7D%7D%2C%7B%22type%22%3A%7B%22operator%22%3A%22%21%22%2C%22values%22%3A%5B%221%22%5D%7D%7D%5D" + contained = strings.Contains(queryString, expected) + if !contained { + t.Errorf("Expected %s to contain %s", queryString, expected) + } +} diff --git a/components/resources/notifications/functions.go b/components/resources/notifications/functions.go index 39d8755..05d9782 100644 --- a/components/resources/notifications/functions.go +++ b/components/resources/notifications/functions.go @@ -27,6 +27,6 @@ func generateQuery(reason string) *requests.Query { filters = append(filters, ReasonFilter(reason)) } - query := requests.NewQuery(filters) + query := requests.NewFilterQuery(filters) return &query } diff --git a/components/resources/users/functions.go b/components/resources/users/functions.go index 2ee16e9..65841d2 100644 --- a/components/resources/users/functions.go +++ b/components/resources/users/functions.go @@ -18,7 +18,7 @@ func ByIds(ids []uint64) []*models.User { var filters []requests.Filter filters = append(filters, IdFilter(ids)) - query := requests.NewQuery(filters) + query := requests.NewFilterQuery(filters) requestUrl := paths.Principals() @@ -61,7 +61,7 @@ func Search(input string) ([]*models.User, error) { filters = append(filters, resources.TypeAheadFilter(input)) } - query := requests.NewQuery(filters) + query := requests.NewFilterQuery(filters) response, err := requests.Get(paths.Principals(), &query) if err != nil { diff --git a/components/resources/work_packages/read.go b/components/resources/work_packages/read.go index f9791b3..a8f63c7 100644 --- a/components/resources/work_packages/read.go +++ b/components/resources/work_packages/read.go @@ -49,7 +49,7 @@ func All(filterOptions *map[FilterOption]string) (*models.WorkPackageCollection, } } - query := requests.NewQuery(filters) + query := requests.NewFilterQuery(filters) requestUrl := paths.WorkPackages()