dry-validation/spec/integration/contract/using_messages_spec.rb

107 lines
3.1 KiB
Ruby

# frozen_string_literal: true
require "dry/validation/contract"
RSpec.describe Dry::Validation::Contract do
shared_context "translated messages" do
subject(:contract) do
contract_class.new
end
let(:contract_class) do
Class.new(Dry::Validation::Contract) do
config.messages.load_paths << SPEC_ROOT.join("fixtures/messages/errors.en.yml").realpath
params do
required(:email).filled(:string, min_size?: 3, max_size?: 100)
end
rule(:email) do
key.failure(:invalid) unless value.include?("@")
key.failure(:taken, values.to_h) if value == "jane@doe.org"
end
end
end
it "configures messages for the schema" do
expect(contract.schema.config.messages.load_paths)
.to eql(contract.class.config.messages.load_paths)
end
describe "result errors" do
it "supports full: true option for schema errors" do
expect(contract.call(email: "").errors(full: true).map(&:to_s))
.to eql(["E-mail must be filled"])
end
it "supports full: true option for contract errors" do
expect(contract.call(email: "jane").errors(full: true).map(&:to_s))
.to eql(["E-mail oh noez bad email"])
end
end
describe "failure" do
it "uses messages for failures" do
expect(contract.call(email: "foo").errors.to_h)
.to eql(email: ["oh noez bad email"])
end
it "passes tokens to message templates" do
expect(contract.call(email: "jane@doe.org").errors.to_h)
.to eql(email: ["looks like jane@doe.org is taken"])
end
end
end
context "using :yaml messages" do
before do
contract_class.config.messages.backend = :yaml
end
include_context "translated messages"
end
context "using :i18n messages" do
before do
I18n.available_locales = %i[en pl]
contract_class.config.messages.backend = :i18n
contract_class.config.messages.load_paths << SPEC_ROOT.join("fixtures/messages/errors.pl.yml").realpath
contract
end
include_context "translated messages"
it "respects I18n.with_locale" do
I18n.with_locale(:pl) do
expect(contract.call(email: "foo").errors.to_h).to eql(email: ["oh nie zły email"])
end
I18n.with_locale(:en) do
expect(contract.call(email: "foo").errors.to_h).to eql(email: ["oh noez bad email"])
end
expect(contract.call(email: "foo").errors(locale: :pl).to_h).to eql(email: ["oh nie zły email"])
expect(contract.call(email: "foo").errors.to_h).to eql(email: ["oh noez bad email"])
end
end
it "parses array tokens as a comma separated list" do
contract = Class.new(Dry::Validation::Contract) do
config.messages.load_paths << SPEC_ROOT.join("fixtures/messages/errors.en.yml").realpath
params do
required(:age).filled(:integer)
end
rule(:age) do
list = [1, 2, 3]
key.failure(:toddler, list: list) unless list.include?(value)
end
end
expect(contract.new.call(age: 4).errors.to_h).to eql(age: ["should be included in 1, 2, 3"])
end
end