internal/githubtest/githubtest.go (60 lines of code) (raw):

// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one // or more contributor license agreements. Licensed under the Elastic License 2.0; // you may not use this file except in compliance with the Elastic License 2.0. package githubtest import ( "errors" "log" "net/http" "os" "path" "testing" "time" "github.com/dnaeon/go-vcr/cassette" "github.com/dnaeon/go-vcr/recorder" "github.com/elastic/elastic-agent-changelog-tool/internal/github" "github.com/spf13/afero" "github.com/stretchr/testify/require" "golang.org/x/oauth2" ) // getHttpClient instantiate a http.Client backed by a recorder.Recorder to be used in testing // scenarios. // As GitHub may require authentication, this function leverages AuthToken functionality to load // GitHub token from env or file; when missing instantiate an unauthenticated client. // NOTE: always remember to call (recorder.Recorder).Stop() in your test case. func GetHttpClient(t *testing.T) (*recorder.Recorder, *http.Client) { t.Helper() var err error testFs := afero.NewOsFs() tkloc, err := github.TokenLocation() require.NoError(t, err, "cannot get token location") tk := github.NewAuthToken(testFs, tkloc) token, err := tk.AuthToken() if err != nil && !errors.Is(err, os.ErrNotExist) { log.Fatalf("unexpected failure getting GitHub token: %v", err) } var rec *recorder.Recorder var hc *http.Client if err != nil && errors.Is(err, os.ErrNotExist) { // NOTE: the auth token was not present (nor in the env nor in the file) so we // initialize an unauthenticated http client and plain recorder. rec, err = recorder.New(path.Join("testdata", "fixtures", t.Name())) hc = &http.Client{ Transport: rec, Timeout: 2 * time.Second, } require.NoError(t, err) return rec, hc } if token == "" { log.Fatal("GitHub authorization token value was read but it is empty") } // NOTE: at this point the token is present, so we initialize a oauth2 http client // and the corresponding recorder; this is necessary to pass the authentication credentials // to the http client transport. ts := oauth2.StaticTokenSource( &oauth2.Token{AccessToken: token}, ) tr := &oauth2.Transport{ Base: http.DefaultTransport, Source: oauth2.ReuseTokenSource(nil, ts), } rec, err = recorder.NewAsMode(path.Join("testdata", "fixtures", t.Name()), recorder.ModeReplaying, tr) require.NoError(t, err) // filter out dynamic & sensitive data/headers. // NOTE: your test code will continue to see (and use) the real access token and // it is redacted before the recorded interactions are saved. rec.AddSaveFilter(func(i *cassette.Interaction) error { delete(i.Request.Headers, "Authorization") // i.Request.Headers["Authorization"] = []string{"Basic REDACTED"} return nil }) hc = &http.Client{ Transport: rec, Timeout: 2 * time.Second, } return rec, hc }