-
Notifications
You must be signed in to change notification settings - Fork 44
RHINENG-25944: add search to the tags list endpoint #2204
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,12 @@ | ||
| package controllers | ||
|
|
||
| import ( | ||
| "app/base/database" | ||
| "app/base/utils" | ||
| "errors" | ||
| "net/http" | ||
|
|
||
| "app/base/database" | ||
| "app/base/utils" | ||
|
|
||
| "app/manager/middlewares" | ||
|
|
||
| "github.com/gin-gonic/gin" | ||
|
|
@@ -48,16 +49,22 @@ var SystemTagsOpts = ListOpts{ | |
| }, | ||
| StableSort: "tag", | ||
| DefaultSort: "tag", | ||
| SearchFields: []string{ | ||
| "sq.tag->>'namespace'", | ||
| "sq.tag->>'key'", | ||
| "sq.tag->>'value'", | ||
|
Comment on lines
+52
to
+55
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just a question for my understanding, how did you determine these 3 fields should be searched? |
||
| }, | ||
| } | ||
|
|
||
| // @Summary Show me systems tags applicable to this application | ||
| // @Description Show me systems tags applicable to this application | ||
| // @ID listSystemTags | ||
| // @Security RhIdentity | ||
| // @Produce json | ||
| // @Param sort query string false "Sort field" Enums(tag, count) | ||
| // @Param limit query int fals "Limit for paging" | ||
| // @Param offset query int false "Offset for paging" | ||
| // @Param sort query string false "Sort field" Enums(tag, count) | ||
| // @Param limit query int false "Limit for paging" | ||
| // @Param search query string false "Find matching text" | ||
| // @Param offset query int false "Offset for paging" | ||
| // @Success 200 {object} SystemTagsResponse | ||
| // @Failure 400 {object} utils.ErrorResponse | ||
| // @Failure 500 {object} utils.ErrorResponse | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,11 @@ | ||
| package controllers | ||
|
|
||
| import ( | ||
| "app/base/core" | ||
| "net/http" | ||
| "testing" | ||
|
|
||
| "app/base/core" | ||
|
|
||
| "github.com/stretchr/testify/assert" | ||
| ) | ||
|
|
||
|
|
@@ -76,3 +77,38 @@ func TestSystemTagsListBadRequestOnIdtSort(t *testing.T) { | |
| w := CreateRequestRouterWithAccount("GET", "/", "", "?sort=id", nil, "", SystemTagListHandler, 1) | ||
| assert.Equal(t, 400, w.Code) | ||
| } | ||
|
|
||
| func TestSystemTagsListSearch(t *testing.T) { | ||
| core.SetupTest(t) | ||
|
|
||
| w := CreateRequestRouterWithAccount("GET", "/", "", "?search=k3", nil, "", SystemTagListHandler, 1) | ||
|
|
||
| var output SystemTagsResponse | ||
| CheckResponse(t, w, http.StatusOK, &output) | ||
|
|
||
| assert.Equal(t, 2, len(output.Data)) | ||
| assert.Equal(t, 2, output.Meta.TotalItems) | ||
|
Comment on lines
+81
to
+90
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. suggestion (testing): Avoid relying on result ordering and tighten assertions to better express expectations This test is tightly coupled to the current result order and exact per-index counts/values, so it may become brittle if query or default sorting changes while behavior remains correct. Either (a) assert that both expected tag combinations are present regardless of order (e.g., by sorting or mapping the response), or (b) treat sort order as part of the contract and assert on the sort field explicitly. Also consider asserting Suggested implementation: import (
"fmt"
"net/http"
"testing"
"app/base/core"
"github.com/stretchr/testify/assert"
)func TestSystemTagsListSearch(t *testing.T) {
core.SetupTest(t)
w := CreateRequestRouterWithAccount("GET", "/", "", "?search=k3", nil, "", SystemTagListHandler, 1)
var output SystemTagsResponse
CheckResponse(t, w, http.StatusOK, &output)
// Expected tag combinations and counts, independent of result order.
expected := map[string]int{
"ns1:k3:val3": 1,
"ns1:k3:val4": 3,
}
assert.Equal(t, len(expected), len(output.Data))
assert.Equal(t, len(expected), output.Meta.TotalItems)
assert.Equal(t, "k3", output.Meta.Search)
seen := make(map[string]bool)
for _, item := range output.Data {
key := fmt.Sprintf("%s:%s:%s", item.Tag.Namespace, item.Tag.Key, item.Tag.Value)
expectedCount, ok := expected[key]
assert.True(t, ok, "unexpected tag combination in response: %s", key)
assert.Equal(t, expectedCount, item.Count, "unexpected count for tag %s", key)
seen[key] = true
}
// Ensure all expected tag combinations were returned.
for key := range expected {
assert.True(t, seen[key], "expected tag combination not found in response: %s", key)
}
} |
||
| assert.Equal(t, "k3", output.Meta.Search) | ||
|
|
||
| assert.Equal(t, 1, output.Data[0].Count) | ||
| assert.Equal(t, "k3", output.Data[0].Tag.Key) | ||
| assert.Equal(t, "ns1", output.Data[0].Tag.Namespace) | ||
| assert.Equal(t, "val3", output.Data[0].Tag.Value) | ||
|
|
||
| assert.Equal(t, 3, output.Data[1].Count) | ||
| assert.Equal(t, "k3", output.Data[1].Tag.Key) | ||
| assert.Equal(t, "ns1", output.Data[1].Tag.Namespace) | ||
| assert.Equal(t, "val4", output.Data[1].Tag.Value) | ||
| } | ||
|
|
||
| func TestSystemTagsListSearchUnknown(t *testing.T) { | ||
| core.SetupTest(t) | ||
|
|
||
| w := CreateRequestRouterWithAccount("GET", "/", "", "?search=unknown", nil, "", SystemTagListHandler, 1) | ||
|
|
||
| var output SystemTagsResponse | ||
| CheckResponse(t, w, http.StatusOK, &output) | ||
|
|
||
| assert.Equal(t, 0, len(output.Data)) | ||
| assert.Equal(t, "unknown", output.Meta.Search) | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (bug_risk): Avoid hard-coding the SQL alias in
SearchFieldsto reduce coupling and future breakage riskThese
SearchFieldsare tightly coupled to thesqalias (for example,"sq.tag->>'namespace'"). If the table/CTE alias changes, search will silently break. Either make these expressions independent of the outer alias (if supported), or centralize them in a shared constant/helper used by both the query builder andSearchFieldsso alias updates are done in one place.Suggested implementation:
This change assumes that the query builder / underlying SQL does not require an explicit table/CTE alias prefix for these expressions. If the current implementation does require the alias (e.g. because multiple tables expose a
tagcolumn), you should instead:const systemTagAlias = "sq"or a function that formats search fields for a given alias) in this file or a shared package.SearchFields, so alias changes are centralized.