Codebase list golang-github-nlopes-slack / c53487f
GetUsersContext bug fixes Fix #563 (Auto-Paginated API Methods Can Include Duplicates If Errors Occur) Fix #557 (GetUsersContext() doesn't return error) Adam Snyder authored 4 years ago James committed 4 years ago
2 changed file(s) with 111 addition(s) and 11 deletion(s). Raw diff Collapse all Expand all
44 "encoding/json"
55 "net/url"
66 "strconv"
7 "time"
78 )
89
910 const (
345346
346347 // GetUsersContext returns the list of users (with their detailed information) with a custom context
347348 func (api *Client) GetUsersContext(ctx context.Context) (results []User, err error) {
348 var (
349 p UserPagination
350 )
351
352 for p = api.GetUsersPaginated(); !p.Done(err); p, err = p.Next(ctx) {
353 results = append(results, p.Users...)
349 p := api.GetUsersPaginated()
350 for err == nil {
351 p, err = p.Next(ctx)
352 if err == nil {
353 results = append(results, p.Users...)
354 } else if rateLimitedError, ok := err.(*RateLimitedError); ok {
355 select {
356 case <-ctx.Done():
357 return nil, ctx.Err()
358 case <-time.After(rateLimitedError.RetryAfter):
359 err = nil
360 }
361 }
354362 }
355363
356364 return results, p.Failure(err)
4949 }
5050 }
5151
52 func getTestUser() User {
52 func getTestUserWithId(id string) User {
5353 return User{
54 ID: "UXXXXXXXX",
54 ID: id,
5555 Name: "Test User",
5656 Deleted: false,
5757 Color: "9f69e7",
6969 Updated: 1555425715,
7070 Has2FA: false,
7171 }
72 }
73
74 func getTestUser() User {
75 return getTestUserWithId("UXXXXXXXX")
7276 }
7377
7478 func getUserIdentity(rw http.ResponseWriter, r *http.Request) {
302306 }
303307
304308 func TestGetUsers(t *testing.T) {
309 http.DefaultServeMux = new(http.ServeMux)
305310 http.HandleFunc("/users.list", getUserPage(4))
306 expectedUser := getTestUser()
307311
308312 once.Do(startServer)
309313 api := New("testing-token", OptionAPIURL("http://"+serverAddr+"/"))
314318 return
315319 }
316320
317 if !reflect.DeepEqual([]User{expectedUser, expectedUser, expectedUser, expectedUser}, users) {
321 if !reflect.DeepEqual([]User{
322 getTestUserWithId("U000"),
323 getTestUserWithId("U001"),
324 getTestUserWithId("U002"),
325 getTestUserWithId("U003"),
326 }, users) {
318327 t.Fatal(ErrIncorrectResponse)
319328 }
320329 }
328337 Ok: true,
329338 }
330339 members := []User{
331 getTestUser(),
340 getTestUserWithId(fmt.Sprintf("U%03d", n)),
332341 }
333342 rw.Header().Set("Content-Type", "application/json")
334343 if cpage = atomic.AddInt64(&n, 1); cpage == max {
348357 }
349358 }
350359
360 // returns n pages of users and sends rate limited errors in between successful pages.
361 func getUserPagesWithRateLimitErrors(max int64) func(rw http.ResponseWriter, r *http.Request) {
362 var n int64
363 doRateLimit := false
364 return func(rw http.ResponseWriter, r *http.Request) {
365 defer func() {
366 doRateLimit = !doRateLimit
367 }()
368 if doRateLimit {
369 rw.Header().Set("Retry-After", "1")
370 rw.WriteHeader(http.StatusTooManyRequests)
371 return
372 }
373 var cpage int64
374 sresp := SlackResponse{
375 Ok: true,
376 }
377 members := []User{
378 getTestUserWithId(fmt.Sprintf("U%03d", n)),
379 }
380 rw.Header().Set("Content-Type", "application/json")
381 if cpage = atomic.AddInt64(&n, 1); cpage == max {
382 response, _ := json.Marshal(userResponseFull{
383 SlackResponse: sresp,
384 Members: members,
385 })
386 rw.Write(response)
387 return
388 }
389 response, _ := json.Marshal(userResponseFull{
390 SlackResponse: sresp,
391 Members: members,
392 Metadata: ResponseMetadata{Cursor: strconv.Itoa(int(cpage))},
393 })
394 rw.Write(response)
395 }
396 }
397
351398 func TestSetUserPhoto(t *testing.T) {
352399 file, fileContent, teardown := createUserPhoto(t)
353400 defer teardown()
552599 t.Fatalf(`fields.fields = %v, wanted %v`, fields.fields, m)
553600 }
554601 }
602
603 func TestGetUsersHandlesRateLimit(t *testing.T) {
604 http.DefaultServeMux = new(http.ServeMux)
605 http.HandleFunc("/users.list", getUserPagesWithRateLimitErrors(4))
606
607 once.Do(startServer)
608 api := New("testing-token", OptionAPIURL("http://"+serverAddr+"/"))
609
610 users, err := api.GetUsers()
611 if err != nil {
612 t.Errorf("Unexpected error: %s", err)
613 return
614 }
615
616 if !reflect.DeepEqual([]User{
617 getTestUserWithId("U000"),
618 getTestUserWithId("U001"),
619 getTestUserWithId("U002"),
620 getTestUserWithId("U003"),
621 }, users) {
622 t.Fatal(ErrIncorrectResponse)
623 }
624 }
625
626 func TestGetUsersReturnsServerError(t *testing.T) {
627 http.DefaultServeMux = new(http.ServeMux)
628 http.HandleFunc("/users.list", func(w http.ResponseWriter, r *http.Request) {
629 w.WriteHeader(http.StatusInternalServerError)
630 })
631
632 once.Do(startServer)
633 api := New("testing-token", OptionAPIURL("http://"+serverAddr+"/"))
634
635 _, err := api.GetUsers()
636
637 if err == nil {
638 t.Errorf("Expected error but got nil")
639 return
640 }
641
642 expectedErr := "slack server error: 500 Internal Server Error"
643 if err.Error() != expectedErr {
644 t.Errorf("Expected: %s. Got: %s", expectedErr, err.Error())
645 }
646 }