mirror of
https://github.com/we-promise/sure.git
synced 2026-09-09 00:24:15 +00:00
220 lines
10 KiB
Ruby
220 lines
10 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "test_helper"
|
|
|
|
class OnchainWalletItemsLocalizationTest < ActionDispatch::IntegrationTest
|
|
include OnchainTestHelper
|
|
|
|
MODAL_HEADERS = { "Turbo-Frame" => "modal" }.freeze
|
|
|
|
TRANSLATED_SCOPES = %w[
|
|
onchain_wallet_items
|
|
settings.providers.onchain_wallet_panel
|
|
].freeze
|
|
|
|
TRANSLATED_KEYS = %w[
|
|
settings.providers.taglines.onchain_wallet
|
|
].freeze
|
|
|
|
setup do
|
|
sign_in users(:family_admin)
|
|
register_fake_chain!
|
|
end
|
|
|
|
teardown do
|
|
unregister_fake_chain!
|
|
end
|
|
|
|
test "the Onchain wallet slices resolve directly in German" do
|
|
translated_keys.each do |key|
|
|
assert I18n.exists?(key, :de, fallback: false), "de is missing #{key}"
|
|
end
|
|
end
|
|
|
|
test "German translations preserve interpolation and pluralization contracts" do
|
|
address = OnchainTestHelper::FAKE_ADDRESS
|
|
|
|
assert_equal address,
|
|
I18n.t("onchain_wallet_items.choose_chain.subtitle", locale: :de, fallback: false, address: address)
|
|
assert_equal "Fake Chain · #{address}",
|
|
I18n.t("onchain_wallet_items.token_review.subtitle", locale: :de, fallback: false,
|
|
chain: "Fake Chain", address: address)
|
|
exchange_rate_body = I18n.t("onchain_wallet_items.price_provider_warning.exchange_rate_body",
|
|
locale: :de, fallback: false, currency: "EUR")
|
|
%w[USD EUR EXCHANGE_RATE_PROVIDER Frankfurter API-Schlüssel].each do |technical_term|
|
|
assert_match technical_term, exchange_rate_body
|
|
end
|
|
tagline = I18n.t("settings.providers.taglines.onchain_wallet", locale: :de, fallback: false)
|
|
%w[Bitcoin EVM Solana].each { |brand_or_network| assert_match brand_or_network, tagline }
|
|
assert_match "USDC",
|
|
I18n.t("onchain_wallet_items.link_wallet.errors.some_failed", locale: :de,
|
|
fallback: false, assets: "USDC")
|
|
assert_equal "1 Vermögenswert dieser Wallet wird verfolgt.",
|
|
I18n.t("onchain_wallet_items.link_wallet.success", locale: :de, fallback: false, count: 1)
|
|
assert_equal "2 Vermögenswerte dieser Wallet werden verfolgt.",
|
|
I18n.t("onchain_wallet_items.link_wallet.success", locale: :de, fallback: false, count: 2)
|
|
assert_match "25", I18n.t("onchain_wallet_items.token_review_form.assets_truncated",
|
|
locale: :de, fallback: false, count: 25)
|
|
assert_equal "USDC wird nicht mehr verfolgt. Das Konto und der Verlauf bleiben erhalten.",
|
|
I18n.t("onchain_wallet_items.disconnect_asset.success", locale: :de,
|
|
fallback: false, symbol: "USDC")
|
|
assert_equal "1 Vermögenswert an dieser Adresse wird nicht mehr verfolgt.",
|
|
I18n.t("onchain_wallet_items.disconnect_wallet.success", locale: :de,
|
|
fallback: false, count: 1)
|
|
assert_equal "2 Vermögenswerte an dieser Adresse werden nicht mehr verfolgt.",
|
|
I18n.t("onchain_wallet_items.disconnect_wallet.success", locale: :de,
|
|
fallback: false, count: 2)
|
|
assert_match "USDC",
|
|
I18n.t("onchain_wallet_items.manage.disconnect_asset_confirm", locale: :de,
|
|
fallback: false, symbol: "USDC")
|
|
assert_equal "Verfolgte Vermögenswerte aktualisiert (2 hinzugefügt, 1 entfernt).",
|
|
I18n.t("onchain_wallet_items.update_tokens.success", locale: :de,
|
|
fallback: false, created: 2, removed: 1)
|
|
assert_equal "Vor 5 Minuten synchronisiert",
|
|
I18n.t("onchain_wallet_items.wallet_card.status", locale: :de,
|
|
fallback: false, timestamp: "5 Minuten")
|
|
end
|
|
|
|
test "the German management page renders tracked wallet actions" do
|
|
item = create_onchain_wallet_item(family: users(:family_admin).family)
|
|
create_onchain_wallet_account(item: item)
|
|
create_onchain_wallet_account(item: item, asset: fake_token_asset(symbol: "USDC", contract: "0xusdc"))
|
|
|
|
get manage_onchain_wallet_item_url(item, locale: :de), headers: MODAL_HEADERS
|
|
|
|
assert_response :success
|
|
assert_match "Selbstverwahrte Wallets verwalten", response.body
|
|
assert_match "Vermögenswerte verwalten", response.body
|
|
assert_match "Wallet trennen", response.body
|
|
assert_match "Nicht mehr verfolgen", response.body
|
|
assert_match OnchainTestHelper::FAKE_ADDRESS, response.body
|
|
assert_match "USDC", response.body
|
|
assert_no_match "Manage self-custody wallets", response.body
|
|
assert_no_match "Disconnect wallet", response.body
|
|
end
|
|
|
|
test "the German settings panel renders management and advanced actions" do
|
|
item = create_onchain_wallet_item(family: users(:family_admin).family)
|
|
create_onchain_wallet_account(item: item)
|
|
|
|
get connect_form_settings_providers_path(provider_key: "onchain_wallet", locale: :de)
|
|
|
|
assert_response :success
|
|
assert_match "Wallets verwalten", response.body
|
|
assert_match "Erweitert", response.body
|
|
assert_match "Etherscan-API-Schlüssel (optional)", response.body
|
|
assert_match "Übertragungen vor diesem Datum ignorieren", response.body
|
|
assert_match "Alle Wallets trennen", response.body
|
|
assert_no_match "Manage wallets", response.body
|
|
assert_no_match "Disconnect all wallets", response.body
|
|
end
|
|
|
|
test "the German add-wallet form renders its security guidance" do
|
|
get new_wallet_onchain_wallet_items_url(locale: :de), headers: MODAL_HEADERS
|
|
|
|
assert_response :success
|
|
assert_match "Selbstverwahrte Wallet hinzufügen", response.body
|
|
assert_match "Nur Lesezugriff, keine Schlüssel erforderlich", response.body
|
|
assert_match "Mit diesen Daten lassen sich keine Vermögenswerte übertragen.", response.body
|
|
assert_match "Gib niemals eine Seed-Phrase oder einen Private Key ein.", response.body
|
|
assert_match "Bitcoin wird jeweils über eine einzelne Adresse verfolgt.", response.body
|
|
end
|
|
|
|
test "the German token review renders selection guidance" do
|
|
stub_fake_snapshot(
|
|
OnchainTestHelper::FAKE_ADDRESS,
|
|
Onchain::Snapshot.new(
|
|
assets: [
|
|
fake_native_asset(quantity: 2),
|
|
fake_token_asset(symbol: "USDC", contract: "0xusdc", quantity: 10, notable: false),
|
|
fake_token_asset(symbol: "Visit site to claim", contract: "0xspam", quantity: 1, notable: false)
|
|
],
|
|
movements: []
|
|
)
|
|
)
|
|
|
|
post preview_wallet_onchain_wallet_items_url(locale: :de),
|
|
params: {
|
|
address: OnchainTestHelper::FAKE_ADDRESS,
|
|
chain: OnchainTestHelper::FAKE_CHAIN
|
|
},
|
|
headers: MODAL_HEADERS
|
|
|
|
assert_response :success
|
|
assert_match "Vermögenswerte zum Verfolgen auswählen", response.body
|
|
assert_match "Wallets erhalten Spam-Airdrops", response.body
|
|
assert_match "Kein Preis verfügbar; wird nur anhand der Menge verfolgt", response.body
|
|
assert_match "USDC", response.body
|
|
end
|
|
|
|
test "the German account method selector localizes the Onchain entry" do
|
|
get new_crypto_url(locale: :de, step: "method_select"), headers: MODAL_HEADERS
|
|
|
|
assert_response :success
|
|
assert_match "Selbstverwahrte Wallet", response.body
|
|
assert_no_match "Self-custody wallet", response.body
|
|
end
|
|
|
|
test "a German recovery state hides the external provider error" do
|
|
external_error = "external explorer exposed a private diagnostic"
|
|
OnchainTestHelper::FakeAdapter.error = StandardError.new(external_error)
|
|
|
|
assert_difference "DebugLogEntry.count", 1 do
|
|
post preview_wallet_onchain_wallet_items_url(locale: :de),
|
|
params: {
|
|
address: OnchainTestHelper::FAKE_ADDRESS,
|
|
chain: OnchainTestHelper::FAKE_CHAIN
|
|
},
|
|
headers: MODAL_HEADERS
|
|
end
|
|
|
|
assert_response :unprocessable_entity
|
|
assert_match "Beim Lesen dieser Wallet ist etwas schiefgelaufen.", response.body
|
|
assert_no_match external_error, response.body
|
|
end
|
|
|
|
test "representative English output remains unchanged" do
|
|
I18n.with_locale(:en) do
|
|
assert_equal "Add a self-custody wallet", I18n.t("onchain_wallet_items.new_wallet.title", fallback: false)
|
|
assert_equal "Read-only, no keys required",
|
|
I18n.t("settings.providers.onchain_wallet_panel.keyless_title", fallback: false)
|
|
assert_equal "Only public chain data is read. Never enter a seed phrase or private key.",
|
|
I18n.t("onchain_wallet_items.new_wallet.read_only_note", fallback: false)
|
|
assert_equal "Self-custody wallet",
|
|
I18n.t("onchain_wallet_items.provider_connection.name", fallback: false)
|
|
assert_equal "Manage self-custody wallets",
|
|
I18n.t("onchain_wallet_items.manage.title", fallback: false)
|
|
assert_equal "Stopped tracking 2 assets at that address.",
|
|
I18n.t("onchain_wallet_items.disconnect_wallet.success", fallback: false, count: 2)
|
|
assert_equal "Etherscan API key (optional)",
|
|
I18n.t("settings.providers.onchain_wallet_panel.etherscan_api_key_label", fallback: false)
|
|
end
|
|
|
|
get new_wallet_onchain_wallet_items_url(locale: :en), headers: MODAL_HEADERS
|
|
|
|
assert_response :success
|
|
assert_match "Add a self-custody wallet", response.body
|
|
assert_match "Read-only, no keys required", response.body
|
|
assert_match "Never enter a seed phrase or private key.", response.body
|
|
end
|
|
|
|
private
|
|
def translated_keys
|
|
scoped_keys = TRANSLATED_SCOPES.flat_map do |scope|
|
|
translations = I18n.t(scope, locale: :en, fallback: false, default: nil)
|
|
assert_kind_of Hash, translations, "#{scope} must remain a translation subtree"
|
|
|
|
flatten_keys(translations).map { |key| "#{scope}.#{key}" }
|
|
end
|
|
|
|
scoped_keys + TRANSLATED_KEYS
|
|
end
|
|
|
|
def flatten_keys(translations, prefix = nil)
|
|
translations.flat_map do |key, value|
|
|
path = [ prefix, key ].compact.join(".")
|
|
value.is_a?(Hash) ? flatten_keys(value, path) : path
|
|
end
|
|
end
|
|
end
|