1package mastodon 2 3import ( 4 "context" 5 "fmt" 6 "net/http" 7 "net/http/httptest" 8 "testing" 9) 10 11func TestGetFavourites(t *testing.T) { 12 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 13 fmt.Fprintln(w, `[{"content": "foo"}, {"content": "bar"}]`) 14 return 15 })) 16 defer ts.Close() 17 18 client := NewClient(&Config{ 19 Server: ts.URL, 20 ClientID: "foo", 21 ClientSecret: "bar", 22 AccessToken: "zoo", 23 }) 24 favs, err := client.GetFavourites(context.Background(), nil) 25 if err != nil { 26 t.Fatalf("should not be fail: %v", err) 27 } 28 if len(favs) != 2 { 29 t.Fatalf("result should be two: %d", len(favs)) 30 } 31 if favs[0].Content != "foo" { 32 t.Fatalf("want %q but %q", "foo", favs[0].Content) 33 } 34 if favs[1].Content != "bar" { 35 t.Fatalf("want %q but %q", "bar", favs[1].Content) 36 } 37} 38 39func TestGetStatus(t *testing.T) { 40 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 41 if r.URL.Path != "/api/v1/statuses/1234567" { 42 http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) 43 return 44 } 45 fmt.Fprintln(w, `{"content": "zzz", "emojis":[{"shortcode":"", "url":"http://example.com", "static_url": "http://example.com/static"}]}`) 46 return 47 })) 48 defer ts.Close() 49 50 client := NewClient(&Config{ 51 Server: ts.URL, 52 ClientID: "foo", 53 ClientSecret: "bar", 54 AccessToken: "zoo", 55 }) 56 _, err := client.GetStatus(context.Background(), "123") 57 if err == nil { 58 t.Fatalf("should be fail: %v", err) 59 } 60 status, err := client.GetStatus(context.Background(), "1234567") 61 if err != nil { 62 t.Fatalf("should not be fail: %v", err) 63 } 64 if status.Content != "zzz" { 65 t.Fatalf("want %q but %q", "zzz", status.Content) 66 } 67 if len(status.Emojis) != 1 { 68 t.Fatal("should have emojis") 69 } 70 if status.Emojis[0].ShortCode != "" { 71 t.Fatalf("want %q but %q", "", status.Emojis[0].ShortCode) 72 } 73 if status.Emojis[0].URL != "http://example.com" { 74 t.Fatalf("want %q but %q", "https://example.com", status.Emojis[0].URL) 75 } 76 if status.Emojis[0].StaticURL != "http://example.com/static" { 77 t.Fatalf("want %q but %q", "https://example.com/static", status.Emojis[0].StaticURL) 78 } 79} 80 81func TestGetStatusCard(t *testing.T) { 82 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 83 if r.URL.Path != "/api/v1/statuses/1234567/card" { 84 http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) 85 return 86 } 87 fmt.Fprintln(w, `{"title": "zzz"}`) 88 return 89 })) 90 defer ts.Close() 91 92 client := NewClient(&Config{ 93 Server: ts.URL, 94 ClientID: "foo", 95 ClientSecret: "bar", 96 AccessToken: "zoo", 97 }) 98 _, err := client.GetStatusCard(context.Background(), "123") 99 if err == nil { 100 t.Fatalf("should be fail: %v", err) 101 } 102 card, err := client.GetStatusCard(context.Background(), "1234567") 103 if err != nil { 104 t.Fatalf("should not be fail: %v", err) 105 } 106 if card.Title != "zzz" { 107 t.Fatalf("want %q but %q", "zzz", card.Title) 108 } 109} 110 111func TestGetStatusContext(t *testing.T) { 112 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 113 if r.URL.Path != "/api/v1/statuses/1234567/context" { 114 http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) 115 return 116 } 117 fmt.Fprintln(w, `{"ancestors": [{"content": "zzz"},{"content": "bbb"}]}`) 118 return 119 })) 120 defer ts.Close() 121 122 client := NewClient(&Config{ 123 Server: ts.URL, 124 ClientID: "foo", 125 ClientSecret: "bar", 126 AccessToken: "zoo", 127 }) 128 _, err := client.GetStatusContext(context.Background(), "123") 129 if err == nil { 130 t.Fatalf("should be fail: %v", err) 131 } 132 context, err := client.GetStatusContext(context.Background(), "1234567") 133 if err != nil { 134 t.Fatalf("should not be fail: %v", err) 135 } 136 if len(context.Ancestors) != 2 { 137 t.Fatalf("Ancestors should have 2 entries but %q", len(context.Ancestors)) 138 } 139 if context.Ancestors[0].Content != "zzz" { 140 t.Fatalf("want %q but %q", "zzz", context.Ancestors[0].Content) 141 } 142 if context.Ancestors[1].Content != "bbb" { 143 t.Fatalf("want %q but %q", "bbb", context.Ancestors[1].Content) 144 } 145 if len(context.Descendants) > 0 { 146 t.Fatalf("Descendants should not be included") 147 } 148} 149 150func TestGetRebloggedBy(t *testing.T) { 151 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 152 if r.URL.Path != "/api/v1/statuses/1234567/reblogged_by" { 153 http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) 154 return 155 } 156 fmt.Fprintln(w, `[{"username": "foo"}, {"username": "bar"}]`) 157 return 158 })) 159 defer ts.Close() 160 161 client := NewClient(&Config{ 162 Server: ts.URL, 163 ClientID: "foo", 164 ClientSecret: "bar", 165 AccessToken: "zoo", 166 }) 167 _, err := client.GetRebloggedBy(context.Background(), "123", nil) 168 if err == nil { 169 t.Fatalf("should be fail: %v", err) 170 } 171 rbs, err := client.GetRebloggedBy(context.Background(), "1234567", nil) 172 if err != nil { 173 t.Fatalf("should not be fail: %v", err) 174 } 175 if len(rbs) != 2 { 176 t.Fatalf("result should be two: %d", len(rbs)) 177 } 178 if rbs[0].Username != "foo" { 179 t.Fatalf("want %q but %q", "foo", rbs[0].Username) 180 } 181 if rbs[1].Username != "bar" { 182 t.Fatalf("want %q but %q", "bar", rbs[1].Username) 183 } 184} 185 186func TestGetFavouritedBy(t *testing.T) { 187 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 188 if r.URL.Path != "/api/v1/statuses/1234567/favourited_by" { 189 http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) 190 return 191 } 192 fmt.Fprintln(w, `[{"username": "foo"}, {"username": "bar"}]`) 193 return 194 })) 195 defer ts.Close() 196 197 client := NewClient(&Config{ 198 Server: ts.URL, 199 ClientID: "foo", 200 ClientSecret: "bar", 201 AccessToken: "zoo", 202 }) 203 _, err := client.GetFavouritedBy(context.Background(), "123", nil) 204 if err == nil { 205 t.Fatalf("should be fail: %v", err) 206 } 207 fbs, err := client.GetFavouritedBy(context.Background(), "1234567", nil) 208 if err != nil { 209 t.Fatalf("should not be fail: %v", err) 210 } 211 if len(fbs) != 2 { 212 t.Fatalf("result should be two: %d", len(fbs)) 213 } 214 if fbs[0].Username != "foo" { 215 t.Fatalf("want %q but %q", "foo", fbs[0].Username) 216 } 217 if fbs[1].Username != "bar" { 218 t.Fatalf("want %q but %q", "bar", fbs[1].Username) 219 } 220} 221 222func TestReblog(t *testing.T) { 223 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 224 if r.URL.Path != "/api/v1/statuses/1234567/reblog" { 225 http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) 226 return 227 } 228 fmt.Fprintln(w, `{"content": "zzz"}`) 229 return 230 })) 231 defer ts.Close() 232 233 client := NewClient(&Config{ 234 Server: ts.URL, 235 ClientID: "foo", 236 ClientSecret: "bar", 237 AccessToken: "zoo", 238 }) 239 _, err := client.Reblog(context.Background(), "123") 240 if err == nil { 241 t.Fatalf("should be fail: %v", err) 242 } 243 status, err := client.Reblog(context.Background(), "1234567") 244 if err != nil { 245 t.Fatalf("should not be fail: %v", err) 246 } 247 if status.Content != "zzz" { 248 t.Fatalf("want %q but %q", "zzz", status.Content) 249 } 250} 251 252func TestUnreblog(t *testing.T) { 253 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 254 if r.URL.Path != "/api/v1/statuses/1234567/unreblog" { 255 http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) 256 return 257 } 258 fmt.Fprintln(w, `{"content": "zzz"}`) 259 return 260 })) 261 defer ts.Close() 262 263 client := NewClient(&Config{ 264 Server: ts.URL, 265 ClientID: "foo", 266 ClientSecret: "bar", 267 AccessToken: "zoo", 268 }) 269 _, err := client.Unreblog(context.Background(), "123") 270 if err == nil { 271 t.Fatalf("should be fail: %v", err) 272 } 273 status, err := client.Unreblog(context.Background(), "1234567") 274 if err != nil { 275 t.Fatalf("should not be fail: %v", err) 276 } 277 if status.Content != "zzz" { 278 t.Fatalf("want %q but %q", "zzz", status.Content) 279 } 280} 281 282func TestFavourite(t *testing.T) { 283 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 284 if r.URL.Path != "/api/v1/statuses/1234567/favourite" { 285 http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) 286 return 287 } 288 fmt.Fprintln(w, `{"content": "zzz"}`) 289 return 290 })) 291 defer ts.Close() 292 293 client := NewClient(&Config{ 294 Server: ts.URL, 295 ClientID: "foo", 296 ClientSecret: "bar", 297 AccessToken: "zoo", 298 }) 299 _, err := client.Favourite(context.Background(), "123") 300 if err == nil { 301 t.Fatalf("should be fail: %v", err) 302 } 303 status, err := client.Favourite(context.Background(), "1234567") 304 if err != nil { 305 t.Fatalf("should not be fail: %v", err) 306 } 307 if status.Content != "zzz" { 308 t.Fatalf("want %q but %q", "zzz", status.Content) 309 } 310} 311 312func TestUnfavourite(t *testing.T) { 313 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 314 if r.URL.Path != "/api/v1/statuses/1234567/unfavourite" { 315 http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) 316 return 317 } 318 fmt.Fprintln(w, `{"content": "zzz"}`) 319 return 320 })) 321 defer ts.Close() 322 323 client := NewClient(&Config{ 324 Server: ts.URL, 325 ClientID: "foo", 326 ClientSecret: "bar", 327 AccessToken: "zoo", 328 }) 329 _, err := client.Unfavourite(context.Background(), "123") 330 if err == nil { 331 t.Fatalf("should be fail: %v", err) 332 } 333 status, err := client.Unfavourite(context.Background(), "1234567") 334 if err != nil { 335 t.Fatalf("should not be fail: %v", err) 336 } 337 if status.Content != "zzz" { 338 t.Fatalf("want %q but %q", "zzz", status.Content) 339 } 340} 341 342func TestGetTimelinePublic(t *testing.T) { 343 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 344 if r.URL.Query().Get("local") == "" { 345 http.Error(w, http.StatusText(http.StatusInternalServerError), http.StatusInternalServerError) 346 return 347 } 348 fmt.Fprintln(w, `[{"content": "foo"}, {"content": "bar"}]`) 349 })) 350 defer ts.Close() 351 352 client := NewClient(&Config{Server: ts.URL}) 353 _, err := client.GetTimelinePublic(context.Background(), false, nil) 354 if err == nil { 355 t.Fatalf("should be fail: %v", err) 356 } 357 tl, err := client.GetTimelinePublic(context.Background(), true, nil) 358 if err != nil { 359 t.Fatalf("should not be fail: %v", err) 360 } 361 if len(tl) != 2 { 362 t.Fatalf("result should be two: %d", len(tl)) 363 } 364 if tl[0].Content != "foo" { 365 t.Fatalf("want %q but %q", "foo", tl[0].Content) 366 } 367 if tl[1].Content != "bar" { 368 t.Fatalf("want %q but %q", "bar", tl[1].Content) 369 } 370} 371 372func TestGetTimelineHashtag(t *testing.T) { 373 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 374 if r.URL.Path != "/api/v1/timelines/tag/zzz" { 375 http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) 376 return 377 } 378 fmt.Fprintln(w, `[{"content": "zzz"},{"content": "yyy"}]`) 379 return 380 })) 381 defer ts.Close() 382 383 client := NewClient(&Config{ 384 Server: ts.URL, 385 ClientID: "foo", 386 ClientSecret: "bar", 387 AccessToken: "zoo", 388 }) 389 _, err := client.GetTimelineHashtag(context.Background(), "notfound", false, nil) 390 if err == nil { 391 t.Fatalf("should be fail: %v", err) 392 } 393 tags, err := client.GetTimelineHashtag(context.Background(), "zzz", true, nil) 394 if err != nil { 395 t.Fatalf("should not be fail: %v", err) 396 } 397 if len(tags) != 2 { 398 t.Fatalf("should have %q entries but %q", "2", len(tags)) 399 } 400 if tags[0].Content != "zzz" { 401 t.Fatalf("want %q but %q", "zzz", tags[0].Content) 402 } 403 if tags[1].Content != "yyy" { 404 t.Fatalf("want %q but %q", "zzz", tags[1].Content) 405 } 406} 407 408func TestGetTimelineMedia(t *testing.T) { 409 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 410 if r.URL.Query().Get("local") == "" { 411 http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) 412 return 413 } 414 fmt.Fprintln(w, `[{"content": "zzz"},{"content": "yyy"}]`) 415 return 416 })) 417 defer ts.Close() 418 419 client := NewClient(&Config{ 420 Server: ts.URL, 421 ClientID: "foo", 422 ClientSecret: "bar", 423 AccessToken: "zoo", 424 }) 425 _, err := client.GetTimelineMedia(context.Background(), false, nil) 426 if err == nil { 427 t.Fatalf("should be fail: %v", err) 428 } 429 tags, err := client.GetTimelineMedia(context.Background(), true, nil) 430 if err != nil { 431 t.Fatalf("should not be fail: %v", err) 432 } 433 if len(tags) != 2 { 434 t.Fatalf("should have %q entries but %q", "2", len(tags)) 435 } 436 if tags[0].Content != "zzz" { 437 t.Fatalf("want %q but %q", "zzz", tags[0].Content) 438 } 439 if tags[1].Content != "yyy" { 440 t.Fatalf("want %q but %q", "zzz", tags[1].Content) 441 } 442} 443 444func TestDeleteStatus(t *testing.T) { 445 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 446 if r.URL.Path != "/api/v1/statuses/1234567" { 447 http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) 448 return 449 } 450 if r.Method != "DELETE" { 451 http.Error(w, http.StatusText(http.StatusNotFound), http.StatusMethodNotAllowed) 452 return 453 } 454 return 455 })) 456 defer ts.Close() 457 458 client := NewClient(&Config{ 459 Server: ts.URL, 460 ClientID: "foo", 461 ClientSecret: "bar", 462 AccessToken: "zoo", 463 }) 464 err := client.DeleteStatus(context.Background(), "123") 465 if err == nil { 466 t.Fatalf("should be fail: %v", err) 467 } 468 err = client.DeleteStatus(context.Background(), "1234567") 469 if err != nil { 470 t.Fatalf("should not be fail: %v", err) 471 } 472} 473 474func TestSearch(t *testing.T) { 475 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 476 if r.URL.Path != "/api/v1/search" { 477 http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) 478 return 479 } 480 if r.RequestURI != "/api/v1/search?q=q&resolve=false" { 481 http.Error(w, http.StatusText(http.StatusNotFound), http.StatusBadRequest) 482 return 483 } 484 485 fmt.Fprintln(w, ` 486 {"accounts":[{"username": "zzz"},{"username": "yyy"}], 487 "statuses":[{"content": "aaa"}], 488 "hashtags":["tag","tag2","tag3"] 489 }`) 490 return 491 })) 492 defer ts.Close() 493 494 client := NewClient(&Config{ 495 Server: ts.URL, 496 ClientID: "foo", 497 ClientSecret: "bar", 498 AccessToken: "zoo", 499 }) 500 ret, err := client.Search(context.Background(), "q", false) 501 if err != nil { 502 t.Fatalf("should not be fail: %v", err) 503 } 504 if len(ret.Accounts) != 2 { 505 t.Fatalf("Accounts have %q entries, but %q", "2", len(ret.Accounts)) 506 } 507 if ret.Accounts[0].Username != "zzz" { 508 t.Fatalf("Accounts Username should %q , but %q", "zzz", ret.Accounts[0].Username) 509 } 510 if len(ret.Statuses) != 1 { 511 t.Fatalf("Statuses have %q entries, but %q", "1", len(ret.Statuses)) 512 } 513 if ret.Statuses[0].Content != "aaa" { 514 t.Fatalf("Statuses Content should %q , but %q", "aaa", ret.Statuses[0].Content) 515 } 516 if len(ret.Hashtags) != 3 { 517 t.Fatalf("Hashtags have %q entries, but %q", "3", len(ret.Hashtags)) 518 } 519 if ret.Hashtags[2] != "tag3" { 520 t.Fatalf("Hashtags[2] should %q , but %q", "tag3", ret.Hashtags[2]) 521 } 522} 523 524func TestUploadMedia(t *testing.T) { 525 ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 526 if r.URL.Path != "/api/v1/media" { 527 http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) 528 return 529 } 530 if r.Method != "POST" { 531 http.Error(w, http.StatusText(http.StatusNotFound), http.StatusNotFound) 532 return 533 } 534 fmt.Fprintln(w, `{"id": 123}`) 535 return 536 })) 537 defer ts.Close() 538 539 client := NewClient(&Config{ 540 Server: ts.URL, 541 ClientID: "foo", 542 ClientSecret: "bar", 543 AccessToken: "zoo", 544 }) 545 attachment, err := client.UploadMedia(context.Background(), "testdata/logo.png") 546 if err != nil { 547 t.Fatalf("should not be fail: %v", err) 548 } 549 if attachment.ID != "123" { 550 t.Fatalf("want %q but %q", "123", attachment.ID) 551 } 552} 553