Skip to content

Commit d07de6d

Browse files
committed
Render empty searches as JSON arrays
Always invoke the collection renderer, even when a search has no matches. JSON callers now receive [] while text users still get an empty-result diagnostic on standard error.
1 parent b8ce0a0 commit d07de6d

4 files changed

Lines changed: 102 additions & 7 deletions

File tree

cmd/user/search.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ func searchUser(_ *cobra.Command, args []string) error {
2525
printer.ErrorText(fmt.Sprintf("Expected 1 argument [searchInput], but got %d", len(args)))
2626
return openerrors.ErrHandled
2727
}
28+
query := args[0]
2829

29-
if common.Contains(keywords, args[0]) {
30+
if common.Contains(keywords, query) {
3031
me, err := users.Me()
3132
if err != nil {
3233
printer.Error(err)
@@ -36,16 +37,15 @@ func searchUser(_ *cobra.Command, args []string) error {
3637
return nil
3738
}
3839

39-
collection, err := users.Search(args[0])
40+
collection, err := users.Search(query)
4041
if err != nil {
4142
printer.Error(err)
4243
return openerrors.ErrHandled
4344
}
4445

4546
if len(collection) == 0 {
46-
printer.Info(fmt.Sprintf("No user found for search input %s.", printer.Cyan(args[0])))
47-
} else {
48-
printer.Users(collection)
47+
printer.Info(fmt.Sprintf("No user found for search input %s.", printer.Cyan(query)))
4948
}
49+
printer.Users(collection)
5050
return nil
5151
}

cmd/user/search_test.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package user
2+
3+
import (
4+
"net/http"
5+
"net/http/httptest"
6+
"net/url"
7+
"strings"
8+
"testing"
9+
10+
"github.com/opf/openproject-cli/components/printer"
11+
"github.com/opf/openproject-cli/components/requests"
12+
)
13+
14+
func TestSearchUsersRendersEmptyJSONArray(t *testing.T) {
15+
server := httptest.NewServer(http.HandlerFunc(func(response http.ResponseWriter, _ *http.Request) {
16+
response.Header().Set("Content-Type", "application/json")
17+
_, _ = response.Write([]byte(`{"_embedded":{"elements":[]},"total":0,"count":0}`))
18+
}))
19+
t.Cleanup(server.Close)
20+
21+
host, err := url.Parse(server.URL)
22+
if err != nil {
23+
t.Fatal(err)
24+
}
25+
requests.Init(host, "", false)
26+
27+
testingPrinter := &printer.TestingPrinter{}
28+
printer.Init(testingPrinter)
29+
if err := printer.InitRenderer("json"); err != nil {
30+
t.Fatal(err)
31+
}
32+
t.Cleanup(func() {
33+
_ = printer.InitRenderer("text")
34+
})
35+
36+
if err := searchUser(nil, []string{"missing person"}); err != nil {
37+
t.Fatalf("searchUser returned an error: %v", err)
38+
}
39+
40+
if testingPrinter.Result != "[]\n" {
41+
t.Errorf("stdout = %q, want %q", testingPrinter.Result, "[]\n")
42+
}
43+
if !strings.Contains(testingPrinter.ErrResult, "missing person") {
44+
t.Errorf("stderr should contain the complete query, got %q", testingPrinter.ErrResult)
45+
}
46+
}
47+
48+
func TestSearchUserRequiresOneArgument(t *testing.T) {
49+
requestCount := 0
50+
server := httptest.NewServer(http.HandlerFunc(func(response http.ResponseWriter, _ *http.Request) {
51+
requestCount++
52+
_, _ = response.Write([]byte(`{"_embedded":{"elements":[]}}`))
53+
}))
54+
t.Cleanup(server.Close)
55+
56+
host, err := url.Parse(server.URL)
57+
if err != nil {
58+
t.Fatal(err)
59+
}
60+
requests.Init(host, "", false)
61+
62+
testingPrinter := &printer.TestingPrinter{}
63+
printer.Init(testingPrinter)
64+
65+
if err := searchUser(nil, []string{"missing", "person"}); err == nil {
66+
t.Fatal("searchUser returned nil for two arguments")
67+
}
68+
if requestCount != 0 {
69+
t.Errorf("request count = %d, want 0", requestCount)
70+
}
71+
}

cmd/workpackage/search.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,7 @@ func searchWorkPackages(_ *cobra.Command, args []string) error {
4949

5050
if len(collection) == 0 {
5151
printer.Info(fmt.Sprintf("No work package found for search input %s.", printer.Cyan(query)))
52-
} else {
53-
printer.WorkPackages(collection)
5452
}
53+
printer.WorkPackages(collection)
5554
return nil
5655
}

cmd/workpackage/search_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package workpackage
2+
3+
import (
4+
"net/http"
5+
"strings"
6+
"testing"
7+
)
8+
9+
func TestSearchWorkPackagesRendersEmptyJSONArray(t *testing.T) {
10+
testingPrinter, _ := initWorkPackageTestServer(t, func(response http.ResponseWriter, _ *http.Request) {
11+
response.Header().Set("Content-Type", "application/json")
12+
_, _ = response.Write([]byte(`{"_embedded":{"elements":[]},"total":0,"count":0}`))
13+
})
14+
15+
if err := searchWorkPackages(nil, []string{"missing"}); err != nil {
16+
t.Fatalf("searchWorkPackages returned an error: %v", err)
17+
}
18+
19+
if testingPrinter.Result != "[]\n" {
20+
t.Errorf("stdout = %q, want %q", testingPrinter.Result, "[]\n")
21+
}
22+
if !strings.Contains(testingPrinter.ErrResult, "No work package found") {
23+
t.Errorf("stderr should describe the empty result, got %q", testingPrinter.ErrResult)
24+
}
25+
}

0 commit comments

Comments
 (0)