1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-08-04 21:15:19 +02:00

Implement Synth as an exchange rate provider (#574)

* Implement Synth as an exchange rate provider

* Add assertions to provider interface test

* Assert the correct provider error is raised

* Remove unnecessary parens
This commit is contained in:
Jose Farias 2024-03-27 09:16:00 -06:00 committed by GitHub
parent a1b25f1c5b
commit 7ae25dd6df
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 310 additions and 34 deletions

View file

@ -0,0 +1,27 @@
require "test_helper"
module ExchangeRateProviderInterfaceTest
extend ActiveSupport::Testing::Declarative
test "exchange rate provider interface" do
assert_respond_to @subject, :fetch_exchange_rate
end
test "exchange rate provider response contract" do
accounting_for_http_calls do
response = @subject.fetch_exchange_rate from: "USD", to: "MXN", date: Date.current
assert_respond_to response, :rate
assert_respond_to response, :success?
assert_respond_to response, :error
assert_respond_to response, :raw_response
end
end
private
def accounting_for_http_calls
VCR.use_cassette "synth_exchange_rate" do
yield
end
end
end

View file

@ -1,7 +1,42 @@
require "test_helper"
class ExchangeRateTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
test "find rate in db" do
assert_equal exchange_rates(:day_29_ago_eur_to_usd),
ExchangeRate.find_rate_or_fetch(from: "EUR", to: "USD", date: 29.days.ago.to_date)
end
test "fetch rate from provider when it's not found in db" do
ExchangeRate
.expects(:fetch_rate_from_provider)
.returns(ExchangeRate.new(base_currency: "USD", converted_currency: "MXN", rate: 1.0, date: Date.current))
ExchangeRate.find_rate_or_fetch from: "USD", to: "MXN", date: Date.current
end
test "provided rates are saved to the db" do
VCR.use_cassette "synth_exchange_rate" do
assert_difference "ExchangeRate.count", 1 do
ExchangeRate.find_rate_or_fetch from: "USD", to: "MXN", date: Date.current
end
end
end
test "retrying, then raising on provider error" do
Faraday.expects(:get).returns(OpenStruct.new(success?: false)).times(3)
error = assert_raises Provider::Base::ProviderError do
ExchangeRate.find_rate_or_fetch from: "USD", to: "MXN", date: Date.current
end
assert_match "Failed to fetch exchange rate from Provider::Synth", error.message
end
test "retrying, then raising on network error" do
Faraday.expects(:get).raises(Faraday::TimeoutError).times(3)
assert_raises Faraday::TimeoutError do
ExchangeRate.find_rate_or_fetch from: "USD", to: "MXN", date: Date.current
end
end
end

View file

@ -0,0 +1,9 @@
require "test_helper"
class Provider::SynthTest < ActiveSupport::TestCase
include ExchangeRateProviderInterfaceTest
setup do
@subject = Provider::Synth.new
end
end

View file

@ -1,6 +1,17 @@
ENV["RAILS_ENV"] ||= "test"
require_relative "../config/environment"
require "rails/test_help"
require "minitest/mock"
require "minitest/autorun"
require "mocha/minitest"
VCR.configure do |config|
config.cassette_library_dir = "test/vcr_cassettes"
config.hook_into :webmock
config.ignore_localhost = true
config.default_cassette_options = { erb: true }
config.filter_sensitive_data("<SYNTH_API_KEY>") { ENV["SYNTH_API_KEY"] }
end
module ActiveSupport
class TestCase
@ -16,3 +27,5 @@ module ActiveSupport
end
end
end
Dir[Rails.root.join("test", "interfaces", "**", "*.rb")].each { |f| require f }

View file

@ -0,0 +1,69 @@
---
http_interactions:
- request:
method: get
uri: https://api.synthfinance.com/rates/historical?date=<%= Date.current.to_s %>&from=USD&to=MXN
body:
encoding: US-ASCII
string: ''
headers:
User-Agent:
- Faraday v2.9.0
Authorization:
- Bearer <SYNTH_API_KEY>
Accept-Encoding:
- gzip;q=1.0,deflate;q=0.6,identity;q=0.3
Accept:
- "*/*"
response:
status:
code: 200
message: OK
headers:
Date:
- Wed, 27 Mar 2024 02:54:11 GMT
Content-Type:
- application/json; charset=utf-8
Content-Length:
- '138'
Connection:
- keep-alive
Cf-Ray:
- 86ac182ad9ec7ce5-LAX
Cf-Cache-Status:
- DYNAMIC
Cache-Control:
- max-age=0, private, must-revalidate
Etag:
- W/"46780d3f34043bb3bc799b1efae62418"
Strict-Transport-Security:
- max-age=63072000; includeSubDomains
Vary:
- Accept-Encoding
Referrer-Policy:
- strict-origin-when-cross-origin
Rndr-Id:
- 3ca97b82-f963-43a3
X-Content-Type-Options:
- nosniff
X-Frame-Options:
- SAMEORIGIN
X-Permitted-Cross-Domain-Policies:
- none
X-Render-Origin-Server:
- Render
X-Request-Id:
- 64731a8c-4cad-4e42-81c9-60b0d3634a0f
X-Runtime:
- '0.021432'
X-Xss-Protection:
- '0'
Server:
- cloudflare
Alt-Svc:
- h3=":443"; ma=86400
body:
encoding: ASCII-8BIT
string: '{"data":{"date":"<%= Date.current.to_s %>","source":"USD","rates":{"MXN":16.64663}},"meta":{"total_records":1,"credits_used":1,"credits_remaining":976}}'
recorded_at: Wed, 27 Mar 2024 02:54:11 GMT
recorded_with: VCR 6.2.0