lib/tram/policy/rspec.rb in tram-policy-0.4.0 vs lib/tram/policy/rspec.rb in tram-policy-1.0.0
- old
+ new
@@ -1,125 +1,76 @@
require "rspec"
-# Checks that a block provides policy that has errors under given tags
-# It also check that selected messages has translations to all available locales
-#
-# @example
-# subject(:policy) { UserPolicy[name: nil] }
-# expect { policy }.to be_invalid_at field: "name", level: "error"
-#
-# You have to wrap expectation to a block called for available locales.
-#
RSpec::Matchers.define :be_invalid_at do |**tags|
- supports_block_expectations
-
- # ****************************************************************************
- # Result collectors for all available locations
- # ****************************************************************************
-
- attr_accessor :policy
-
- def errors
- @errors ||= {}
+ def locales
+ @locales ||= I18n.available_locales
end
- def tags
- @tags ||= {}
- end
-
- # ****************************************************************************
- # Helpers to provide results for all locales
- # ****************************************************************************
-
- def prepare_localized_results(policy_block, tags, locale)
- I18n.locale = locale
- local_policy = policy_block.call
- self.policy = local_policy.inspect
- errors[locale] = local_policy&.errors&.filter(tags)&.map do |error|
- { message: error.message, tags: error.options } # translate immediately
+ def check(policy, tags)
+ @errors ||= policy.errors.filter(tags).map do |error|
+ { item: error.item }.tap do |obj|
+ locales.each { |l| obj[l] = I18n.with_locale(l) { error.message } }
+ end
end
end
- def prepare_results(policy_block, tags)
- original = I18n.locale
- I18n.available_locales.each do |locale|
- prepare_localized_results(policy_block, tags, locale)
- end
- ensure
- I18n.locale = original
- end
+ attr_reader :errors
- # ****************************************************************************
- # Checkers for collected results
- # ****************************************************************************
-
- # Checks if selected errors are present in all available locales
- def errored?
- errors.values.map(&:any?).reduce(true, &:&) == true
+ def missed_translations
+ @missed_translations ||= \
+ errors.flat_map { |rec| rec.values_at(*locales) }
+ .select { |message| message.start_with? "translation missing" }
end
- # Checks if selected errors are absent in all available locales
- def not_errored?
- errors.values.map(&:empty?).reduce(true, &:&) == true
- end
-
- # Checks if all collected errors are translated
- def translated?
- texts = errors.values.flatten.map { |err| err[:message] }
- texts.select { |text| text.start_with?("translation missing") }.empty?
- end
-
def report_errors
- text = "Actual errors:\n"
- errors.each do |locale, local_errors|
- text << " #{locale}:\n"
- local_errors&.each { |err| text << " - #{err.values.join(" ")}\n" }
+ locales.each_with_object("Actual errors:\n") do |loc, text|
+ text << " #{loc}:\n"
+ errors.each { |err| text << " - #{err[loc]} #{err[:item]}\n" }
end
- text
end
- # ****************************************************************************
- # Positive matcher
- # ****************************************************************************
+ match do |policy|
+ check(policy, tags)
+ errors.any? && missed_translations.empty?
+ end
- match do |policy_block|
- prepare_results(policy_block, tags)
- errored? && translated?
+ match_when_negated do |policy|
+ check(policy, tags)
+ errors.empty?
end
- failure_message do |_|
+ failure_message do |policy|
+ desc = tags.any? ? " with tags: #{tags}" : ""
text = "The policy: #{policy}\n"
- text << "should have had errors with tags: #{tags}, "
- text << "whose messages are translated in all available locales.\n"
+ text << " should have had errors#{desc},"
+ text << " whose messages are translated in all available locales.\n"
text << report_errors
text
end
- # ****************************************************************************
- # Negative matcher
- # ****************************************************************************
-
- match_when_negated do |policy_block|
- prepare_results(policy_block, tags)
- not_errored?
- end
-
- failure_message_when_negated do |_|
- text = "#{policy}\nshould not have had any error with tags: #{tags}.\n"
+ failure_message_when_negated do |policy|
+ desc = tags.any? ? " with tags: #{tags}" : ""
+ text = "#{policy}\nshould not have had any error#{desc}.\n"
text << report_errors
text
end
end
-RSpec.shared_examples :invalid_policy do |condition = nil, **tags|
- constraint = "with tags: #{tags}" if tags.any?
- it ["is invalid", condition, constraint].compact.join(" ") do
- expect { subject }.to be_invalid_at(tags)
+RSpec::Matchers.define :be_invalid do
+ match do |policy|
+ expect(policy).to be_invalid_at
end
+
+ match_when_negated do |policy|
+ expect(policy).not_to be_invalid_at
+ end
end
-RSpec.shared_examples :valid_policy do |condition = nil, **tags|
- constraint = "with tags: #{tags}" if tags.any?
- it ["is valid", condition, constraint].compact.join(" ") do
- expect { subject }.not_to be_invalid_at(tags)
+RSpec::Matchers.define :be_valid_at do |**tags|
+ match do |policy|
+ expect(policy).not_to be_invalid_at(tags)
+ end
+
+ match_when_negated do |policy|
+ expect(policy).to be_invalid_at(tags)
end
end