mirror of
https://github.com/we-promise/sure.git
synced 2026-09-06 15:14:19 +00:00
* fix(rules): validate Rule::Condition type registry + normalize legacy 'name' values Closes #1229. /rules crashes with `ActionView::Template::Error (Unsupported condition type: name)` when a Rule::Condition row has a condition_type the registry doesn't know about. Reporter found two cases in the wild: - "name" — invalid, crashes the rules index because the view path (`_rule.html.erb` → `displayed_condition.filter.label`) ends up in `Rule::Registry#get_filter!` which raises. - "transaction_details" — actually a valid filter that searches the `transactions.extra` JSONB metadata field (see existing tests in test/models/rule/condition_test.rb). Reporter assumed it was a transaction-name synonym; it isn't. This PR leaves it alone. Changes: - Rule::Condition gains a SUPPORTED_CONDITION_TYPES registry constant matching Rule::Registry::TransactionResource#condition_filters plus "compound", an inclusion validation against it, and a before_validation callback that maps the one known legacy alias ("name" -> "transaction_name") so saving an existing rule fixes itself. - Rule::Condition#filter now rescues UnsupportedConditionError and returns a Rule::ConditionFilter::Unsupported placeholder. The placeholder labels itself "Unsupported (<key>)" (i18n) and its #apply returns `scope.none`, so any stale row that survives the migration stops matching rather than silently matching everything. - A one-shot migration normalizes existing "name" rows. Single UPDATE statement — rule_conditions is a small per-family table. Tests added in test/models/rule/condition_test.rb cover the inclusion validation, the normalization callback, and the graceful-render path (uses update_columns to simulate a row written before the validation existed — that's the exact codepath that crashes /rules today). * test(rules): add system test for unsupported condition_type render + raise on migration down - test/system/rules_test.rb: visit /rules with a row whose condition_type has been update_columns'd to "name" — assert page renders and shows the "Unsupported (name)" label instead of raising. - db/migrate/...normalize_rule_condition_types.rb: replace the empty #down with `raise ActiveRecord::IrreversibleMigration` to match the repo's data-migration convention (see e.g. 20260219190000_scope_*). * chore(rules): log unsupported condition + cross-check supported types Address maintainer review on #1908: - Log a Rails.logger.warn (with rule_id and condition_type) from Rule::ConditionFilter::Unsupported#apply so silent zero-match rules are traceable when debugging. - Add a comment above Rule::Condition::SUPPORTED_CONDITION_TYPES and a test that cross-checks it against the registry's filter keys, so drift between the two surfaces as a failing test rather than a confusing validation error. * refactor(rules): derive supported condition types from registry --------- Co-authored-by: John Baillie <johnbaillie2007@gmail.com> Co-authored-by: Khaostica <256858950+Khaostica@users.noreply.github.com> Co-authored-by: sure-admin <sure-admin@splashblot.com>
59 lines
1.8 KiB
Ruby
59 lines
1.8 KiB
Ruby
require "application_system_test_case"
|
|
|
|
class RulesTest < ApplicationSystemTestCase
|
|
setup do
|
|
sign_in @user = users(:family_admin)
|
|
end
|
|
|
|
test "shows queued processed modified and blocked counts for recent rule runs" do
|
|
rule = @user.family.rules.create!(
|
|
name: "Whole Foods Testing",
|
|
resource_type: "transaction",
|
|
effective_date: 1.year.ago.to_date,
|
|
conditions: [
|
|
Rule::Condition.new(condition_type: "transaction_name", operator: "like", value: "Whole Foods")
|
|
],
|
|
actions: [
|
|
Rule::Action.new(action_type: "set_transaction_category", value: categories(:food_and_drink).id)
|
|
]
|
|
)
|
|
|
|
rule.rule_runs.create!(
|
|
rule_name: rule.name,
|
|
execution_type: "manual",
|
|
status: "success",
|
|
transactions_queued: 20,
|
|
transactions_processed: 20,
|
|
transactions_modified: 10,
|
|
pending_jobs_count: 0,
|
|
executed_at: Time.current
|
|
)
|
|
|
|
visit rules_path
|
|
|
|
assert_selector "th", text: /queued\s+processed\s+modified\s+blocked/i
|
|
assert_selector "td", text: "20 / 20 / 10 / 10"
|
|
end
|
|
|
|
test "rules page renders gracefully when a condition has an unsupported condition_type" do
|
|
rule = @user.family.rules.create!(
|
|
name: "Legacy bad rule",
|
|
resource_type: "transaction",
|
|
conditions: [
|
|
Rule::Condition.new(condition_type: "transaction_name", operator: "like", value: "x")
|
|
],
|
|
actions: [
|
|
Rule::Action.new(action_type: "set_transaction_category", value: categories(:food_and_drink).id)
|
|
]
|
|
)
|
|
|
|
# Simulate a legacy row written before the inclusion validation existed.
|
|
rule.conditions.first.update_columns(condition_type: "name")
|
|
|
|
visit rules_path
|
|
|
|
assert_selector "h3", text: "Legacy bad rule"
|
|
assert_text "Unsupported (name)"
|
|
end
|
|
end
|