@@ -26,13 +26,13 @@ func createTempTokenStore(t *testing.T) (*store.TokenStore, string) {
2626 if err != nil {
2727 t .Fatalf ("Failed to create temp directory: %v" , err )
2828 }
29-
29+
3030 tempFile := filepath .Join (tempDir , "tokens.json" )
3131 tokenStore := & store.TokenStore {
3232 OAuth2Tokens : make (map [string ]store.Token ),
3333 FilePath : tempFile ,
3434 }
35-
35+
3636 return tokenStore , tempDir
3737}
3838
@@ -47,15 +47,15 @@ func createMockAuth(t *testing.T) (*auth.Auth, string) {
4747 APIBaseURL : "https://api.x.com" ,
4848 InfoURL : "https://api.x.com/2/users/me" ,
4949 }
50-
50+
5151 mockAuth := auth .NewAuth (cfg )
5252 tokenStore , tempDir := createTempTokenStore (t )
53-
53+
5454 err := tokenStore .SaveBearerToken ("test-bearer-token" )
5555 if err != nil {
5656 t .Fatalf ("Failed to save bearer token: %v" , err )
5757 }
58-
58+
5959 mockAuth .WithTokenStore (tokenStore )
6060 return mockAuth , tempDir
6161}
@@ -66,9 +66,9 @@ func TestNewApiClient(t *testing.T) {
6666 }
6767 auth , tempDir := createMockAuth (t )
6868 defer os .RemoveAll (tempDir )
69-
69+
7070 client := NewApiClient (cfg , auth )
71-
71+
7272 assert .Equal (t , cfg .APIBaseURL , client .url , "URL should match config" )
7373 assert .Equal (t , auth , client .auth , "Auth should be set correctly" )
7474 assert .NotNil (t , client .client , "HTTP client should not be nil" )
@@ -81,9 +81,9 @@ func TestBuildRequest(t *testing.T) {
8181 }
8282 authMock , tempDir := createMockAuth (t )
8383 defer os .RemoveAll (tempDir )
84-
84+
8585 client := NewApiClient (cfg , authMock )
86-
86+
8787 tests := []struct {
8888 name string
8989 method string
@@ -133,45 +133,45 @@ func TestBuildRequest(t *testing.T) {
133133 wantErr : false ,
134134 },
135135 }
136-
136+
137137 for _ , tt := range tests {
138138 t .Run (tt .name , func (t * testing.T ) {
139139 var body io.Reader
140140 contentType := ""
141141 if tt .data != "" && (strings .ToUpper (tt .method ) == "POST" || strings .ToUpper (tt .method ) == "PUT" || strings .ToUpper (tt .method ) == "PATCH" ) {
142142 body = bytes .NewBufferString (tt .data )
143-
143+
144144 var js json.RawMessage
145145 if json .Unmarshal ([]byte (tt .data ), & js ) == nil {
146146 contentType = "application/json"
147147 } else {
148148 contentType = "application/x-www-form-urlencoded"
149149 }
150150 }
151-
151+
152152 req , err := client .BuildRequest (tt .method , tt .endpoint , tt .headers , body , contentType , tt .authType , tt .username )
153-
153+
154154 if tt .wantErr {
155155 assert .Error (t , err )
156156 return
157157 }
158-
158+
159159 require .NoError (t , err )
160160 assert .Equal (t , tt .wantMethod , req .Method )
161161 assert .Equal (t , tt .wantURL , req .URL .String ())
162-
162+
163163 for _ , header := range tt .headers {
164164 parts := strings .Split (header , ": " )
165165 require .Len (t , parts , 2 , "Invalid header format: %s" , header )
166-
166+
167167 key := strings .TrimSpace (parts [0 ])
168168 value := strings .TrimSpace (parts [1 ])
169-
169+
170170 assert .Equal (t , value , req .Header .Get (key ))
171171 }
172172
173173 assert .Equal (t , "xurl/dev" , req .Header .Get ("User-Agent" ))
174-
174+
175175 if tt .method == "POST" && tt .data != "" {
176176 assert .Equal (t , "application/json" , req .Header .Get ("Content-Type" ))
177177 }
@@ -187,67 +187,97 @@ func TestSendRequest(t *testing.T) {
187187 w .Write ([]byte (`{"data":{"id":"12345","name":"Test User","username":"testuser"}}` ))
188188 return
189189 }
190-
190+
191191 if r .URL .Path == "/2/tweets" && r .Method == "POST" {
192192 w .Header ().Set ("Content-Type" , "application/json" )
193193 w .WriteHeader (http .StatusCreated )
194194 w .Write ([]byte (`{"data":{"id":"67890","text":"Hello world!"}}` ))
195195 return
196196 }
197-
197+
198198 if r .URL .Path == "/2/tweets/search/recent" {
199199 w .Header ().Set ("Content-Type" , "application/json" )
200200 w .WriteHeader (http .StatusBadRequest )
201201 w .Write ([]byte (`{"errors":[{"message":"Invalid query","code":400}]}` ))
202202 return
203203 }
204-
204+
205205 w .WriteHeader (http .StatusNotFound )
206206 }))
207207 defer server .Close ()
208-
208+
209209 cfg := & config.Config {
210210 APIBaseURL : server .URL ,
211211 }
212212 authMock , tempDir := createMockAuth (t )
213213 defer os .RemoveAll (tempDir )
214214 client := NewApiClient (cfg , authMock )
215-
215+
216216 // Test successful GET request
217217 t .Run ("Get user profile" , func (t * testing.T ) {
218- resp , err := client .SendRequest ("GET" , "/2/users/me" , []string {"Authorization: Bearer test-token" }, "" , "" , "" , false )
219-
218+ options := RequestOptions {
219+ Method : "GET" ,
220+ Endpoint : "/2/users/me" ,
221+ Headers : []string {"Authorization: Bearer test-token" },
222+ Data : "" ,
223+ AuthType : "" ,
224+ Username : "" ,
225+ Verbose : false ,
226+ }
227+
228+ resp , err := client .SendRequest (options )
229+
220230 require .NoError (t , err )
221-
231+
222232 var result map [string ]interface {}
223233 err = json .Unmarshal (resp , & result )
224234 require .NoError (t , err , "Failed to parse response" )
225-
235+
226236 data , ok := result ["data" ].(map [string ]interface {})
227237 require .True (t , ok , "Expected data object in response" )
228-
238+
229239 assert .Equal (t , "testuser" , data ["username" ], "Username should match" )
230240 })
231-
241+
232242 // Test successful POST request
233243 t .Run ("Post tweet" , func (t * testing.T ) {
234- resp , err := client .SendRequest ("POST" , "/2/tweets" , []string {"Authorization: Bearer test-token" }, `{"text":"Hello world!"}` , "" , "" , false )
235-
244+ options := RequestOptions {
245+ Method : "POST" ,
246+ Endpoint : "/2/tweets" ,
247+ Headers : []string {"Authorization: Bearer test-token" },
248+ Data : `{"text":"Hello world!"}` ,
249+ AuthType : "" ,
250+ Username : "" ,
251+ Verbose : false ,
252+ }
253+
254+ resp , err := client .SendRequest (options )
255+
236256 require .NoError (t , err )
237-
257+
238258 var result map [string ]interface {}
239259 err = json .Unmarshal (resp , & result )
240260 require .NoError (t , err , "Failed to parse response" )
241-
261+
242262 data , ok := result ["data" ].(map [string ]interface {})
243263 require .True (t , ok , "Expected data object in response" )
244-
264+
245265 assert .Equal (t , "Hello world!" , data ["text" ], "Tweet text should match" )
246266 })
247-
267+
248268 t .Run ("Error response" , func (t * testing.T ) {
249- resp , err := client .SendRequest ("GET" , "/2/tweets/search/recent" , []string {"Authorization: Bearer test-token" }, "" , "" , "" , false )
250-
269+ options := RequestOptions {
270+ Method : "GET" ,
271+ Endpoint : "/2/tweets/search/recent" ,
272+ Headers : []string {"Authorization: Bearer test-token" },
273+ Data : "" ,
274+ AuthType : "" ,
275+ Username : "" ,
276+ Verbose : false ,
277+ }
278+
279+ resp , err := client .SendRequest (options )
280+
251281 assert .Error (t , err , "Expected an error" )
252282 assert .Nil (t , resp , "Response should be nil" )
253283 assert .True (t , xurlErrors .IsAPIError (err ), "Expected API error" )
@@ -258,23 +288,23 @@ func TestGetAuthHeader(t *testing.T) {
258288 cfg := & config.Config {
259289 APIBaseURL : "https://api.x.com" ,
260290 }
261-
291+
262292 t .Run ("No auth set" , func (t * testing.T ) {
263293 client := NewApiClient (cfg , nil )
264-
294+
265295 _ , err := client .GetAuthHeader ("GET" , "https://api.x.com/2/users/me" , "" , "" )
266-
296+
267297 assert .Error (t , err , "Expected an error" )
268298 assert .True (t , xurlErrors .IsAuthError (err ), "Expected auth error" )
269299 })
270-
300+
271301 t .Run ("Invalid auth type" , func (t * testing.T ) {
272302 authMock , tempDir := createMockAuth (t )
273303 defer os .RemoveAll (tempDir )
274304 client := NewApiClient (cfg , authMock )
275-
305+
276306 _ , err := client .GetAuthHeader ("GET" , "https://api.x.com/2/users/me" , "invalid" , "" )
277-
307+
278308 assert .Error (t , err , "Expected an error" )
279309 assert .True (t , xurlErrors .IsAuthError (err ), "Expected auth error" )
280310 })
@@ -283,7 +313,7 @@ func TestGetAuthHeader(t *testing.T) {
283313func TestStreamRequest (t * testing.T ) {
284314 // This is a basic test for the StreamRequest method
285315 // A more comprehensive test would require mocking the streaming response
286-
316+
287317 server := httptest .NewServer (http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
288318 if r .URL .Path == "/2/tweets/search/stream" {
289319 w .Header ().Set ("Content-Type" , "application/json" )
@@ -292,28 +322,38 @@ func TestStreamRequest(t *testing.T) {
292322 // but for this simple test, we'll just close the connection
293323 return
294324 }
295-
325+
296326 if r .URL .Path == "/2/tweets/search/stream/error" {
297327 w .Header ().Set ("Content-Type" , "application/json" )
298328 w .WriteHeader (http .StatusBadRequest )
299329 w .Write ([]byte (`{"errors":[{"message":"Invalid rule","code":400}]}` ))
300330 return
301331 }
302-
332+
303333 w .WriteHeader (http .StatusNotFound )
304334 }))
305335 defer server .Close ()
306-
336+
307337 cfg := & config.Config {
308338 APIBaseURL : server .URL ,
309339 }
310340 authMock , tempDir := createMockAuth (t )
311341 defer os .RemoveAll (tempDir )
312342 client := NewApiClient (cfg , authMock )
313-
343+
314344 t .Run ("Stream error response" , func (t * testing.T ) {
315- err := client .StreamRequest ("GET" , "/2/tweets/search/stream/error" , []string {"Authorization: Bearer test-token" }, "" , "" , "" , false )
316-
345+ options := RequestOptions {
346+ Method : "GET" ,
347+ Endpoint : "/2/tweets/search/stream/error" ,
348+ Headers : []string {"Authorization: Bearer test-token" },
349+ Data : "" ,
350+ AuthType : "" ,
351+ Username : "" ,
352+ Verbose : false ,
353+ }
354+
355+ err := client .StreamRequest (options )
356+
317357 assert .Error (t , err , "Expected an error" )
318358 assert .True (t , xurlErrors .IsAPIError (err ), "Expected API error" )
319359 })
0 commit comments