Browse Source

Add integrations tests for Authorizations API

Fixes #119
Fixes #325
Ref #241
Neil O'Toole 10 years ago
committed by Will Norris
parent
commit
5379d93f65
3 changed files with 324 additions and 0 deletions
  1. +10
    -0
      tests/README.md
  2. +303
    -0
      tests/integration/authorizations_test.go
  3. +11
    -0
      tests/integration/github_test.go

+ 10
- 0
tests/README.md View File

@ -31,6 +31,16 @@ Run tests using:
GITHUB_AUTH_TOKEN=XXX go test -v -tags=integration ./integration
Additionally there are a set of integration tests for the Authorizations API.
These tests require a GitHub user (username and password), and also that a
[GitHub Application](https://github.com/settings/applications/new) (with
attendant Client ID and Client Secret) be available. Then, to execute just the
Authorization tests:
GITHUB_USERNAME='<GH_USERNAME>' GITHUB_PASSWORD='<GH_PASSWORD>' GITHUB_CLIENT_ID='<CLIENT_ID>' GITHUB_CLIENT_SECRET='<CLIENT_SECRET>' go test -v -tags=integration --run=Authorizations ./integration
If some or all of these environment variables are not available, certain of the
Authorization integration tests will be skipped.
fields
------


+ 303
- 0
tests/integration/authorizations_test.go View File

