1# frozen_string_literal: true
2
3require "test_helper"
4require "bull_bitcoin"
5
6class BullBitcoinTest < Minitest::Test
7 def setup
8 @subject = BullBitcoin.new
9 end
10
11 def stub_bull_btc_cad(user_price: 12_345, precision: 2)
12 stub_request(:post, "https://www.bullbitcoin.com/api/price").with { |req|
13 body = JSON.parse(req.body)
14 expected = {
15 "jsonrpc" => "2.0",
16 "method" => "getUserRate",
17 "params" => {
18 "element" => {
19 "fromCurrency" => "BTC",
20 "toCurrency" => "CAD"
21 }
22 }
23 }
24 req.headers["Content-Type"] == "application/json" &&
25 body["id"] =~ /^\d{13}-\d{3}$/ &&
26 body.slice("jsonrpc", "method", "params") == expected
27 }.to_return(
28 status: 200,
29 body: {
30 jsonrpc: "2.0",
31 result: {
32 element: {
33 userPrice: user_price,
34 precision: precision
35 }
36 }
37 }.to_json
38 )
39 end
40
41 def test_fetch_btc_cad
42 stub_bull_btc_cad
43 assert_equal BigDecimal("123.45"), @subject.fetch_btc_cad.sync
44 end
45 em :test_fetch_btc_cad
46
47 def test_fetch_btc_cad_raises_on_http_error
48 stub_request(:post, "https://www.bullbitcoin.com/api/price").to_return(
49 status: 500,
50 body: "Internal Server Error"
51 )
52
53 error = assert_raises(BullBitcoin::Error) { @subject.fetch_btc_cad.sync }
54 assert_equal(
55 "Bull Bitcoin price request failed with HTTP 500",
56 error.message
57 )
58 end
59 em :test_fetch_btc_cad_raises_on_http_error
60
61 def test_fetch_btc_cad_raises_on_missing_element
62 stub_request(:post, "https://www.bullbitcoin.com/api/price").to_return(
63 status: 200,
64 body: { jsonrpc: "2.0", result: {} }.to_json
65 )
66
67 error = assert_raises(BullBitcoin::Error) { @subject.fetch_btc_cad.sync }
68 assert_equal(
69 "Bull Bitcoin price response missing result.element",
70 error.message
71 )
72 end
73 em :test_fetch_btc_cad_raises_on_missing_element
74
75 def test_fetch_btc_cad_raises_on_validation_error_with_nested_data
76 stub_request(:post, "https://www.bullbitcoin.com/api/price").to_return(
77 status: 200,
78 body: {
79 jsonrpc: "2.0",
80 error: {
81 code: -32602,
82 message: "Validation error",
83 data: {
84 apiError: {
85 code: "ERR_API_400",
86 message: "Invalid request parameters"
87 }
88 }
89 }
90 }.to_json
91 )
92
93 error = assert_raises(BullBitcoin::Error) { @subject.fetch_btc_cad.sync }
94 expected = "Bull Bitcoin price response error: " \
95 "Validation error: Invalid request parameters"
96 assert_equal(expected, error.message)
97 end
98 em :test_fetch_btc_cad_raises_on_validation_error_with_nested_data
99
100 def test_fetch_btc_cad_raises_on_validation_error_with_string_data
101 stub_request(:post, "https://www.bullbitcoin.com/api/price").to_return(
102 status: 200,
103 body: {
104 jsonrpc: "2.0",
105 error: {
106 code: -32602,
107 message: "Validation error",
108 data: "4667aad3bf0ef71f:3017b8b112de44f2"
109 }
110 }.to_json
111 )
112
113 error = assert_raises(BullBitcoin::Error) { @subject.fetch_btc_cad.sync }
114 assert_equal(
115 "Bull Bitcoin price response error: Validation error",
116 error.message
117 )
118 end
119 em :test_fetch_btc_cad_raises_on_validation_error_with_string_data
120
121 def test_fetch_btc_cad_raises_on_standard_json_rpc_error
122 stub_request(:post, "https://www.bullbitcoin.com/api/price").to_return(
123 status: 200,
124 body: {
125 jsonrpc: "2.0",
126 error: {
127 code: -32603,
128 message: "No Validation schema found for [notARealMethod]",
129 data: "4667aad3bf0ef71f:3017b8b112de44f2:6e6c5c73209cfe6a:0"
130 }
131 }.to_json
132 )
133
134 error = assert_raises(BullBitcoin::Error) { @subject.fetch_btc_cad.sync }
135 expected = "Bull Bitcoin price response error: " \
136 "No Validation schema found for [notARealMethod]"
137 assert_equal(expected, error.message)
138 end
139 em :test_fetch_btc_cad_raises_on_standard_json_rpc_error
140end