mirror of
https://github.com/we-promise/sure.git
synced 2026-04-09 15:24:48 +00:00
* [FEATURE] Add CoinStats exchange portfolios and normalize linked investment charts * [BUGFIX] Fix CoinStats PR regressions * [BUGFIX] Fix CoinStats PR review findings * [BUGFIX] Address follow-up CoinStats PR feedback * [REFACTO] Extract CoinStats exchange account helpers * [BUGFIX] Batch linked CoinStats chart normalization * [BUGFIX] Fix CoinStats processor lint --------- Signed-off-by: Juan José Mata <juanjo.mata@gmail.com> Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
216 lines
6.3 KiB
Ruby
216 lines
6.3 KiB
Ruby
require "test_helper"
|
|
|
|
class CoinstatsItemsControllerTest < ActionDispatch::IntegrationTest
|
|
setup do
|
|
sign_in users(:family_admin)
|
|
@family = families(:dylan_family)
|
|
@coinstats_item = CoinstatsItem.create!(
|
|
family: @family,
|
|
name: "Test CoinStats Connection",
|
|
api_key: "test_api_key_123"
|
|
)
|
|
tailwind_build = Rails.root.join("app/assets/builds/tailwind.css")
|
|
FileUtils.mkdir_p(tailwind_build.dirname)
|
|
File.write(tailwind_build, "/* test */") unless tailwind_build.exist?
|
|
end
|
|
|
|
# Helper to wrap data in Provider::Response
|
|
def success_response(data)
|
|
Provider::Response.new(success?: true, data: data, error: nil)
|
|
end
|
|
|
|
def error_response(message)
|
|
Provider::Response.new(success?: false, data: nil, error: Provider::Error.new(message))
|
|
end
|
|
|
|
test "should get new" do
|
|
get new_coinstats_item_url
|
|
assert_response :success
|
|
end
|
|
|
|
test "should create coinstats item with valid api key" do
|
|
# Mock the API key validation
|
|
Provider::Coinstats.any_instance.expects(:get_blockchains).returns(success_response([])).once
|
|
|
|
assert_difference("CoinstatsItem.count", 1) do
|
|
post coinstats_items_url, params: {
|
|
coinstats_item: {
|
|
name: "New CoinStats Connection",
|
|
api_key: "valid_api_key"
|
|
}
|
|
}
|
|
end
|
|
end
|
|
|
|
test "should not create coinstats item with invalid api key" do
|
|
# Mock the API key validation to fail
|
|
Provider::Coinstats.any_instance.expects(:get_blockchains)
|
|
.returns(error_response("Invalid API key"))
|
|
|
|
assert_no_difference("CoinstatsItem.count") do
|
|
post coinstats_items_url, params: {
|
|
coinstats_item: {
|
|
name: "New CoinStats Connection",
|
|
api_key: "invalid_api_key"
|
|
}
|
|
}
|
|
end
|
|
end
|
|
|
|
test "should destroy coinstats item" do
|
|
# Schedules for deletion, doesn't actually delete immediately
|
|
assert_no_difference("CoinstatsItem.count") do
|
|
delete coinstats_item_url(@coinstats_item)
|
|
end
|
|
|
|
assert_redirected_to settings_providers_path
|
|
@coinstats_item.reload
|
|
assert @coinstats_item.scheduled_for_deletion?
|
|
end
|
|
|
|
test "should sync coinstats item" do
|
|
post sync_coinstats_item_url(@coinstats_item)
|
|
assert_redirected_to accounts_path
|
|
end
|
|
|
|
test "sync responds to json format" do
|
|
post sync_coinstats_item_url(@coinstats_item, format: :json)
|
|
assert_response :ok
|
|
end
|
|
|
|
test "should update coinstats item with valid api key" do
|
|
Provider::Coinstats.any_instance.expects(:get_blockchains).returns(success_response([])).once
|
|
|
|
patch coinstats_item_url(@coinstats_item), params: {
|
|
coinstats_item: {
|
|
name: "Updated Name",
|
|
api_key: "new_valid_api_key"
|
|
}
|
|
}
|
|
|
|
@coinstats_item.reload
|
|
assert_equal "Updated Name", @coinstats_item.name
|
|
end
|
|
|
|
test "should not update coinstats item with invalid api key" do
|
|
Provider::Coinstats.any_instance.expects(:get_blockchains)
|
|
.returns(error_response("Invalid API key"))
|
|
|
|
original_name = @coinstats_item.name
|
|
|
|
patch coinstats_item_url(@coinstats_item), params: {
|
|
coinstats_item: {
|
|
name: "Updated Name",
|
|
api_key: "invalid_api_key"
|
|
}
|
|
}
|
|
|
|
@coinstats_item.reload
|
|
assert_equal original_name, @coinstats_item.name
|
|
end
|
|
|
|
test "link_wallet requires all parameters" do
|
|
post link_wallet_coinstats_items_url, params: {
|
|
coinstats_item_id: @coinstats_item.id,
|
|
address: "0x123"
|
|
# missing blockchain
|
|
}
|
|
|
|
assert_response :unprocessable_entity
|
|
end
|
|
|
|
test "link_wallet with valid params creates accounts" do
|
|
balance_data = [
|
|
{ coinId: "ethereum", name: "Ethereum", symbol: "ETH", amount: 1.5, price: 2000 }
|
|
]
|
|
|
|
bulk_response = [
|
|
{ blockchain: "ethereum", address: "0x123abc", connectionId: "ethereum", balances: balance_data }
|
|
]
|
|
|
|
Provider::Coinstats.any_instance.expects(:get_wallet_balances)
|
|
.with("ethereum:0x123abc")
|
|
.returns(success_response(bulk_response))
|
|
|
|
Provider::Coinstats.any_instance.expects(:extract_wallet_balance)
|
|
.with(bulk_response, "0x123abc", "ethereum")
|
|
.returns(balance_data)
|
|
|
|
assert_difference("Account.count", 1) do
|
|
assert_difference("CoinstatsAccount.count", 1) do
|
|
post link_wallet_coinstats_items_url, params: {
|
|
coinstats_item_id: @coinstats_item.id,
|
|
address: "0x123abc",
|
|
blockchain: "ethereum"
|
|
}
|
|
end
|
|
end
|
|
|
|
assert_redirected_to accounts_path
|
|
end
|
|
|
|
test "link_wallet handles provider errors" do
|
|
Provider::Coinstats.any_instance.expects(:get_wallet_balances)
|
|
.raises(Provider::Coinstats::Error.new("Invalid API key"))
|
|
|
|
post link_wallet_coinstats_items_url, params: {
|
|
coinstats_item_id: @coinstats_item.id,
|
|
address: "0x123abc",
|
|
blockchain: "ethereum"
|
|
}
|
|
|
|
assert_response :unprocessable_entity
|
|
end
|
|
|
|
test "link_wallet handles no tokens found" do
|
|
Provider::Coinstats.any_instance.expects(:get_wallet_balances)
|
|
.returns(success_response([]))
|
|
|
|
Provider::Coinstats.any_instance.expects(:extract_wallet_balance)
|
|
.returns([])
|
|
|
|
post link_wallet_coinstats_items_url, params: {
|
|
coinstats_item_id: @coinstats_item.id,
|
|
address: "0x123abc",
|
|
blockchain: "ethereum"
|
|
}
|
|
|
|
assert_response :unprocessable_entity
|
|
assert_match(/No tokens found/, response.body)
|
|
end
|
|
|
|
test "link_exchange filters unexpected connection fields" do
|
|
Provider::Coinstats.any_instance.expects(:get_exchanges).returns(success_response([
|
|
{
|
|
connectionId: "bitvavo",
|
|
name: "Bitvavo",
|
|
connectionFields: [
|
|
{ key: "apiKey", name: "API Key" },
|
|
{ key: "apiSecret", name: "API Secret" }
|
|
]
|
|
}
|
|
])).once
|
|
|
|
linker_result = CoinstatsItem::ExchangeLinker::Result.new(success?: true, created_count: 0, errors: [])
|
|
CoinstatsItem::ExchangeLinker.expects(:new).with(
|
|
@coinstats_item,
|
|
connection_id: "bitvavo",
|
|
connection_fields: { "apiKey" => "key", "apiSecret" => "secret" },
|
|
name: "Bitvavo"
|
|
).returns(stub(link: linker_result))
|
|
|
|
post link_exchange_coinstats_items_url, params: {
|
|
coinstats_item_id: @coinstats_item.id,
|
|
exchange_connection_id: "bitvavo",
|
|
exchange_connection_name: "Bitvavo",
|
|
connection_fields: {
|
|
apiKey: " key ",
|
|
apiSecret: " secret ",
|
|
unexpected: "should_not_be_forwarded"
|
|
}
|
|
}
|
|
|
|
assert_redirected_to accounts_path
|
|
end
|
|
end
|