@ -0,0 +1,303 @@
// Copyright 2016 The go-github AUTHORS. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package tests
import (
"math/rand"
"os"
"strconv"
"strings"
"testing"
"time"
"github.com/google/go-github/github"
)
const msgEnvMissing = "Skipping test because the required environment variable (%v) is not present."
const envKeyGitHubUsername = "GITHUB_USERNAME"
const envKeyGitHubPassword = "GITHUB_PASSWORD"
const envKeyClientID = "GITHUB_CLIENT_ID"
const envKeyClientSecret = "GITHUB_CLIENT_SECRET"
const InvalidTokenValue = "iamnotacroken"
// TestAuthorizationsBasicOperations tests the basic CRUD operations of the API (mostly for
// the Personal Access Token scenario).
func TestAuthorizationsBasicOperations(t *testing.T) {
client := getUserPassClient(t)
auths, resp, err := client.Authorizations.List(nil)
failOnError(t, err)
failIfNotStatusCode(t, resp, 200)
initialAuthCount := len(auths)
authReq := generatePersonalAuthTokenRequest()
createdAuth, resp, err := client.Authorizations.Create(authReq)
failOnError(t, err)
failIfNotStatusCode(t, resp, 201)
if *authReq.Note != *createdAuth.Note {
t.Fatal("Returned Authorization does not match the requested Authorization.")
}
auths, resp, err = client.Authorizations.List(nil)
failOnError(t, err)
failIfNotStatusCode(t, resp, 200)
if len(auths) != initialAuthCount+1 {
t.Fatalf("The number of Authorizations should have increased. Expected [%v], was [%v]", (initialAuthCount + 1), len(auths))
}
// Test updating the authorization
authUpdate := new(github.AuthorizationUpdateRequest)
authUpdate.Note = github.String("Updated note: " + randString())
updatedAuth, resp, err := client.Authorizations.Edit(*createdAuth.ID, authUpdate)
failOnError(t, err)
failIfNotStatusCode(t, resp, 200)
if *updatedAuth.Note != *authUpdate.Note {
t.Fatal("The returned Authorization does not match the requested updated value.")
}
// Verify that the Get operation also reflects the update
retrievedAuth, resp, err := client.Authorizations.Get(*createdAuth.ID)
failOnError(t, err)
failIfNotStatusCode(t, resp, 200)
if *retrievedAuth.Note != *updatedAuth.Note {
t.Fatal("The retrieved Authorization does not match the expected (updated) value.")
}
// Now, let's delete...
resp, err = client.Authorizations.Delete(*createdAuth.ID)
failOnError(t, err)
failIfNotStatusCode(t, resp, 204)
// Verify that we can no longer retrieve the auth
retrievedAuth, resp, err = client.Authorizations.Get(*createdAuth.ID)
if err == nil {
t.Fatal("Should have failed due to 404")
}
failIfNotStatusCode(t, resp, 404)
// Verify that our count reset back to the initial value
auths, resp, err = client.Authorizations.List(nil)
failOnError(t, err)
failIfNotStatusCode(t, resp, 200)
if len(auths) != initialAuthCount {
t.Fatal("The number of Authorizations should match the initial count Expected [%v], got [%v]", (initialAuthCount), len(auths))
}
}
// TestAuthorizationsAppOperations tests the application/token related operations, such
// as creating, testing, resetting and revoking application OAuth tokens.
func TestAuthorizationsAppOperations(t *testing.T) {
userAuthenticatedClient := getUserPassClient(t)
appAuthenticatedClient := getOAuthAppClient(t)
// We know these vars are set because getOAuthAppClient would have
// skipped the test by now
clientID := os.Getenv(envKeyClientID)
clientSecret := os.Getenv(envKeyClientSecret)
authRequest := generateAppAuthTokenRequest(clientID, clientSecret)
createdAuth, resp, err := userAuthenticatedClient.Authorizations.GetOrCreateForApp(clientID, authRequest)
failOnError(t, err)
failIfNotStatusCode(t, resp, 201)
// Quick sanity check:
if *createdAuth.Note != *authRequest.Note {
t.Fatal("The returned auth does not match expected value.")
}
// Let's try the same request again, this time it should return the same
// auth instead of creating a new one
secondAuth, resp, err := userAuthenticatedClient.Authorizations.GetOrCreateForApp(clientID, authRequest)
failOnError(t, err)
failIfNotStatusCode(t, resp, 200)
// Verify that the IDs are the same
if *createdAuth.ID != *secondAuth.ID {
t.Fatalf("The ID of the second returned auth should be the same as the first. Expected [%v], got [%v]", createdAuth.ID, secondAuth.ID)
}
// Verify the token
appAuth, resp, err := appAuthenticatedClient.Authorizations.Check(clientID, *createdAuth.Token)
failOnError(t, err)
failIfNotStatusCode(t, resp, 200)
// Quick sanity check
if *appAuth.ID != *createdAuth.ID || *appAuth.Token != *createdAuth.Token {
t.Fatal("The returned auth/token does not match.")
}
// Let's verify that we get a 404 for a non-existent token
_, resp, err = appAuthenticatedClient.Authorizations.Check(clientID, InvalidTokenValue)
if err == nil {
t.Fatal("An error should have been returned because of the invalid token.")
}
failIfNotStatusCode(t, resp, 404)
// Let's reset the token
resetAuth, resp, err := appAuthenticatedClient.Authorizations.Reset(clientID, *createdAuth.Token)
failOnError(t, err)
failIfNotStatusCode(t, resp, 200)
// Let's verify that we get a 404 for a non-existent token
_, resp, err = appAuthenticatedClient.Authorizations.Reset(clientID, InvalidTokenValue)
if err == nil {
t.Fatal("An error should have been returned because of the invalid token.")
}
failIfNotStatusCode(t, resp, 404)
// Verify that the token has changed
if resetAuth.Token == createdAuth.Token {
t.Fatal("The reset token should be different from the original.")
}
// Verify that we do have a token value
if *resetAuth.Token == "" {
t.Fatal("A token value should have been returned.")
}
// Verify that the original token is now invalid
_, resp, err = appAuthenticatedClient.Authorizations.Check(clientID, *createdAuth.Token)
if err == nil {
t.Fatal("The original token should be invalid.")
}
failIfNotStatusCode(t, resp, 404)
// Check that the reset token is valid
_, resp, err = appAuthenticatedClient.Authorizations.Check(clientID, *resetAuth.Token)
failOnError(t, err)
failIfNotStatusCode(t, resp, 200)
// Let's revoke the token
resp, err = appAuthenticatedClient.Authorizations.Revoke(clientID, *resetAuth.Token)
failOnError(t, err)
failIfNotStatusCode(t, resp, 204)
// Sleep for two seconds... I've seen cases where the revocation appears not
// to have take place immediately.
time.Sleep(time.Second * 2)
// Now, the reset token should also be invalid
_, resp, err = appAuthenticatedClient.Authorizations.Check(clientID, *resetAuth.Token)
if err == nil {
t.Fatal("The reset token should be invalid.")
}
failIfNotStatusCode(t, resp, 404)
}
// generatePersonalAuthTokenRequest is a helper function that generates an
// AuthorizationRequest for a Personal Access Token (no client id).
func generatePersonalAuthTokenRequest() *github.AuthorizationRequest {
rand := randString()
auth := github.AuthorizationRequest{
Note: github.String("Personal token: Note generated by test: " + rand),
Scopes: []github.Scope{github.ScopePublicRepo},
Fingerprint: github.String("Personal token: Fingerprint generated by test: " + rand),
}
return &auth
}
// generatePersonalAuthTokenRequest is a helper function that generates an
// AuthorizationRequest for an OAuth application Token (uses client id).
func generateAppAuthTokenRequest(clientID string, clientSecret string) *github.AuthorizationRequest {
rand := randString()
auth := github.AuthorizationRequest{
Note: github.String("App token: Note generated by test: " + rand),
Scopes: []github.Scope{github.ScopePublicRepo},
Fingerprint: github.String("App token: Fingerprint generated by test: " + rand),
ClientID: github.String(clientID),
ClientSecret: github.String(clientSecret),
}
return &auth
}
// randString returns a (kinda) random string for uniqueness purposes.
func randString() string {
return strconv.FormatInt(rand.NewSource(time.Now().UnixNano()).Int63(), 10)
}
// failOnError invokes t.Fatal() if err is present.
func failOnError(t *testing.T, err error) {
if err != nil {
t.Fatal(err)
}
}
// failIfNotStatusCode invokes t.Fatal() if the response's status code doesn't match the expected code.
func failIfNotStatusCode(t *testing.T, resp *github.Response, expectedCode int) {
if resp.StatusCode != expectedCode {
t.Fatalf("Expected HTTP status code [%v] but received [%v]", expectedCode, resp.StatusCode)
}
}
// getUserPassClient returns a GitHub client for authorization testing. The client
// uses BasicAuth via GH username and password passed in environment variables
// (and will skip the calling test if those vars are not present).
func getUserPassClient(t *testing.T) *github.Client {
username, ok := os.LookupEnv(envKeyGitHubUsername)
if !ok {
t.Skipf(msgEnvMissing, envKeyGitHubUsername)
}
password, ok := os.LookupEnv(envKeyGitHubPassword)
if !ok {
t.Skipf(msgEnvMissing, envKeyGitHubPassword)
}
tp := github.BasicAuthTransport{
Username: strings.TrimSpace(username),
Password: strings.TrimSpace(password),
}
return github.NewClient(tp.Client())
}
// getOAuthAppClient returns a GitHub client for authorization testing. The client
// uses BasicAuth, but instead of username and password, it uses the client id
// and client secret passed in via environment variables
// (and will skip the calling test if those vars are not present). Certain API operations (check
// an authorization; reset an authorization; revoke an authorization for an app)
// require this authentication mechanism.
//
// See GitHub API docs: https://developer.com/v3/oauth_authorizations/#check-an-authorization
func getOAuthAppClient(t *testing.T) *github.Client {
username, ok := os.LookupEnv(envKeyClientID)
if !ok {
t.Skipf(msgEnvMissing, envKeyClientID)
}
password, ok := os.LookupEnv(envKeyClientSecret)
if !ok {
t.Skipf(msgEnvMissing, envKeyClientSecret)
}
tp := github.BasicAuthTransport{
Username: strings.TrimSpace(username),
Password: strings.TrimSpace(password),
}
return github.NewClient(tp.Client())
}

+ 11
- 0
tests/integration/github_test.go View File

@ -39,6 +39,17 @@ func init() {
client = github.NewClient(tc)
auth = true
}
// Environment variables required for Authorization integration tests
vars := []string{envKeyGitHubUsername, envKeyGitHubPassword, envKeyClientID, envKeyClientSecret}
for _, v := range vars {
value := os.Getenv(v)
if value == "" {
print("!!! " + fmt.Sprintf(msgEnvMissing, v) + " !!!\n\n")
}
}
}
func checkAuth(name string) bool {


Loading…
Cancel
Save