Skip to content

Commit

Permalink
Merge pull request #12 from marthjod/feature/allow-unset-base-currency
Browse files Browse the repository at this point in the history
allow not setting base currency
  • Loading branch information
mattevans authored Aug 29, 2021
2 parents ef1ff21 + 025018c commit 3ce7fd7
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 26 deletions.
9 changes: 6 additions & 3 deletions cache_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package dinero

import (
"encoding/json"
"os"
"strings"
"testing"
"time"

Expand All @@ -12,14 +12,17 @@ import (
// TestCache will test that our in-memory cache of forex results is working.
func TestCache(t *testing.T) {
// Register the test.
RegisterTestingT(t)
NewWithT(t)

// Init dinero client.
client := NewClient(os.Getenv("OPEN_EXCHANGE_APP_ID"), "AUD", 1*time.Minute)
client := NewClient(appID, "AUD", 1*time.Minute)

// Get latest forex rates.
response1, err := client.Rates.List()
if err != nil {
if strings.HasPrefix(err.Error(), setBaseNotAllowedResponsePrefix) {
t.Skipf("skipping test, unsuitable app ID: %s", err)
}
t.Fatalf("Unexpected error running client.Rates.List(): %s", err.Error())
}

Expand Down
6 changes: 4 additions & 2 deletions dinero.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,12 @@ func NewClient(appID, baseCurrency string, expiry time.Duration) *Client {

// NewRequest creates an authenticated API request. A relative URL can be provided in urlPath,
// which will be resolved to the BackendURL of the Client.
func (c *Client) NewRequest(method, urlPath string, body interface{}) (*http.Request, error) {
func (c *Client) NewRequest(method, urlPath string, params url.Values, body interface{}) (*http.Request, error) {
// make sure rendered URL is correct whether we have other params than app_id or not
params.Set("app_id", c.AppID)
// Parse our URL.
rel, err := url.Parse(
fmt.Sprintf("/api/%s&app_id=%s", urlPath, c.AppID),
fmt.Sprintf("/api/%s?%s", urlPath, params.Encode()),
)
if err != nil {
return nil, err
Expand Down
42 changes: 42 additions & 0 deletions dinero_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package dinero

import (
"net/url"
"testing"
"time"

. "github.com/onsi/gomega"
)

func TestNewRequest(t *testing.T) {
// Register the test.
NewWithT(t)

// Init dinero client.
client := NewClient("12345", "", 1*time.Minute)

var tests = []struct {
params url.Values
expectedURL string
}{
{
params: url.Values{},
expectedURL: "https://openexchangerates.org/api/latest.json?app_id=12345",
},
{
params: url.Values{"base": []string{"AUD"}},
expectedURL: "https://openexchangerates.org/api/latest.json?app_id=12345&base=AUD",
},
}

for _, test := range tests {
req, err := client.NewRequest("GET", "latest.json", test.params, nil)
if err != nil {
t.Fatal(err)
}
actual := req.URL.String()
if actual != test.expectedURL {
t.Errorf("expected %s, got %s", test.expectedURL, actual)
}
}
}
30 changes: 17 additions & 13 deletions rates.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package dinero

import (
"errors"
"fmt"
"net/url"
)

const (
Expand All @@ -26,8 +26,8 @@ func NewRatesService(
baseCurrency string,
) *RatesService {
return &RatesService{
client,
baseCurrency,
client: client,
baseCurrency: baseCurrency,
}
}

Expand All @@ -47,7 +47,7 @@ func (s *RatesService) List() (*RateResponse, error) {
}

// No cached results, go and fetch them.
if err := s.Update(s.baseCurrency); err != nil {
if err := s.Update(); err != nil {
return nil, err
}

Expand All @@ -71,35 +71,39 @@ func (s *RatesService) Get(code string) (*float64, error) {
}

// No cached results, go and fetch them.
if err := s.Update(s.baseCurrency); err != nil {
if err := s.Update(); err != nil {
return nil, err
}

return s.Get(code)
}

// Update will update the rates for the given currency from OXR.
func (s *RatesService) Update(base string) error {
if base == "" {
return errors.New("base currency provided cannot be empty")
}

func (s *RatesService) Update() error {
// Build request.
// add `base` query param if it is not empty
params := url.Values{}
if s.baseCurrency != "" {
params.Set("base", s.baseCurrency)
}
request, err := s.client.NewRequest(
"GET",
fmt.Sprintf("%s?base=%s", latestAPIPath, base),
latestAPIPath,
params,
nil,
)
if err != nil {
return err
}

// Make request
latest := &RateResponse{}
if _, err = s.client.Do(request, latest); err != nil {
var latest *RateResponse
if _, err := s.client.Do(request, &latest); err != nil {
return err
}

s.SetBaseCurrency(latest.Base)

// Store our results.
s.client.Cache.Store(latest)

Expand Down
75 changes: 67 additions & 8 deletions rates_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,47 +3,106 @@ package dinero
import (
"os"
"reflect"
"strings"
"testing"
"time"

. "github.com/onsi/gomega"
)

const (
// Default currency returned by API calls that do not set a base currency.
defaultCurrency = "USD"
// > 403 Changing the API `base` currency is available for Developer, Enterprise and Unlimited plan clients.
setBaseNotAllowedResponsePrefix = "403"
)

var appID = os.Getenv("OPEN_EXCHANGE_APP_ID")

// TestListRatesDefaultCurrency will test updating our local store of forex rates from the OXR API expecting rates for defaultCurrency.
func TestListRatesDefaultCurrency(t *testing.T) {
// Register the test.
NewWithT(t)

// Init dinero client.
client := NewClient(appID, "", 1*time.Minute)

// Get latest forex rates.
response, err := client.Rates.List()
if err != nil {
t.Fatalf("Unexpected error running client.Rates.List(): %s", err)
}

if response.Base != defaultCurrency {
t.Fatalf("Unexpected base oxr rate: Expecting `%s`.", defaultCurrency)
}

if response.Rates == nil {
t.Fatal("Unexpected nil length of rates")
}
}

// TestGetRateDefaultCurrency will test pulling a single rate for defaultCurrency.
func TestGetRateDefaultCurrency(t *testing.T) {
// Register the test.
NewWithT(t)

// Init dinero client.
client := NewClient(appID, "", 1*time.Minute)

// Get latest forex rates for NZD (using defaultCurrency as a base).
response, err := client.Rates.Get("NZD")
if err != nil {
t.Fatalf("Unexpected error running client.Rates.Get('NZD'): %s", err)
}

// Did we get a *float64 back?
if reflect.TypeOf(response).String() != "*float64" {
t.Fatalf("Unexpected rate datatype, expected float64 got %T", response)
}
}

// TestListRates will test updating our local store of forex rates from the OXR API.
func TestListRates(t *testing.T) {
// Register the test.
RegisterTestingT(t)
NewWithT(t)

// Init dinero client.
client := NewClient(os.Getenv("OPEN_EXCHANGE_APP_ID"), "AUD", 1*time.Minute)
client := NewClient(appID, "AUD", 1*time.Minute)

// Get latest forex rates.
response, err := client.Rates.List()
if err != nil {
t.Fatalf("Unexpected error running client.Rates.List(): %s", err.Error())
if strings.HasPrefix(err.Error(), setBaseNotAllowedResponsePrefix) {
t.Skipf("skipping test, unsuitable app ID: %s", err)
}
t.Fatalf("Unexpected error running client.Rates.List(): %s", err)
}

if response.Base != "AUD" {
t.Fatalf("Unexpected base oxr rate: %s. Expecting `AUD`.", err.Error())
t.Fatal("Unexpected base oxr rate. Expecting `AUD`.")
}

if response.Rates == nil {
t.Fatalf("Unexpected length of rates: %s.", err.Error())
t.Fatal("Unexpected length of rates")
}
}

// TestGetRate will test pulling a single rate.
func TestGetRate(t *testing.T) {
// Register the test.
RegisterTestingT(t)
NewWithT(t)

// Init dinero client.
client := NewClient(os.Getenv("OPEN_EXCHANGE_APP_ID"), "AUD", 1*time.Minute)
client := NewClient(appID, "AUD", 1*time.Minute)

// Get latest forex rates for NZD (using AUD as a base).
response, err := client.Rates.Get("NZD")
if err != nil {
t.Fatalf("Unexpected error running client.Rates.Get('NZD'): %s", err.Error())
if strings.HasPrefix(err.Error(), setBaseNotAllowedResponsePrefix) {
t.Skipf("skipping test, unsuitable app ID: %s", err)
}
t.Fatalf("Unexpected error running client.Rates.Get('NZD'): %s", err)
}

// Did we get a *float64 back?
Expand Down

0 comments on commit 3ce7fd7

Please sign in to comment.