diff --git a/digits/token_test.go b/digits/token_test.go index ea91284..0c5f4be 100644 --- a/digits/token_test.go +++ b/digits/token_test.go @@ -1,11 +1,15 @@ package digits import ( + "context" + "fmt" "net/http" "net/http/httptest" "net/url" + "strings" "testing" + "github.com/dghubble/gologin" oauth1Login "github.com/dghubble/gologin/oauth1" "github.com/dghubble/gologin/testutils" "github.com/dghubble/oauth1" @@ -30,6 +34,9 @@ func TestTokenHandler(t *testing.T) { proxyClient, _, server := newDigitsTestServer(testAccountJSON) defer server.Close() + // oauth1 Client will use the proxy client's base Transport + ctx := context.WithValue(context.Background(), oauth1.HTTPClient, proxyClient) + config := &oauth1.Config{} success := func(w http.ResponseWriter, req *http.Request) { ctx := req.Context() @@ -43,29 +50,51 @@ func TestTokenHandler(t *testing.T) { assert.Nil(t, err) assert.Equal(t, testDigitsToken, accessToken) assert.Equal(t, testDigitsSecret, accessSecret) + fmt.Fprintf(w, "success handler called") } - handler := TokenHandler(config, http.HandlerFunc(success), testutils.AssertFailureNotCalled(t)) - // oauth1 Client will use the proxy client's base Transport - ts := httptest.NewServer(oauth1Login.WithHTTPClient(proxyClient, handler)) - // POST Digits access token to server under test - resp, err := http.PostForm(ts.URL, url.Values{accessTokenField: {testDigitsToken}, accessTokenSecretField: {testDigitsSecret}}) - assert.Nil(t, err) - if assert.NotNil(t, resp) { - assert.Equal(t, resp.StatusCode, http.StatusOK) - } + + // TokenHandler assert that: + // - access token/secret are read from POST + // - digits account is obtained from the Digits accounts endpoint + // - success handler is called + // - digits account is added to the success handler ctx + tokenHandler := TokenHandler(config, http.HandlerFunc(success), testutils.AssertFailureNotCalled(t)) + w := httptest.NewRecorder() + form := url.Values{accessTokenField: {testDigitsToken}, accessTokenSecretField: {testDigitsSecret}} + req, _ := http.NewRequest("POST", "/", strings.NewReader(form.Encode())) + req.Header.Add("Content-Type", "application/x-www-form-urlencoded") + tokenHandler.ServeHTTP(w, req.WithContext(ctx)) + assert.Equal(t, http.StatusOK, w.Code) + assert.Equal(t, "success handler called", w.Body.String()) } func TestTokenHandler_ErrorVerifyingToken(t *testing.T) { proxyClient, server := testutils.NewErrorServer("Digits Account Endpoint Down", http.StatusInternalServerError) defer server.Close() - config := &oauth1.Config{} - handler := TokenHandler(config, testutils.AssertSuccessNotCalled(t), nil) // oauth1 Client will use the proxy client's base Transport - ts := httptest.NewServer(oauth1Login.WithHTTPClient(proxyClient, handler)) - // assert that error occurs indicating the Digits Account could not be confirmed - resp, _ := http.PostForm(ts.URL, url.Values{accessTokenField: {testDigitsToken}, accessTokenSecretField: {testDigitsSecret}}) - testutils.AssertBodyString(t, resp.Body, ErrUnableToGetDigitsAccount.Error()+"\n") + ctx := context.WithValue(context.Background(), oauth1.HTTPClient, proxyClient) + + config := &oauth1.Config{} + failure := func(w http.ResponseWriter, req *http.Request) { + ctx := req.Context() + err := gologin.ErrorFromContext(ctx) + if assert.Error(t, err) { + assert.Equal(t, err, ErrUnableToGetDigitsAccount) + } + fmt.Fprintf(w, "failure handler called") + } + + // TokenHandler cannot verify Digits account, assert that: + // - failure handler is called + // - error is added to the failure handler context + tokenHandler := TokenHandler(config, testutils.AssertSuccessNotCalled(t), http.HandlerFunc(failure)) + w := httptest.NewRecorder() + form := url.Values{accessTokenField: {testDigitsToken}, accessTokenSecretField: {testDigitsSecret}} + req, _ := http.NewRequest("POST", "/", strings.NewReader(form.Encode())) + req.Header.Add("Content-Type", "application/x-www-form-urlencoded") + tokenHandler.ServeHTTP(w, req.WithContext(ctx)) + assert.Equal(t, "failure handler called", w.Body.String()) } func TestTokenHandler_NonPost(t *testing.T) { diff --git a/github/login_test.go b/github/login_test.go index ff146da..bb05246 100644 --- a/github/login_test.go +++ b/github/login_test.go @@ -20,6 +20,7 @@ func TestGithubHandler(t *testing.T) { expectedUser := &github.User{ID: github.Int(917408), Name: github.String("Alyssa Hacker")} proxyClient, server := newGithubTestServer(jsonData) defer server.Close() + // oauth2 Client will use the proxy client's base Transport ctx := context.WithValue(context.Background(), oauth2.HTTPClient, proxyClient) anyToken := &oauth2.Token{AccessToken: "any-token"} diff --git a/oauth1/context.go b/oauth1/context.go index e4e2e68..b911377 100644 --- a/oauth1/context.go +++ b/oauth1/context.go @@ -3,9 +3,6 @@ package oauth1 import ( "context" "fmt" - "net/http" - - olib "github.com/dghubble/oauth1" ) // unexported key type prevents collisions @@ -53,11 +50,3 @@ func AccessTokenFromContext(ctx context.Context) (string, string, error) { } return accessToken, accessSecret, nil } - -// WithHTTPClient returns a handler that sets the provided HttpClient in the request context. -func WithHTTPClient(client *http.Client, next http.Handler) http.Handler { - fn := func(w http.ResponseWriter, req *http.Request) { - next.ServeHTTP(w, req.WithContext(context.WithValue(req.Context(), olib.HTTPClient, client))) - } - return http.HandlerFunc(fn) -} diff --git a/twitter/token_test.go b/twitter/token_test.go index 2e0c627..3e0c811 100644 --- a/twitter/token_test.go +++ b/twitter/token_test.go @@ -1,10 +1,12 @@ package twitter import ( + "context" "fmt" "net/http" "net/http/httptest" "net/url" + "strings" "testing" "github.com/dghubble/gologin" @@ -25,6 +27,9 @@ func TestTokenHandler(t *testing.T) { proxyClient, _, server := newTwitterVerifyServer(testTwitterUserJSON) defer server.Close() + // oauth1 Client will use the proxy client's base Transport + ctx := context.WithValue(context.Background(), oauth1.HTTPClient, proxyClient) + config := &oauth1.Config{} success := func(w http.ResponseWriter, req *http.Request) { ctx := req.Context() @@ -37,48 +42,52 @@ func TestTokenHandler(t *testing.T) { assert.Nil(t, err) assert.Equal(t, expectedUserID, user.ID) assert.Equal(t, "1234", user.IDStr) + fmt.Fprintf(w, "success handler called") } - handler := TokenHandler(config, http.HandlerFunc(success), testutils.AssertFailureNotCalled(t)) - // oauth1 Client will use the proxy client's base Transport - ts := httptest.NewServer(oauth1Login.WithHTTPClient(proxyClient, handler)) - // POST token to server under test - resp, err := http.PostForm(ts.URL, url.Values{accessTokenField: {testTwitterToken}, accessTokenSecretField: {testTwitterTokenSecret}}) - assert.Nil(t, err) - if assert.NotNil(t, resp) { - assert.Equal(t, resp.StatusCode, http.StatusOK) - } + failure := testutils.AssertFailureNotCalled(t) + + // TokenHandler assert that: + // - access token/secret are read from POST + // - twitter User is obtained from Twitter API + // - success handler is called + // - twitter User is added to success handler ctx + tokenHandler := TokenHandler(config, http.HandlerFunc(success), failure) + w := httptest.NewRecorder() + form := url.Values{accessTokenField: {testTwitterToken}, accessTokenSecretField: {testTwitterTokenSecret}} + req, _ := http.NewRequest("POST", "/", strings.NewReader(form.Encode())) + req.Header.Add("Content-Type", "application/x-www-form-urlencoded") + tokenHandler.ServeHTTP(w, req.WithContext(ctx)) + assert.Equal(t, http.StatusOK, w.Code) + assert.Equal(t, "success handler called", w.Body.String()) } func TestTokenHandler_ErrorVerifyingToken(t *testing.T) { proxyClient, server := testutils.NewErrorServer("Twitter Verify Credentials Down", http.StatusInternalServerError) defer server.Close() - config := &oauth1.Config{} - handler := TokenHandler(config, testutils.AssertSuccessNotCalled(t), nil) // oauth1 Client will use the proxy client's base Transport - ts := httptest.NewServer(oauth1Login.WithHTTPClient(proxyClient, handler)) - // assert that error occurs indicating the Twitter User could not be confirmed - resp, _ := http.PostForm(ts.URL, url.Values{accessTokenField: {testTwitterToken}, accessTokenSecretField: {testTwitterTokenSecret}}) - testutils.AssertBodyString(t, resp.Body, ErrUnableToGetTwitterUser.Error()+"\n") -} - -func TestTokenHandler_ErrorVerifyingTokenPassesError(t *testing.T) { - proxyClient, server := testutils.NewErrorServer("Twitter Verify Credentials Down", http.StatusInternalServerError) - defer server.Close() + ctx := context.WithValue(context.Background(), oauth1.HTTPClient, proxyClient) config := &oauth1.Config{} failure := func(w http.ResponseWriter, req *http.Request) { ctx := req.Context() - // assert that error passed through ctx err := gologin.ErrorFromContext(ctx) if assert.Error(t, err) { assert.Equal(t, err, ErrUnableToGetTwitterUser) } + fmt.Fprintf(w, "failure handler called") } - handler := TokenHandler(config, testutils.AssertSuccessNotCalled(t), http.HandlerFunc(failure)) - // oauth1 Client will use the proxy client's base Transport - ts := httptest.NewServer(oauth1Login.WithHTTPClient(proxyClient, handler)) - http.PostForm(ts.URL, url.Values{accessTokenField: {testTwitterToken}, accessTokenSecretField: {testTwitterTokenSecret}}) + + // TokenHandler cannot verify Twitter credentials and get User, assert that: + // - failure handler is called + // - error is added to the failure handler context + tokenHandler := TokenHandler(config, testutils.AssertSuccessNotCalled(t), http.HandlerFunc(failure)) + w := httptest.NewRecorder() + form := url.Values{accessTokenField: {testTwitterToken}, accessTokenSecretField: {testTwitterTokenSecret}} + req, _ := http.NewRequest("POST", "/", strings.NewReader(form.Encode())) + req.Header.Add("Content-Type", "application/x-www-form-urlencoded") + tokenHandler.ServeHTTP(w, req.WithContext(ctx)) + assert.Equal(t, "failure handler called", w.Body.String()) } func TestTokenHandler_NonPost(t *testing.T) {