Skip to content

Commit 47613d0

Browse files
test
1 parent 2bf8133 commit 47613d0

2 files changed

Lines changed: 276 additions & 0 deletions

File tree

cmd/docs/search_test.go

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,63 @@ func Test_Docs_SearchCommand_TextJSONOutput_QueryFormats(t *testing.T) {
158158
}
159159
}
160160

161+
// JSON Output Tests
162+
163+
// Verifies that JSON output mode correctly formats and outputs search results.
164+
func Test_Docs_SearchCommand_JSONOutput(t *testing.T) {
165+
response := &api.DocsSearchResponse{
166+
TotalResults: 1,
167+
Limit: 20,
168+
Results: []api.DocsSearchItem{
169+
{
170+
Title: "Block Kit",
171+
URL: "/block-kit",
172+
},
173+
},
174+
}
175+
176+
clients := setupDocsAPITest(t, response, nil)
177+
err := fetchAndOutputSearchResults(slackcontext.MockContext(context.Background()), clients, "Block Kit", 20)
178+
require.NoError(t, err)
179+
}
180+
181+
// Text Output Tests
182+
183+
// Verifies that text output mode correctly formats and outputs search results.
184+
func Test_Docs_SearchCommand_TextOutput(t *testing.T) {
185+
response := &api.DocsSearchResponse{
186+
TotalResults: 1,
187+
Limit: 20,
188+
Results: []api.DocsSearchItem{
189+
{
190+
Title: "Block Kit",
191+
URL: "/block-kit",
192+
},
193+
},
194+
}
195+
196+
clients := setupDocsAPITest(t, response, nil)
197+
err := fetchAndOutputTextResults(slackcontext.MockContext(context.Background()), clients, "Block Kit", 20)
198+
require.NoError(t, err)
199+
}
200+
201+
// Invalid Output Format Tests
202+
203+
// Verifies that invalid output format returns an error with helpful remediation.
204+
func Test_Docs_SearchCommand_InvalidOutputFormat(t *testing.T) {
205+
testutil.TableTestCommand(t, testutil.CommandTests{
206+
"rejects invalid output format": {
207+
CmdArgs: []string{"search", "test", "--output=invalid"},
208+
ExpectedErrorStrings: []string{
209+
"Invalid output format",
210+
"Use one of: text, json, browser",
211+
},
212+
},
213+
}, func(cf *shared.ClientFactory) *cobra.Command {
214+
return NewCommand(cf)
215+
})
216+
}
217+
161218
// Browser Output Tests
162219

163220
// Verifies that browser output mode correctly handles various query formats and opens the correct URLs.

