# frozen_string_literal: true
require_relative "../../helper"
require "provider/adapters/nbm"
class Provider < Sequel::Model(:providers)
module Adapters
describe NBM do
before do
VCR.insert_cassette("nbm", match_requests_on: [:method, :uri])
end
after { VCR.eject_cassette }
let(:adapter) { NBM.new }
it "fetches rates for a date range" do
dataset = adapter.fetch(after: Date.new(2026, 4, 6), upto: Date.new(2026, 4, 8))
_(dataset).wont_be_empty
end
it "fetches multiple currencies per date" do
dataset = adapter.fetch(after: Date.new(2026, 4, 6), upto: Date.new(2026, 4, 8))
dates = dataset.map { |r| r[:date] }.uniq
sample = dataset.select { |r| r[:date] == dates.first && r[:base] != "XAU" && r[:base] != "XAG" }
_(sample.size).must_be(:>, 1)
end
it "fetches foreign currency as base and MDL as quote" do
dataset = adapter.fetch(after: Date.new(2026, 4, 6), upto: Date.new(2026, 4, 8))
usd = dataset.find { |r| r[:base] == "USD" && r[:quote] == "MDL" }
_(usd).wont_be_nil
_(usd[:rate]).must_be(:>, 10)
end
it "fetches XAU and XAG against MDL" do
dataset = adapter.fetch(after: Date.new(2026, 4, 6), upto: Date.new(2026, 4, 8))
metals = dataset.select { |r| NBM::METAL_CODES.include?(r[:base]) }
bases = metals.map { |r| r[:base] }.uniq
_(bases).must_include("XAU")
_(bases).must_include("XAG")
metals.each { |r| _(r[:quote]).must_equal("MDL") }
end
it "normalizes metal rates from MDL-per-gram to MDL-per-troy-ounce" do
xml = <<~XML
961
XAG
1
Gram silver
41.5550
959
XAU
1
Gram gold
2619.6183
XML
records = adapter.parse_metals(xml)
xau = records.find { |r| r[:base] == "XAU" }
xag = records.find { |r| r[:base] == "XAG" }
_(records.size).must_equal(2)
_(xau[:rate]).must_be_close_to(2619.6183 * Adapter::GRAMS_PER_TROY_OUNCE, 0.0001)
_(xag[:rate]).must_be_close_to(41.5550 * Adapter::GRAMS_PER_TROY_OUNCE, 0.0001)
_(xau[:quote]).must_equal("MDL")
end
it "skips weekend metal records" do
xml = <<~XML
959
XAU
1
Gram gold
2619.6183
XML
_(adapter.parse_metals(xml)).must_be_empty
end
it "parses XML correctly" do
xml = <<~XML
840
USD
1
US Dollar
17.4597
XML
records = adapter.parse(xml)
_(records.length).must_equal(1)
_(records.first[:base]).must_equal("USD")
_(records.first[:quote]).must_equal("MDL")
_(records.first[:rate]).must_be_close_to(17.4597, 0.0001)
end
it "normalizes rate by nominal" do
xml = <<~XML
392
JPY
100
Japanese Yen
10.9277
XML
records = adapter.parse(xml)
_(records.first[:rate]).must_be_close_to(0.109277, 0.0001)
end
it "skips zero values" do
xml = <<~XML
804
UAK
0
Ukrainian Karbovanets
0.0000
XML
records = adapter.parse(xml)
_(records).must_be_empty
end
it "skips invalid currency codes" do
xml = <<~XML
999
XX
1
Invalid
1.5
XML
records = adapter.parse(xml)
_(records).must_be_empty
end
end
end
end