mirror of
https://github.com/we-promise/sure.git
synced 2026-09-08 16:14:23 +00:00
* fix(hosting): consistent provider-block visibility + fix Twelve Data toggle bug (#3089) T-Invest was the only provider block always rendered regardless of its checkbox state; now it follows the same pattern as every other provider (shown when tinkoff_invest or moex_public is enabled, since T-Invest also serves as a brand-logo fallback for MOEX-priced securities). Also fixes a related functional bug: unchecking every securities provider tried to clear the legacy securities_provider setting by assigning nil, but rails-settings-cached treats nil as "delete override", which silently reverted the field to its own default ("twelve_data") — re-enabling Twelve Data right after the user disabled it. Assigning "" instead persists the cleared state. Twelve Data and Yahoo Finance settings blocks can still be shown purely because they're the selected FX/exchange-rate provider even when unchecked for securities pricing; added an info notice explaining that instead of leaving it unexplained. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * fix(hosting): address review feedback on #3333 - Drop the FX-only notice for Twelve Data/Yahoo Finance per feedback — the block staying visible while unchecked (because it's still the FX provider) doesn't need extra UI explanation. - Fix Codex finding: T-Invest settings must stay visible/manageable whenever a token is already configured, not just when tinkoff_invest or moex_public is checked. Security::Provided#import_brand_logo calls the T-Invest provider unconditionally for every non-crypto security once a token exists, regardless of price provider — hiding the field in that case would leave an active credential impossible to see, rotate, or clear through the UI. Reworded the notice to reflect the real, provider-independent reason instead of the narrower "MOEX only" framing. - Fix CodeRabbit finding: setting_test.rb's default-fallback test now isolates against SECURITIES_PROVIDER(S) env vars, and the explicit-clear test captures and restores the pre-test values instead of hardcoding a restore target. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> * No overexplaining in code --------- Co-authored-by: Gerald <248542187+gfr-free@users.noreply.github.com> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> Co-authored-by: Juan José Mata <jjmata@jjmata.com>
160 lines
5.2 KiB
Ruby
160 lines
5.2 KiB
Ruby
require "test_helper"
|
|
|
|
class SettingTest < ActiveSupport::TestCase
|
|
setup do
|
|
# Clear settings before each test
|
|
Setting.openai_uri_base = nil
|
|
Setting.openai_model = nil
|
|
end
|
|
|
|
teardown do
|
|
# Clean up dynamic fields after each test
|
|
Setting.where("var LIKE ?", "dynamic:%").destroy_all
|
|
end
|
|
|
|
test "validate_openai_config! passes when both uri base and model are set" do
|
|
assert_nothing_raised do
|
|
Setting.validate_openai_config!(uri_base: "https://api.example.com", model: "gpt-4")
|
|
end
|
|
end
|
|
|
|
test "validate_openai_config! passes when neither uri base nor model are set" do
|
|
assert_nothing_raised do
|
|
Setting.validate_openai_config!(uri_base: "", model: "")
|
|
end
|
|
end
|
|
|
|
test "validate_openai_config! passes when uri base is blank and model is set" do
|
|
assert_nothing_raised do
|
|
Setting.validate_openai_config!(uri_base: "", model: "gpt-4")
|
|
end
|
|
end
|
|
|
|
test "validate_openai_config! raises error when uri base is set but model is blank" do
|
|
error = assert_raises(Setting::ValidationError) do
|
|
Setting.validate_openai_config!(uri_base: "https://api.example.com", model: "")
|
|
end
|
|
|
|
assert_match(/OpenAI model is required/, error.message)
|
|
end
|
|
|
|
test "validate_openai_config! uses current settings when parameters are nil" do
|
|
Setting.openai_uri_base = "https://api.example.com"
|
|
Setting.openai_model = "gpt-4"
|
|
|
|
assert_nothing_raised do
|
|
Setting.validate_openai_config!(uri_base: nil, model: nil)
|
|
end
|
|
end
|
|
|
|
test "validate_openai_config! raises error when current uri base is set but new model is blank" do
|
|
Setting.openai_uri_base = "https://api.example.com"
|
|
Setting.openai_model = "gpt-4"
|
|
|
|
error = assert_raises(Setting::ValidationError) do
|
|
Setting.validate_openai_config!(uri_base: nil, model: "")
|
|
end
|
|
|
|
assert_match(/OpenAI model is required/, error.message)
|
|
end
|
|
|
|
test "validate_openai_config! passes when new uri base is blank and current model exists" do
|
|
Setting.openai_uri_base = "https://api.example.com"
|
|
Setting.openai_model = "gpt-4"
|
|
|
|
assert_nothing_raised do
|
|
Setting.validate_openai_config!(uri_base: "", model: nil)
|
|
end
|
|
end
|
|
|
|
# Dynamic field tests
|
|
test "can set and get dynamic fields" do
|
|
Setting["custom_key"] = "custom_value"
|
|
assert_equal "custom_value", Setting["custom_key"]
|
|
end
|
|
|
|
test "can set and get multiple dynamic fields independently" do
|
|
Setting["key1"] = "value1"
|
|
Setting["key2"] = "value2"
|
|
Setting["key3"] = "value3"
|
|
|
|
assert_equal "value1", Setting["key1"]
|
|
assert_equal "value2", Setting["key2"]
|
|
assert_equal "value3", Setting["key3"]
|
|
end
|
|
|
|
test "setting nil value deletes dynamic field" do
|
|
Setting["temp_key"] = "temp_value"
|
|
assert_equal "temp_value", Setting["temp_key"]
|
|
|
|
Setting["temp_key"] = nil
|
|
assert_nil Setting["temp_key"]
|
|
end
|
|
|
|
test "can delete dynamic field" do
|
|
Setting["delete_key"] = "delete_value"
|
|
assert_equal "delete_value", Setting["delete_key"]
|
|
|
|
value = Setting.delete("delete_key")
|
|
assert_equal "delete_value", value
|
|
assert_nil Setting["delete_key"]
|
|
end
|
|
|
|
test "key? returns true for existing dynamic field" do
|
|
Setting["exists_key"] = "exists_value"
|
|
assert Setting.key?("exists_key")
|
|
end
|
|
|
|
test "key? returns false for non-existing dynamic field" do
|
|
assert_not Setting.key?("nonexistent_key")
|
|
end
|
|
|
|
test "dynamic_keys returns all dynamic field keys" do
|
|
Setting["dynamic1"] = "value1"
|
|
Setting["dynamic2"] = "value2"
|
|
|
|
keys = Setting.dynamic_keys
|
|
assert_includes keys, "dynamic1"
|
|
assert_includes keys, "dynamic2"
|
|
end
|
|
|
|
test "declared fields take precedence over dynamic fields" do
|
|
# Try to set a declared field using bracket notation
|
|
Setting["openai_model"] = "custom-model"
|
|
assert_equal "custom-model", Setting["openai_model"]
|
|
assert_equal "custom-model", Setting.openai_model
|
|
end
|
|
|
|
test "cannot delete declared fields" do
|
|
Setting.openai_model = "test-model"
|
|
result = Setting.delete("openai_model")
|
|
assert_nil result
|
|
assert_equal "test-model", Setting.openai_model
|
|
end
|
|
|
|
test "enabled_securities_providers falls back to twelve_data when nothing is configured" do
|
|
with_env_overrides("SECURITIES_PROVIDERS" => nil, "SECURITIES_PROVIDER" => nil) do
|
|
assert_equal [ "twelve_data" ], Setting.enabled_securities_providers
|
|
end
|
|
end
|
|
|
|
test "enabled_securities_providers returns an empty list when explicitly cleared, not the legacy default" do
|
|
original_providers = Setting.securities_providers
|
|
original_provider = Setting.securities_provider
|
|
|
|
Setting.securities_providers = ""
|
|
Setting.securities_provider = ""
|
|
|
|
assert_equal [], Setting.enabled_securities_providers
|
|
ensure
|
|
# Restore whatever was there before this test, not a hardcoded value —
|
|
# and restore via assignment (not nil) either way, since
|
|
# rails-settings-cached's cache layer doesn't reliably invalidate on
|
|
# delete within a single test process, so a later test can still read
|
|
# back the just-deleted blank override instead of falling through to
|
|
# the field's default.
|
|
Setting.securities_providers = original_providers.presence || ""
|
|
Setting.securities_provider = original_provider.presence || "twelve_data"
|
|
end
|
|
end
|