From 3ae9081fb9f686be98c3be0c8035ef75118441a8 Mon Sep 17 00:00:00 2001 From: seborama Date: Fri, 22 Jul 2016 17:35:22 +0100 Subject: [PATCH] [CassettePath] Added support to provide custom location for fixtures --- cassette.go | 36 +++++++++++++++++++++++------------- examples/main.go | 2 +- govcr.go | 8 ++++++-- govcr_example1_test.go | 2 +- govcr_example2_test.go | 2 +- govcr_example3_test.go | 2 +- govcr_test.go | 6 +++--- 7 files changed, 36 insertions(+), 22 deletions(-) diff --git a/cassette.go b/cassette.go index 1aa829b..1e371c6 100644 --- a/cassette.go +++ b/cassette.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "io/ioutil" + "log" "net" "net/http" "net/url" @@ -184,8 +185,8 @@ type Stats struct { // cassette contains a set of tracks. type cassette struct { - Name string - Tracks []track + Name, Path string + Tracks []track // stats is unexported since it doesn't need serialising stats Stats @@ -225,7 +226,7 @@ func (k7 *cassette) save() error { } // write cassette to file - filename := cassetteNameToFilename(k7.Name) + filename := cassetteNameToFilename(k7.Name, k7.Path) path := filepath.Dir(filename) if err := os.MkdirAll(path, 0750); err != nil { return err @@ -265,8 +266,8 @@ func (k7 *cassette) numberOfTracks() int { } // DeleteCassette removes the cassette file from disk. -func DeleteCassette(cassetteName string) error { - filename := cassetteNameToFilename(cassetteName) +func DeleteCassette(cassetteName, cassettePath string) error { + filename := cassetteNameToFilename(cassetteName, cassettePath) err := os.Remove(filename) if os.IsNotExist(err) { @@ -278,18 +279,27 @@ func DeleteCassette(cassetteName string) error { } // CassetteExistsAndValid verifies a cassette file exists and is seemingly valid. -func CassetteExistsAndValid(cassetteName string) bool { - _, err := readCassetteFromFile(cassetteName) +func CassetteExistsAndValid(cassetteName, cassettePath string) bool { + _, err := readCassetteFromFile(cassetteName, cassettePath) return err == nil } // cassetteNameToFilename returns the filename associated to the cassette. -func cassetteNameToFilename(cassetteName string) string { +func cassetteNameToFilename(cassetteName, cassettePath string) string { if cassetteName == "" { return "" } - return "./govcr-fixtures/" + cassetteName + ".cassette" + if cassettePath == "" { + cassettePath = defaultCassettePath + } + + fpath, err := filepath.Abs(filepath.Join(cassettePath, cassetteName+".cassette")) + if err != nil { + log.Fatal(err) + } + + return fpath } // transformInterfacesInJSON looks for known properties in the JSON that are defined as interface{} @@ -311,8 +321,8 @@ func transformInterfacesInJSON(jsonString []byte) ([]byte, error) { return []byte(regex.ReplaceAllString(string(jsonString), `$1"$2",`)), nil } -func loadCassette(cassetteName string) (*cassette, error) { - k7, err := readCassetteFromFile(cassetteName) +func loadCassette(cassetteName, cassettePath string) (*cassette, error) { + k7, err := readCassetteFromFile(cassetteName, cassettePath) if err != nil && !os.IsNotExist(err) { return nil, err } @@ -329,8 +339,8 @@ func loadCassette(cassetteName string) (*cassette, error) { } // readCassetteFromFile reads the cassette file, if present. -func readCassetteFromFile(cassetteName string) (*cassette, error) { - filename := cassetteNameToFilename(cassetteName) +func readCassetteFromFile(cassetteName, cassettePath string) (*cassette, error) { + filename := cassetteNameToFilename(cassetteName, cassettePath) // retrieve cassette from file data, err := ioutil.ReadFile(filename) diff --git a/examples/main.go b/examples/main.go index 182e351..11d5ceb 100644 --- a/examples/main.go +++ b/examples/main.go @@ -6,7 +6,7 @@ import "github.com/seborama/govcr" func runExample(name, cassetteName string, f func()) { fmt.Println("Running " + name + "...") fmt.Println("1st run =======================================================") - govcr.DeleteCassette(cassetteName) + govcr.DeleteCassette(cassetteName, "") f() fmt.Println("2nd run =======================================================") f() diff --git a/govcr.go b/govcr.go index 0ca5b29..9a8b7c1 100644 --- a/govcr.go +++ b/govcr.go @@ -21,14 +21,16 @@ func (vcr *VCRControlPanel) Stats() Stats { return vcrT.Cassette.Stats() } +const defaultCassettePath = "./govcr-fixtures/" + // VCRConfig holds a set of options for the VCR. -// TODO: update README.md with details of DisableRecording and FilterFunc's type VCRConfig struct { Client *http.Client ExcludeHeaderFunc ExcludeHeaderFunc RequestBodyFilterFunc BodyFilterFunc DisableRecording bool Logging bool + CassettePath string } // PCB stands for Printed Circuit Board. It is a structure that holds some @@ -39,6 +41,7 @@ type pcb struct { RequestBodyFilterFunc BodyFilterFunc Logger *log.Logger DisableRecording bool + CassettePath string } const trackNotFound = -1 @@ -135,7 +138,7 @@ func NewVCR(cassetteName string, vcrConfig *VCRConfig) *VCRControlPanel { } // load cassette - cassette, err := loadCassette(cassetteName) + cassette, err := loadCassette(cassetteName, vcrConfig.CassettePath) if err != nil { logger.Fatal(err) } @@ -148,6 +151,7 @@ func NewVCR(cassetteName string, vcrConfig *VCRConfig) *VCRControlPanel { ExcludeHeaderFunc: vcrConfig.ExcludeHeaderFunc, RequestBodyFilterFunc: vcrConfig.RequestBodyFilterFunc, Logger: logger, + CassettePath: vcrConfig.CassettePath, } // create VCR's HTTP client diff --git a/govcr_example1_test.go b/govcr_example1_test.go index 07875b2..91fc67f 100644 --- a/govcr_example1_test.go +++ b/govcr_example1_test.go @@ -32,7 +32,7 @@ func runTestEx1() { // http.Client suffices. func Example_number1SimpleVCR() { // Delete cassette to enable live HTTP call - govcr.DeleteCassette(example1CassetteName) + govcr.DeleteCassette(example1CassetteName, "") // 1st run of the test - will use live HTTP calls runTestEx1() diff --git a/govcr_example2_test.go b/govcr_example2_test.go index 0140add..4a3dbbe 100644 --- a/govcr_example2_test.go +++ b/govcr_example2_test.go @@ -83,7 +83,7 @@ func Example_number2CustomClientVCR1() { } // Delete cassette to enable live HTTP call - govcr.DeleteCassette(example2CassetteName) + govcr.DeleteCassette(example2CassetteName, "") // 1st run of the test - will use live HTTP calls runTestEx2(app) diff --git a/govcr_example3_test.go b/govcr_example3_test.go index c83f31e..bc6a3d3 100644 --- a/govcr_example3_test.go +++ b/govcr_example3_test.go @@ -58,7 +58,7 @@ func runTestEx4() { // http.Client suffices. func Example_number3HeaderExclusionVCR() { // Delete cassette to enable live HTTP call - govcr.DeleteCassette(example3CassetteName) + govcr.DeleteCassette(example3CassetteName, "") // 1st run of the test - will use live HTTP calls runTestEx4() diff --git a/govcr_test.go b/govcr_test.go index ca7c47a..a8d94bc 100644 --- a/govcr_test.go +++ b/govcr_test.go @@ -29,7 +29,7 @@ func TestPlaybackOrder(t *testing.T) { fmt.Println("Phase 1 ================================================") - if err := govcr.DeleteCassette(cassetteName); err != nil { + if err := govcr.DeleteCassette(cassetteName, ""); err != nil { t.Fatalf("err from govcr.DeleteCassette(): Expected nil, got %s", err) } @@ -43,7 +43,7 @@ func TestPlaybackOrder(t *testing.T) { // check outcome of the request checkResponseForTestPlaybackOrder(t, cassetteName, vcr, resp, i) - if !govcr.CassetteExistsAndValid(cassetteName) { + if !govcr.CassetteExistsAndValid(cassetteName, "") { t.Fatalf("CassetteExists: expected true, got false") } @@ -64,7 +64,7 @@ func TestPlaybackOrder(t *testing.T) { // check outcome of the request checkResponseForTestPlaybackOrder(t, cassetteName, vcr, resp, i) - if !govcr.CassetteExistsAndValid(cassetteName) { + if !govcr.CassetteExistsAndValid(cassetteName, "") { t.Fatalf("CassetteExists: expected true, got false") }