Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow not setting base currency #12

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -21,8 +21,8 @@ func NewRatesService(
baseCurrency string,
) *RatesService {
return &RatesService{
client,
baseCurrency,
client: client,
baseCurrency: baseCurrency,
}
}

Expand All @@ -42,7 +42,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 @@ -64,35 +64,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