diff --git a/recorder/recorder.go b/recorder/recorder.go index dc890d1..f95784a 100644 --- a/recorder/recorder.go +++ b/recorder/recorder.go @@ -111,6 +111,11 @@ const ( // invoked before replaying a previously recorded response to // the client. BeforeResponseReplayHook + + // OnRecorderStopHook is a hook, which will be invoked when the recorder + // is about to be stopped. This hook is useful for performing any + // post-actions such as cleanup or reporting. + OnRecorderStopHook ) // Hook represents a function hook of a given kind. Depending on the @@ -388,16 +393,27 @@ func (rec *Recorder) Stop() error { _, err := os.Stat(cassetteFile) cassetteExists := !os.IsNotExist(err) + // Nothing to do for ModeReplayOnly and ModePassthrough here switch { case rec.options.Mode == ModeRecordOnly || rec.options.Mode == ModeReplayWithNewEpisodes: - return rec.persistCassette() - case rec.options.Mode == ModeReplayOnly || rec.options.Mode == ModePassthrough: - return nil + if err := rec.persistCassette(); err != nil { + return err + } + case rec.options.Mode == ModeRecordOnce && !cassetteExists: - return rec.persistCassette() - default: - return nil + if err := rec.persistCassette(); err != nil { + return err + } } + + // Apply on-recorder-stop hooks + for _, interaction := range rec.cassette.Interactions { + if err := rec.applyHooks(interaction, OnRecorderStopHook); err != nil { + return err + } + } + + return nil } // persisteCassette persists the cassette on disk for future re-use diff --git a/recorder/recorder_test.go b/recorder/recorder_test.go index 1deb0d4..0340c91 100644 --- a/recorder/recorder_test.go +++ b/recorder/recorder_test.go @@ -987,6 +987,17 @@ func TestReplayableInteractions(t *testing.T) { t.Fatal("recorder is not recording") } + // Create an on-recorder-stop hook to verify that interactions were + // replayed + errNotReplayed := errors.New("interaction was not replayed") + hook := func(i *cassette.Interaction) error { + if !i.WasReplayed() { + return errNotReplayed + } + return nil + } + rec.AddHook(hook, recorder.OnRecorderStopHook) + // Configure replayable interactions rec.SetReplayableInteractions(true) @@ -999,8 +1010,10 @@ func TestReplayableInteractions(t *testing.T) { } } - // We should have only 1 interaction recorded - rec.Stop() + // We should have only 1 interaction recorded after stopping the recorder + if err := rec.Stop(); err != nil { + t.Fatalf("recorder did not stop properly: %s", err) + } c, err := cassette.Load(cassPath) if err != nil {