mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-06 22:15:20 +02:00
* Rename MarketDataSyncer to MarketDataImporter * Materializers * Importers * More reference replacements
143 lines
5.1 KiB
Ruby
143 lines
5.1 KiB
Ruby
require "test_helper"
|
|
require "ostruct"
|
|
|
|
class Security::Price::ImporterTest < ActiveSupport::TestCase
|
|
include ProviderTestHelper
|
|
|
|
setup do
|
|
@provider = mock
|
|
@security = Security.create!(ticker: "AAPL")
|
|
end
|
|
|
|
test "syncs missing prices from provider" do
|
|
Security::Price.delete_all
|
|
|
|
provider_response = provider_success_response([
|
|
OpenStruct.new(security: @security, date: 2.days.ago.to_date, price: 150, currency: "USD"),
|
|
OpenStruct.new(security: @security, date: 1.day.ago.to_date, price: 155, currency: "USD"),
|
|
OpenStruct.new(security: @security, date: Date.current, price: 160, currency: "USD")
|
|
])
|
|
|
|
@provider.expects(:fetch_security_prices)
|
|
.with(symbol: @security.ticker, exchange_operating_mic: @security.exchange_operating_mic,
|
|
start_date: get_provider_fetch_start_date(2.days.ago.to_date), end_date: Date.current)
|
|
.returns(provider_response)
|
|
|
|
Security::Price::Importer.new(
|
|
security: @security,
|
|
security_provider: @provider,
|
|
start_date: 2.days.ago.to_date,
|
|
end_date: Date.current
|
|
).import_provider_prices
|
|
|
|
db_prices = Security::Price.where(security: @security, date: 2.days.ago.to_date..Date.current).order(:date)
|
|
|
|
assert_equal 3, db_prices.count
|
|
assert_equal [ 150, 155, 160 ], db_prices.map(&:price)
|
|
end
|
|
|
|
test "syncs diff when some prices already exist" do
|
|
Security::Price.delete_all
|
|
|
|
# Pre-populate DB with first two days
|
|
Security::Price.create!(security: @security, date: 3.days.ago.to_date, price: 140, currency: "USD")
|
|
Security::Price.create!(security: @security, date: 2.days.ago.to_date, price: 145, currency: "USD")
|
|
|
|
provider_response = provider_success_response([
|
|
OpenStruct.new(security: @security, date: 1.day.ago.to_date, price: 150, currency: "USD")
|
|
])
|
|
|
|
@provider.expects(:fetch_security_prices)
|
|
.with(symbol: @security.ticker, exchange_operating_mic: @security.exchange_operating_mic,
|
|
start_date: get_provider_fetch_start_date(1.day.ago.to_date), end_date: Date.current)
|
|
.returns(provider_response)
|
|
|
|
Security::Price::Importer.new(
|
|
security: @security,
|
|
security_provider: @provider,
|
|
start_date: 3.days.ago.to_date,
|
|
end_date: Date.current
|
|
).import_provider_prices
|
|
|
|
db_prices = Security::Price.where(security: @security).order(:date)
|
|
assert_equal 4, db_prices.count
|
|
assert_equal [ 140, 145, 150, 150 ], db_prices.map(&:price)
|
|
end
|
|
|
|
test "no provider calls when all prices exist" do
|
|
Security::Price.delete_all
|
|
|
|
(3.days.ago.to_date..Date.current).each_with_index do |date, idx|
|
|
Security::Price.create!(security: @security, date:, price: 100 + idx, currency: "USD")
|
|
end
|
|
|
|
@provider.expects(:fetch_security_prices).never
|
|
|
|
Security::Price::Importer.new(
|
|
security: @security,
|
|
security_provider: @provider,
|
|
start_date: 3.days.ago.to_date,
|
|
end_date: Date.current
|
|
).import_provider_prices
|
|
end
|
|
|
|
test "full upsert if clear_cache is true" do
|
|
Security::Price.delete_all
|
|
|
|
# Seed DB with stale prices
|
|
(2.days.ago.to_date..Date.current).each do |date|
|
|
Security::Price.create!(security: @security, date:, price: 100, currency: "USD")
|
|
end
|
|
|
|
provider_response = provider_success_response([
|
|
OpenStruct.new(security: @security, date: 2.days.ago.to_date, price: 150, currency: "USD"),
|
|
OpenStruct.new(security: @security, date: 1.day.ago.to_date, price: 155, currency: "USD"),
|
|
OpenStruct.new(security: @security, date: Date.current, price: 160, currency: "USD")
|
|
])
|
|
|
|
@provider.expects(:fetch_security_prices)
|
|
.with(symbol: @security.ticker, exchange_operating_mic: @security.exchange_operating_mic,
|
|
start_date: get_provider_fetch_start_date(2.days.ago.to_date), end_date: Date.current)
|
|
.returns(provider_response)
|
|
|
|
Security::Price::Importer.new(
|
|
security: @security,
|
|
security_provider: @provider,
|
|
start_date: 2.days.ago.to_date,
|
|
end_date: Date.current,
|
|
clear_cache: true
|
|
).import_provider_prices
|
|
|
|
db_prices = Security::Price.where(security: @security).order(:date)
|
|
assert_equal [ 150, 155, 160 ], db_prices.map(&:price)
|
|
end
|
|
|
|
test "clamps end_date to today when future date is provided" do
|
|
Security::Price.delete_all
|
|
|
|
future_date = Date.current + 3.days
|
|
|
|
provider_response = provider_success_response([
|
|
OpenStruct.new(security: @security, date: Date.current, price: 165, currency: "USD")
|
|
])
|
|
|
|
@provider.expects(:fetch_security_prices)
|
|
.with(symbol: @security.ticker, exchange_operating_mic: @security.exchange_operating_mic,
|
|
start_date: get_provider_fetch_start_date(Date.current), end_date: Date.current)
|
|
.returns(provider_response)
|
|
|
|
Security::Price::Importer.new(
|
|
security: @security,
|
|
security_provider: @provider,
|
|
start_date: Date.current,
|
|
end_date: future_date
|
|
).import_provider_prices
|
|
|
|
assert_equal 1, Security::Price.count
|
|
end
|
|
|
|
private
|
|
def get_provider_fetch_start_date(start_date)
|
|
start_date - 5.days
|
|
end
|
|
end
|