internal/api/docs_test.go

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
// Copyright 2022-2026 Salesforce, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package api
16+
17+
import (
18+
"bytes"
19+
"context"
20+
"encoding/json"
21+
"fmt"
22+
"io"
23+
"net/http"
24+
"testing"
25+
26+
"github.com/stretchr/testify/assert"
27+
"github.com/stretchr/testify/require"
28+
)
29+
30+
// mockRoundTripper implements http.RoundTripper for testing
31+
type mockRoundTripper struct {
32+
response *http.Response
33+
err error
34+
capturedURL string
35+
}
36+
37+
func (m *mockRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
38+
m.capturedURL = req.URL.String()
39+
return m.response, m.err
40+
}
41+
42+
// Test_DocsSearch_Success verifies successful API response parsing
43+
func Test_DocsSearch_Success(t *testing.T) {
44+
responseBody := DocsSearchResponse{
45+
TotalResults: 2,
46+
Limit: 20,
47+
Results: []DocsSearchItem{
48+
{
49+
Title: "Block Kit",
50+
URL: "/block-kit",
51+
},
52+
{
53+
Title: "Block Kit Elements",
54+
URL: "/block-kit/elements",
55+
},
56+
},
57+
}
58+
59+
bodyBytes, err := json.Marshal(responseBody)
60+
require.NoError(t, err)
61+
62+
mockTransport := &mockRoundTripper{
63+
response: &http.Response{
64+
StatusCode: http.StatusOK,
65+
Body: io.NopCloser(bytes.NewReader(bodyBytes)),
66+
Header: make(http.Header),
67+
},
68+
}
69+
70+
httpClient := &http.Client{
71+
Transport: mockTransport,
72+
}
73+
74+
client := &Client{
75+
httpClient: httpClient,
76+
}
77+
78+
result, err := client.DocsSearch(context.Background(), "Block Kit", 20)
79+
require.NoError(t, err)
80+
assert.Equal(t, 2, result.TotalResults)
81+
assert.Equal(t, 20, result.Limit)
82+
assert.Len(t, result.Results, 2)
83+
assert.Equal(t, "Block Kit", result.Results[0].Title)
84+
assert.Equal(t, "/block-kit", result.Results[0].URL)
85+
}
86+
87+
// Test_DocsSearch_EmptyResults verifies handling of empty results
88+
func Test_DocsSearch_EmptyResults(t *testing.T) {
89+
responseBody := DocsSearchResponse{
90+
TotalResults: 0,
91+
Limit: 20,
92+
Results: []DocsSearchItem{},
93+
}
94+
95+
bodyBytes, err := json.Marshal(responseBody)
96+
require.NoError(t, err)
97+
98+
mockTransport := &mockRoundTripper{
99+
response: &http.Response{
100+
StatusCode: http.StatusOK,
101+
Body: io.NopCloser(bytes.NewReader(bodyBytes)),
102+
Header: make(http.Header),
103+
},
104+
}
105+
106+
httpClient := &http.Client{
107+
Transport: mockTransport,
108+
}
109+
110+
client := &Client{
111+
httpClient: httpClient,
112+
}
113+
114+
result, err := client.DocsSearch(context.Background(), "nonexistent", 20)
115+
require.NoError(t, err)
116+
assert.Equal(t, 0, result.TotalResults)
117+
assert.Len(t, result.Results, 0)
118+
}
119+
120+
// Test_DocsSearch_QueryEncoding verifies query parameters are properly encoded
121+
func Test_DocsSearch_QueryEncoding(t *testing.T) {
122+
responseBody := DocsSearchResponse{
123+
TotalResults: 0,
124+
Limit: 20,
125+
Results: []DocsSearchItem{},
126+
}
127+
128+
bodyBytes, err := json.Marshal(responseBody)
129+
require.NoError(t, err)
130+
131+
mockTransport := &mockRoundTripper{
132+
response: &http.Response{
133+
StatusCode: http.StatusOK,
134+
Body: io.NopCloser(bytes.NewReader(bodyBytes)),
135+
Header: make(http.Header),
136+
},
137+
}
138+
139+
httpClient := &http.Client{
140+
Transport: mockTransport,
141+
}
142+
143+
client := &Client{
144+
httpClient: httpClient,
145+
}
146+
147+
_, err = client.DocsSearch(context.Background(), "messages & webhooks", 5)
148+
require.NoError(t, err)
149+
150+
// Verify URL encoding
151+
assert.Contains(t, mockTransport.capturedURL, "q=messages+%26+webhooks")
152+
assert.Contains(t, mockTransport.capturedURL, "limit=5")
153+
}
154+
155+
// Test_DocsSearch_HTTPError verifies HTTP request errors are handled
156+
func Test_DocsSearch_HTTPError(t *testing.T) {
157+
mockTransport := &mockRoundTripper{
158+
err: fmt.Errorf("network error"),
159+
}
160+
161+
httpClient := &http.Client{
162+
Transport: mockTransport,
163+
}
164+
165+
client := &Client{
166+
httpClient: httpClient,
167+
}
168+
169+
result, err := client.DocsSearch(context.Background(), "test", 20)
170+
assert.Error(t, err)
171+
assert.Nil(t, result)
172+
}
173+
174+
// Test_DocsSearch_NonOKStatus verifies non-200 status codes are handled
175+
func Test_DocsSearch_NonOKStatus(t *testing.T) {
176+
mockTransport := &mockRoundTripper{
177+
response: &http.Response{
178+
StatusCode: http.StatusNotFound,
179+
Body: io.NopCloser(bytes.NewBufferString("")),
180+
Header: make(http.Header),
181+
},
182+
}
183+
184+
httpClient := &http.Client{
185+
Transport: mockTransport,
186+
}
187+
188+
client := &Client{
189+
httpClient: httpClient,
190+
}
191+
192+
result, err := client.DocsSearch(context.Background(), "test", 20)
193+
assert.Error(t, err)
194+
assert.Nil(t, result)
195+
assert.Contains(t, err.Error(), "404")
196+
}
197+
198+
// Test_DocsSearch_InvalidJSON verifies invalid JSON responses are handled
199+
func Test_DocsSearch_InvalidJSON(t *testing.T) {
200+
mockTransport := &mockRoundTripper{
201+
response: &http.Response{
202+
StatusCode: http.StatusOK,
203+
Body: io.NopCloser(bytes.NewBufferString("{invalid json}")),
204+
Header: make(http.Header),
205+
},
206+
}
207+
208+
httpClient := &http.Client{
209+
Transport: mockTransport,
210+
}
211+
212+
client := &Client{
213+
httpClient: httpClient,
214+
}
215+
216+
result, err := client.DocsSearch(context.Background(), "test", 20)
217+
assert.Error(t, err)
218+
assert.Nil(t, result)
219+
}

0 commit comments

Comments
 (0)