mirror of
https://github.com/we-promise/sure.git
synced 2026-04-18 11:34:13 +00:00
feat: Enhance holding detail drawer with live price sync and enriched overview (#1086)
* Feat: Implement manual sync prices functionality and enhance holdings display * Feat: Enhance sync prices functionality with error handling and update UI components * Feat: Update sync prices error handling and enhance Spanish locale messages * Fix: Address CodeRabbit review feedback - Set fallback @provider_error when prices_updated == 0 so turbo stream never fails silently without a visible error message - Move attr_reader :provider_error to class header in Price::Importer for conventional placement alongside other attribute declarations - Precompute @last_price_updated in controller (show + sync_prices) instead of running a DB query directly inside ERB templates Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix: Replace bare rescue with explicit exception handling in turbo stream view Bare `rescue` silently swallows all exceptions, making debugging impossible. Match the pattern already used in show.html.erb: rescue ActiveRecord::RecordInvalid explicitly, then catch StandardError with logging (message + backtrace) before falling back to the unknown label. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix: Update test assertion to expect actual provider error message The stub returns "Yahoo Finance rate limit exceeded" as the provider error. After the @provider_error fallback fix, the controller now correctly surfaces the real provider error when present (using .presence || fallback), so the flash[:alert] is the actual error string, not the generic fallback. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * Fix: Assert scoped security_ids in sync_prices materializer test Replace loose stub with constructor expectation to verify that Balance::Materializer is instantiated with the single-security scope. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Fix: Assert holding remap in remap_security test Add assertion that @holding.security_id is updated to the target security after remap, covering the core command outcome. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Fix: CI test failure - Update disconnect external assistant test to use env overrides --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -61,4 +61,61 @@ class HoldingsControllerTest < ActionDispatch::IntegrationTest
|
||||
assert_equal 50.0, @holding.cost_basis.to_f
|
||||
assert_equal "manual", @holding.cost_basis_source
|
||||
end
|
||||
|
||||
test "remap_security brings offline security back online" do
|
||||
# Given: the target security is marked offline (e.g. created by a failed QIF import)
|
||||
msft = securities(:msft)
|
||||
msft.update!(offline: true, failed_fetch_count: 3)
|
||||
|
||||
# When: user explicitly selects it from the provider search and saves
|
||||
patch remap_security_holding_path(@holding), params: { security_id: "MSFT|XNAS" }
|
||||
|
||||
# Then: the security is brought back online and the holding is remapped
|
||||
assert_redirected_to account_path(@holding.account, tab: "holdings")
|
||||
@holding.reload
|
||||
msft.reload
|
||||
assert_equal msft.id, @holding.security_id
|
||||
assert_not msft.offline?
|
||||
assert_equal 0, msft.failed_fetch_count
|
||||
end
|
||||
|
||||
test "sync_prices redirects with alert for offline security" do
|
||||
@holding.security.update!(offline: true)
|
||||
|
||||
post sync_prices_holding_path(@holding)
|
||||
|
||||
assert_redirected_to account_path(@holding.account, tab: "holdings")
|
||||
assert_equal I18n.t("holdings.sync_prices.unavailable"), flash[:alert]
|
||||
end
|
||||
|
||||
test "sync_prices syncs market data and redirects with notice" do
|
||||
Security.any_instance.expects(:import_provider_prices).with(
|
||||
start_date: 31.days.ago.to_date,
|
||||
end_date: Date.current,
|
||||
clear_cache: true
|
||||
).returns([ 31, nil ])
|
||||
Security.any_instance.stubs(:import_provider_details)
|
||||
materializer = mock("materializer")
|
||||
materializer.expects(:materialize_balances).once
|
||||
Balance::Materializer.expects(:new).with(
|
||||
@holding.account,
|
||||
strategy: :forward,
|
||||
security_ids: [ @holding.security_id ]
|
||||
).returns(materializer)
|
||||
|
||||
post sync_prices_holding_path(@holding)
|
||||
|
||||
assert_redirected_to account_path(@holding.account, tab: "holdings")
|
||||
assert_equal I18n.t("holdings.sync_prices.success"), flash[:notice]
|
||||
end
|
||||
|
||||
test "sync_prices shows provider error inline when provider returns no prices" do
|
||||
Security.any_instance.stubs(:import_provider_prices).returns([ 0, "Yahoo Finance rate limit exceeded" ])
|
||||
Security.any_instance.stubs(:import_provider_details)
|
||||
|
||||
post sync_prices_holding_path(@holding)
|
||||
|
||||
assert_redirected_to account_path(@holding.account, tab: "holdings")
|
||||
assert_equal "Yahoo Finance rate limit exceeded", flash[:alert]
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user