diff --git a/govcr_wb_test.go b/govcr_wb_test.go index 632f40e..15e42bb 100644 --- a/govcr_wb_test.go +++ b/govcr_wb_test.go @@ -19,10 +19,10 @@ import ( func TestRoundTrip_SavesMutatedTracksToCassette(t *testing.T) { const cassetteName = "govcr-fixtures/TestRoundTrip_SavesMutatedCassetteTracks.cassette" - _ = os.Remove(cassetteName) var testServer *httptest.Server + // create a test server for the purpose of this test func() { counter := 0 testServer = httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -38,16 +38,22 @@ func TestRoundTrip_SavesMutatedTracksToCassette(t *testing.T) { testServerClient := testServer.Client() testServerClient.Timeout = 3 * time.Second + // example mutator, mutation is not too intrusive to allow replaying correctly. + // for instance, when an Err is injected, the response is set to nil on replay, as per + // go's HTTP client design. aMutator := TrackMutator( func(trk *track.Track) { - trk.Request.Method = trk.Request.Method + " has been mutated" + q := trk.Request.URL.Query() + q.Set("mutated_query_key", "this_query_key_has_been_mutated") + trk.Request.URL.RawQuery = q.Encode() trk.Response.Status = trk.Response.Status + " has been mutated" - trk.ErrType = "ErrType was mutated" - trk.ErrMsg = "ErrMsg was mutated" }) + // create a new VCR for the test vcr := NewVCR(WithClient(testServerClient), WithTrackRecordingMutators(aMutator)) + // load a fresh cassette + _ = os.Remove(cassetteName) err := vcr.LoadCassette(cassetteName) assert.NoError(t, err) defer func() { _ = os.Remove(cassetteName) }() @@ -61,15 +67,23 @@ func TestRoundTrip_SavesMutatedTracksToCassette(t *testing.T) { } require.EqualValues(t, expectedStats, actualStats) + // load the cassette and verify contents has been mutated. err = vcr.LoadCassette(cassetteName) assert.NoError(t, err) for trackNum, aTrack := range vcr.vcrTransport().cassette.Tracks { - require.EqualValues(t, "GET has been mutated", aTrack.Request.Method, "track #%d", trackNum) + require.EqualValues(t, "this_query_key_has_been_mutated", aTrack.Request.URL.Query().Get("mutated_query_key"), "track #%d", trackNum) require.EqualValues(t, "200 OK has been mutated", aTrack.Response.Status, "track #%d", trackNum) - require.EqualValues(t, "ErrType was mutated", aTrack.ErrType, "track #%d", trackNum) - require.EqualValues(t, "ErrMsg was mutated", aTrack.ErrMsg, "track #%d", trackNum) } + + // 2nd execution of set of calls (replayed) + actualStats = replayHTTPCalls_WithMutations_WithSuccess(testServer.URL, vcr, t) + expectedStats = stats.Stats{ + TracksLoaded: 2, + TracksRecorded: 0, + TracksPlayed: 2, + } + assert.EqualValues(t, expectedStats, actualStats) } func makeHTTPCalls_WithSuccess(testServerURL string, vcr *ControlPanel, t *testing.T) stats.Stats { @@ -82,6 +96,49 @@ func makeHTTPCalls_WithSuccess(testServerURL string, vcr *ControlPanel, t *testi resp, err := vcr.Player().Do(req) require.NoError(t, err) + require.Equal(t, "200 OK", resp.Status) + require.Equal(t, http.StatusOK, resp.StatusCode) + require.EqualValues(t, strconv.Itoa(38+len(strconv.Itoa(i))), resp.Header.Get("Content-Length")) + require.EqualValues(t, "text/plain; charset=utf-8", resp.Header.Get("Content-Type")) + require.NotEmpty(t, resp.Header.Get("Date")) + require.EqualValues(t, resp.Trailer, http.Header(nil)) + + bodyBytes, err := ioutil.ReadAll(resp.Body) + require.NoError(t, err) + _ = resp.Body.Close() + require.Equal(t, fmt.Sprintf("Hello, server responds '%d' to query '%d'", i, i), string(bodyBytes)) + + require.Equal(t, int64(38+len(strconv.Itoa(i))), resp.ContentLength) + require.NotNil(t, resp.Request) + require.NotNil(t, resp.TLS) + } + + require.EqualValues(t, 2, vcr.NumberOfTracks()) + + actualStats := *vcr.Stats() + vcr.EjectCassette() + + return actualStats +} + +func replayHTTPCalls_WithMutations_WithSuccess(testServerURL string, vcr *ControlPanel, t *testing.T) stats.Stats { + for i := 1; i <= 2; i++ { + req, err := http.NewRequest(http.MethodGet, testServerURL+fmt.Sprintf("?i=%d", i), nil) + require.NoError(t, err) + + // manually modify the request inline with the previous mutations that took place. + // not doing so would prevent matching our request against the (mutated) cassette. + q := req.URL.Query() + q.Set("mutated_query_key", "this_query_key_has_been_mutated") + req.URL.RawQuery = q.Encode() + + req.Header.Add("header", "value") + req.SetBasicAuth("not_a_username", "not_a_password") + + resp, err := vcr.Player().Do(req) + require.NoError(t, err) + + require.Equal(t, "200 OK has been mutated", resp.Status) require.Equal(t, http.StatusOK, resp.StatusCode) require.EqualValues(t, strconv.Itoa(38+len(strconv.Itoa(i))), resp.Header.Get("Content-Length")) require.EqualValues(t, "text/plain; charset=utf-8", resp.Header.Get("Content-Type")) diff --git a/vcrsettings.go b/vcrsettings.go index bee3fe8..e5bdb13 100644 --- a/vcrsettings.go +++ b/vcrsettings.go @@ -14,6 +14,8 @@ type Setting func(vcrConfig *VCRSettings) // with the Long Play function enabled. // LongPlay simply compresses the contents of the cassette to make // it smaller. +// TODO this is not needed if the LongPlay mode is autosensed from the cassette name +// ie if the name ends with '.gz' func WithLongPlay() Setting { return func(vcrConfig *VCRSettings) { vcrConfig.longPlay = true