From 633dbc5b74489ab32d1d8226d5d5fa250b8a61fa Mon Sep 17 00:00:00 2001 From: Ani Channarasappa Date: Fri, 31 May 2024 20:46:30 -0400 Subject: [PATCH] test: improved test coverage and fixed tests that were executing network requests --- internal/cli/cli.go | 19 ++++++++++---- internal/cli/cli_test.go | 51 ++++++++++++++++++++++++++++++------ internal/common/common.go | 5 ++-- internal/quote/quote.go | 4 +-- internal/quote/quote_test.go | 2 +- test/http/http.go | 33 +++++++++++++++++++++-- 6 files changed, 94 insertions(+), 20 deletions(-) diff --git a/internal/cli/cli.go b/internal/cli/cli.go index efddf2d..2d9b6e1 100644 --- a/internal/cli/cli.go +++ b/internal/cli/cli.go @@ -70,8 +70,9 @@ func GetDependencies() c.Dependencies { return c.Dependencies{ Fs: afero.NewOsFs(), HttpClients: c.DependenciesHttpClients{ - Default: resty.New(), - Yahoo: yahooClient.New(resty.New(), resty.New()), + Default: resty.New(), + Yahoo: yahooClient.New(resty.New(), resty.New()), + YahooSession: resty.New(), }, } @@ -85,7 +86,7 @@ func GetContext(d c.Dependencies, config c.Config) (c.Context, error) { err error ) - err = yahooClient.RefreshSession(d.HttpClients.Yahoo, resty.New()) + err = yahooClient.RefreshSession(d.HttpClients.Yahoo, d.HttpClients.YahooSession) if err != nil { return c.Context{}, err @@ -97,7 +98,11 @@ func GetContext(d c.Dependencies, config c.Config) (c.Context, error) { return c.Context{}, err } - reference, err = getReference(config, groups, *d.HttpClients.Yahoo) + reference, err = getReference(config, groups, d.HttpClients.Yahoo) + + if err != nil { + return c.Context{}, err + } context := c.Context{ Reference: reference, @@ -131,11 +136,15 @@ func readConfig(fs afero.Fs, configPathOption string) (c.Config, error) { return config, nil } -func getReference(config c.Config, assetGroups []c.AssetGroup, client resty.Client) (c.Reference, error) { +func getReference(config c.Config, assetGroups []c.AssetGroup, client *resty.Client) (c.Reference, error) { currencyRates, err := quote.GetAssetGroupsCurrencyRates(client, assetGroups, config.Currency) styles := util.GetColorScheme(config.ColorScheme) + if err != nil { + return c.Reference{}, err + } + return c.Reference{ CurrencyRates: currencyRates, Styles: styles, diff --git a/internal/cli/cli_test.go b/internal/cli/cli_test.go index 8180c2a..981c9c4 100644 --- a/internal/cli/cli_test.go +++ b/internal/cli/cli_test.go @@ -19,7 +19,7 @@ import ( "github.com/achannarasappa/ticker/internal/cli" . "github.com/achannarasappa/ticker/internal/cli" c "github.com/achannarasappa/ticker/internal/common" - "github.com/achannarasappa/ticker/test/http" + httpMocks "github.com/achannarasappa/ticker/test/http" ) func getStdout(fn func()) string { @@ -67,13 +67,16 @@ var _ = Describe("Cli", func() { dep = c.Dependencies{ Fs: afero.NewMemMapFs(), HttpClients: c.DependenciesHttpClients{ - Default: client, - Yahoo: client, + Default: client, + Yahoo: client, + YahooSession: client, }, } - http.MockTickerSymbols() - http.MockResponseCurrency() + httpMocks.MockTickerSymbols() + httpMocks.MockResponseCurrency() + httpMocks.MockResponseForRefreshSessionSuccess() + //nolint:errcheck dep.Fs.MkdirAll("./", 0755) }) @@ -293,7 +296,7 @@ var _ = Describe("Cli", func() { It("returns the error", func() { - http.MockTickerSymbolsError() + httpMocks.MockTickerSymbolsError() _, outputErr := GetContext(dep, c.Config{}) @@ -305,9 +308,25 @@ var _ = Describe("Cli", func() { When("there is an error getting reference data", func() { - PIt("returns the error", func() { + It("returns the error", func() { + + httpMocks.MockResponseCurrencyError() + + _, outputErr := GetContext(dep, c.Config{ + Watchlist: []string{"TSLA"}, + }) + + Expect(outputErr).ToNot(BeNil()) + + }) - http.MockResponseCurrencyError() + }) + + When("there is an error refreshing the yahoo session", func() { + + It("returns the error", func() { + + httpMocks.MockResponseForRefreshSessionError() _, outputErr := GetContext(dep, c.Config{}) @@ -543,6 +562,22 @@ var _ = Describe("Cli", func() { }) }) + Describe("GetDependencies", func() { + + It("should dependencies", func() { + + output := GetDependencies() + expected := g.MatchAllFields(g.Fields{ + "Fs": BeAssignableToTypeOf(afero.NewOsFs()), + "HttpClients": BeAssignableToTypeOf(c.DependenciesHttpClients{}), + }) + + Expect(output).To(expected) + + }) + + }) + Describe("Validate", func() { var ( diff --git a/internal/common/common.go b/internal/common/common.go index 55dbb66..f2e41c6 100644 --- a/internal/common/common.go +++ b/internal/common/common.go @@ -75,8 +75,9 @@ type Dependencies struct { } type DependenciesHttpClients struct { //nolint:golint,stylecheck,revive - Default *resty.Client - Yahoo *resty.Client + Default *resty.Client + Yahoo *resty.Client + YahooSession *resty.Client } // Lot represents a cost basis lot diff --git a/internal/quote/quote.go b/internal/quote/quote.go index 5919c72..9678509 100644 --- a/internal/quote/quote.go +++ b/internal/quote/quote.go @@ -80,7 +80,7 @@ func getUniqueSymbolsBySource(assetGroups []c.AssetGroup) []c.AssetGroupSymbolsB } // GetAssetGroupsCurrencyRates gets the currency rates by source across all asset groups -func GetAssetGroupsCurrencyRates(client resty.Client, assetGroups []c.AssetGroup, targetCurrency string) (c.CurrencyRates, error) { +func GetAssetGroupsCurrencyRates(client *resty.Client, assetGroups []c.AssetGroup, targetCurrency string) (c.CurrencyRates, error) { var err error var currencyRates c.CurrencyRates @@ -89,7 +89,7 @@ func GetAssetGroupsCurrencyRates(client resty.Client, assetGroups []c.AssetGroup for _, source := range uniqueSymbolsBySource { if source.Source == c.QuoteSourceYahoo && err == nil { - currencyRates, err = quoteYahoo.GetCurrencyRates(client, source.Symbols, targetCurrency) + currencyRates, err = quoteYahoo.GetCurrencyRates(*client, source.Symbols, targetCurrency) } } diff --git a/internal/quote/quote_test.go b/internal/quote/quote_test.go index 498f0e6..2d3b75e 100644 --- a/internal/quote/quote_test.go +++ b/internal/quote/quote_test.go @@ -136,7 +136,7 @@ var _ = Describe("Quote", func() { }, }, } - output, _ := GetAssetGroupsCurrencyRates(*client, input, "EUR") + output, _ := GetAssetGroupsCurrencyRates(client, input, "EUR") Expect(output).To(g.MatchAllKeys(g.Keys{ "USD": g.MatchFields(g.IgnoreExtras, g.Fields{ "FromCurrency": Equal("USD"), diff --git a/test/http/http.go b/test/http/http.go index 6889615..824ddae 100644 --- a/test/http/http.go +++ b/test/http/http.go @@ -72,7 +72,8 @@ func MockResponseCurrency() { func MockResponseCurrencyError() { responseUrl := `=~.*\/finance\/quote.*` //nolint:golint,stylecheck,revive httpmock.RegisterResponder("GET", responseUrl, func(_ *http.Request) (*http.Response, error) { - return &http.Response{}, errors.New("error getting currencies") //nolint:goerr113 + + return httpmock.NewStringResponse(http.StatusInternalServerError, "server error"), errors.New("error getting currencies") //nolint:goerr113 }) } @@ -155,6 +156,34 @@ func MockTickerSymbols() { func MockTickerSymbolsError() { responseUrl := "https://raw.githubusercontent.com/achannarasappa/ticker-static/master/symbols.csv" //nolint:golint,stylecheck,revive httpmock.RegisterResponder("GET", responseUrl, func(_ *http.Request) (*http.Response, error) { - return &http.Response{}, errors.New("error getting ticker symbols") //nolint:goerr113 + + return httpmock.NewStringResponse(http.StatusInternalServerError, "server error"), errors.New("error getting ticker symbols") //nolint:goerr113 + }) +} + +// Mocks for Yahoo session refresh +func MockResponseForRefreshSessionSuccess() { + httpmock.RegisterResponder("GET", "https://finance.yahoo.com/", func(request *http.Request) (*http.Response, error) { + response := httpmock.NewStringResponse(http.StatusOK, "") + response.Header.Set("Set-Cookie", "A3=d=AQABBPMJfWQCWPnJSAFIwq1PtsjJQ_yNsJ8FEgEBAQFbfmSGZNxN0iMA_eMAAA&S=AQAAAk_fgKYu72Cro5IHlbBd6yg; Expires=Tue, 4 Jun 2024 04:02:28 GMT; Max-Age=31557600; Domain=.yahoo.com; Path=/; SameSite=None; Secure; HttpOnly") + + return response, nil + }) + + httpmock.RegisterResponder("GET", "https://query2.finance.yahoo.com/v1/test/getcrumb", func(request *http.Request) (*http.Response, error) { + return httpmock.NewStringResponse(http.StatusOK, "MrBKM4QQ"), nil + }) +} + +func MockResponseForRefreshSessionError() { + httpmock.RegisterResponder("GET", "https://finance.yahoo.com/", func(request *http.Request) (*http.Response, error) { + response := httpmock.NewStringResponse(http.StatusOK, "") + response.Header.Set("Set-Cookie", "A3=d=AQABBPMJfWQCWPnJSAFIwq1PtsjJQ_yNsJ8FEgEBAQFbfmSGZNxN0iMA_eMAAA&S=AQAAAk_fgKYu72Cro5IHlbBd6yg; Expires=Tue, 4 Jun 2024 04:02:28 GMT; Max-Age=31557600; Domain=.yahoo.com; Path=/; SameSite=None; Secure; HttpOnly") + + return response, nil + }) + + httpmock.RegisterResponder("GET", "https://query2.finance.yahoo.com/v1/test/getcrumb", func(request *http.Request) (*http.Response, error) { + return httpmock.NewStringResponse(http.StatusBadRequest, "tests"), nil }) }