rubocop -a
This commit is contained in:
parent
016b634b8c
commit
9161759d83
36
Gemfile
36
Gemfile
|
@ -1,37 +1,37 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
source 'https://rubygems.org'
|
||||
source "https://rubygems.org"
|
||||
|
||||
eval_gemfile 'Gemfile.devtools'
|
||||
eval_gemfile "Gemfile.devtools"
|
||||
|
||||
gemspec
|
||||
|
||||
if ENV['DRY_CONFIGURABLE_FROM_MASTER'].eql?('true')
|
||||
gem 'dry-configurable', github: 'dry-rb/dry-configurable', branch: 'master'
|
||||
if ENV["DRY_CONFIGURABLE_FROM_MASTER"].eql?("true")
|
||||
gem "dry-configurable", github: "dry-rb/dry-configurable", branch: "master"
|
||||
end
|
||||
|
||||
gem 'dry-schema', github: 'dry-rb/dry-schema', branch: 'master'
|
||||
gem "dry-schema", github: "dry-rb/dry-schema", branch: "master"
|
||||
|
||||
if ENV['DRY_TYPES_FROM_MASTER'].eql?('true')
|
||||
gem 'dry-types', github: 'dry-rb/dry-types', branch: 'master'
|
||||
if ENV["DRY_TYPES_FROM_MASTER"].eql?("true")
|
||||
gem "dry-types", github: "dry-rb/dry-types", branch: "master"
|
||||
end
|
||||
|
||||
group :test do
|
||||
gem 'dry-monads', '~> 1.0'
|
||||
gem 'i18n', require: false
|
||||
gem "dry-monads", "~> 1.0"
|
||||
gem "i18n", require: false
|
||||
end
|
||||
|
||||
group :tools do
|
||||
gem 'pry', platform: :jruby
|
||||
gem 'pry-byebug', platform: :mri
|
||||
gem "pry", platform: :jruby
|
||||
gem "pry-byebug", platform: :mri
|
||||
end
|
||||
|
||||
group :benchmarks do
|
||||
gem 'actionpack'
|
||||
gem 'activemodel'
|
||||
gem 'activerecord'
|
||||
gem 'benchmark-ips'
|
||||
gem 'hotch', platform: :mri
|
||||
gem 'sqlite3'
|
||||
gem 'virtus'
|
||||
gem "actionpack"
|
||||
gem "activemodel"
|
||||
gem "activerecord"
|
||||
gem "benchmark-ips"
|
||||
gem "hotch", platform: :mri
|
||||
gem "sqlite3"
|
||||
gem "virtus"
|
||||
end
|
||||
|
|
28
Rakefile
28
Rakefile
|
@ -1,22 +1,22 @@
|
|||
#!/usr/bin/env rake
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'bundler/gem_tasks'
|
||||
require "bundler/gem_tasks"
|
||||
|
||||
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'lib'))
|
||||
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "lib"))
|
||||
|
||||
require 'rspec/core'
|
||||
require 'rspec/core/rake_task'
|
||||
require "rspec/core"
|
||||
require "rspec/core/rake_task"
|
||||
|
||||
require 'dry/validation'
|
||||
require "dry/validation"
|
||||
|
||||
RSpec::Core::RakeTask.new(:spec)
|
||||
|
||||
extensions = Dir['./spec/extensions/*'].map { |path| Pathname(path).basename.to_s.to_sym }
|
||||
extensions = Dir["./spec/extensions/*"].map { |path| Pathname(path).basename.to_s.to_sym }
|
||||
|
||||
desc 'Run only core specs without extensions specs'
|
||||
RSpec::Core::RakeTask.new('spec:core') do |t|
|
||||
t.rspec_opts = 'spec/unit spec/integration --pattern **/*_spec.rb'
|
||||
desc "Run only core specs without extensions specs"
|
||||
RSpec::Core::RakeTask.new("spec:core") do |t|
|
||||
t.rspec_opts = "spec/unit spec/integration --pattern **/*_spec.rb"
|
||||
end
|
||||
|
||||
extensions.each do |ext|
|
||||
|
@ -30,18 +30,18 @@ extensions.each do |ext|
|
|||
end
|
||||
end
|
||||
|
||||
desc 'Run all specs with all extensions enabled'
|
||||
task 'spec:extensions' do
|
||||
desc "Run all specs with all extensions enabled"
|
||||
task "spec:extensions" do
|
||||
puts "Loading extensions: #{extensions.inspect}"
|
||||
|
||||
Dry::Validation.load_extensions(*extensions)
|
||||
Rake::Task[:spec].invoke
|
||||
end
|
||||
|
||||
desc 'Run all specs in isolation with extension enabled'
|
||||
task 'spec:isolation' => ['spec:core', *extensions.map { |ext| "spec:#{ext}" }]
|
||||
desc "Run all specs in isolation with extension enabled"
|
||||
task "spec:isolation" => ["spec:core", *extensions.map { |ext| "spec:#{ext}" }]
|
||||
|
||||
desc 'Run CI build'
|
||||
desc "Run CI build"
|
||||
task ci: %w[spec:core spec:isolation spec:extensions]
|
||||
|
||||
task default: :ci
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'active_record'
|
||||
require "active_record"
|
||||
|
||||
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
|
||||
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
|
||||
|
||||
ActiveRecord::Schema.define do
|
||||
create_table :users do |table|
|
||||
|
@ -16,6 +16,6 @@ module AR
|
|||
self.table_name = :users
|
||||
|
||||
validates :email, :age, presence: true
|
||||
validates :age, numericality: { greater_than: 18 }
|
||||
validates :age, numericality: {greater_than: 18}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'benchmark/ips'
|
||||
require 'active_model'
|
||||
require "benchmark/ips"
|
||||
require "active_model"
|
||||
|
||||
require 'i18n'
|
||||
require 'dry-validation'
|
||||
require 'byebug'
|
||||
require "i18n"
|
||||
require "dry-validation"
|
||||
require "byebug"
|
||||
|
||||
require_relative 'active_record_setup'
|
||||
require_relative "active_record_setup"
|
||||
|
||||
module AM
|
||||
class User
|
||||
|
@ -16,10 +16,10 @@ module AM
|
|||
attr_reader :email, :age
|
||||
|
||||
validates :email, :age, presence: true
|
||||
validates :age, numericality: { greater_than: 18 }
|
||||
validates :age, numericality: {greater_than: 18}
|
||||
|
||||
def initialize(attrs)
|
||||
@email, @age = attrs.values_at('email', 'age')
|
||||
@email, @age = attrs.values_at("email", "age")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -33,30 +33,30 @@ contract = Dry::Validation::Contract.build do
|
|||
end
|
||||
|
||||
rule(:age) do
|
||||
key.failure('must be greater than 18') if values[:age] <= 18
|
||||
key.failure("must be greater than 18") if values[:age] <= 18
|
||||
end
|
||||
end
|
||||
|
||||
params = { 'email' => '', 'age' => '18' }
|
||||
params = {"email" => "", "age" => "18"}
|
||||
|
||||
puts contract.(params).inspect
|
||||
puts AR::User.new(params).validate
|
||||
puts AM::User.new(params).validate
|
||||
|
||||
Benchmark.ips do |x|
|
||||
x.report('ActiveModel') do
|
||||
x.report("ActiveModel") do
|
||||
user = AM::User.new(params)
|
||||
user.validate
|
||||
user.errors
|
||||
end
|
||||
|
||||
x.report('ActiveRecord') do
|
||||
x.report("ActiveRecord") do
|
||||
user = AR::User.new(params)
|
||||
user.validate
|
||||
user.errors
|
||||
end
|
||||
|
||||
x.report('dry-validation') do
|
||||
x.report("dry-validation") do
|
||||
contract.(params).errors
|
||||
end
|
||||
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'benchmark/ips'
|
||||
require 'active_model'
|
||||
require "benchmark/ips"
|
||||
require "active_model"
|
||||
|
||||
require 'i18n'
|
||||
require 'dry-validation'
|
||||
require 'byebug'
|
||||
require "i18n"
|
||||
require "dry-validation"
|
||||
require "byebug"
|
||||
|
||||
COUNT = (ENV['COUNT'] || 100).to_i
|
||||
COUNT = (ENV["COUNT"] || 100).to_i
|
||||
FIELDS = COUNT.times.map { |i| :"field_#{i}" }
|
||||
|
||||
class User
|
||||
include ActiveModel::Validations
|
||||
|
||||
attr_reader(*FIELDS)
|
||||
validates(*FIELDS, presence: true, numericality: { greater_than: FIELDS.size / 2 })
|
||||
validates(*FIELDS, presence: true, numericality: {greater_than: FIELDS.size / 2})
|
||||
|
||||
def initialize(attrs)
|
||||
attrs.each do |field, value|
|
||||
|
@ -39,13 +39,13 @@ puts contract.(params).inspect
|
|||
puts User.new(params).validate
|
||||
|
||||
Benchmark.ips do |x|
|
||||
x.report('ActiveModel::Validations') do
|
||||
x.report("ActiveModel::Validations") do
|
||||
user = User.new(params)
|
||||
user.validate
|
||||
user.errors
|
||||
end
|
||||
|
||||
x.report('dry-validation / schema') do
|
||||
x.report("dry-validation / schema") do
|
||||
contract.(params).errors
|
||||
end
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'benchmark/ips'
|
||||
require 'active_model'
|
||||
require "benchmark/ips"
|
||||
require "active_model"
|
||||
|
||||
require 'i18n'
|
||||
require 'dry-validation'
|
||||
require "i18n"
|
||||
require "dry-validation"
|
||||
|
||||
require_relative 'active_record_setup'
|
||||
require_relative "active_record_setup"
|
||||
|
||||
module AM
|
||||
class User
|
||||
|
@ -15,10 +15,10 @@ module AM
|
|||
attr_reader :email, :age
|
||||
|
||||
validates :email, :age, presence: true
|
||||
validates :age, presence: true, numericality: { greater_than: 18 }
|
||||
validates :age, presence: true, numericality: {greater_than: 18}
|
||||
|
||||
def initialize(attrs)
|
||||
@email, @age = attrs.values_at('email', 'age')
|
||||
@email, @age = attrs.values_at("email", "age")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -32,29 +32,29 @@ contract = Dry::Validation::Contract.build {
|
|||
end
|
||||
|
||||
rule(:age) do
|
||||
failure('must be greater than 18') if values[:age] <= 18
|
||||
failure("must be greater than 18") if values[:age] <= 18
|
||||
end
|
||||
}
|
||||
|
||||
params = { 'email' => 'jane@doe.org', 'age' => '19' }
|
||||
params = {"email" => "jane@doe.org", "age" => "19"}
|
||||
|
||||
puts contract.(params).inspect
|
||||
puts AM::User.new(params).validate
|
||||
|
||||
Benchmark.ips do |x|
|
||||
x.report('ActiveModel::Validations') do
|
||||
x.report("ActiveModel::Validations") do
|
||||
user = AM::User.new(params)
|
||||
user.validate
|
||||
user.errors
|
||||
end
|
||||
|
||||
x.report('ActiveRecord') do
|
||||
x.report("ActiveRecord") do
|
||||
user = AR::User.new(params)
|
||||
user.validate
|
||||
user.errors
|
||||
end
|
||||
|
||||
x.report('dry-validation') do
|
||||
x.report("dry-validation") do
|
||||
contract.(params).errors
|
||||
end
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'suite'
|
||||
require_relative "suite"
|
||||
|
||||
class TestContract < Dry::Validation::Contract
|
||||
config.messages.backend = :i18n
|
||||
|
@ -12,12 +12,12 @@ class TestContract < Dry::Validation::Contract
|
|||
end
|
||||
|
||||
rule(:age) do
|
||||
key.failure('must be greater than 18') if values[:age] <= 18
|
||||
key.failure("must be greater than 18") if values[:age] <= 18
|
||||
end
|
||||
end
|
||||
|
||||
contract = TestContract.new
|
||||
input = { email: '', age: 18, address: {} }
|
||||
input = {email: "", age: 18, address: {}}
|
||||
|
||||
profile do
|
||||
10_000.times do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'suite'
|
||||
require_relative "suite"
|
||||
|
||||
class TestContract < Dry::Validation::Contract
|
||||
config.messages.backend = :i18n
|
||||
|
@ -12,11 +12,11 @@ class TestContract < Dry::Validation::Contract
|
|||
end
|
||||
|
||||
rule(:age) do
|
||||
key.failure('must be greater than 18') if values[:age] <= 18
|
||||
key.failure("must be greater than 18") if values[:age] <= 18
|
||||
end
|
||||
end
|
||||
|
||||
input = { 'email' => 'jane@doe.org', 'age' => 19, 'address' => { 'city' => 'Krakow' } }
|
||||
input = {"email" => "jane@doe.org", "age" => 19, "address" => {"city" => "Krakow"}}
|
||||
contract = TestContract.new
|
||||
|
||||
profile do
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'suite'
|
||||
require 'hotch'
|
||||
require_relative "suite"
|
||||
require "hotch"
|
||||
|
||||
Hotch() do
|
||||
1000.times do
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'suite'
|
||||
require 'hotch'
|
||||
require_relative "suite"
|
||||
require "hotch"
|
||||
|
||||
require 'dry-validation'
|
||||
require "dry-validation"
|
||||
|
||||
I18n.locale = :en
|
||||
I18n.backend.load_translations
|
||||
|
||||
COUNT = ENV['COUNT'].to_i
|
||||
COUNT = ENV["COUNT"].to_i
|
||||
FIELDS = COUNT.times.map { |i| :"field_#{i}" }
|
||||
|
||||
schema = Dry::Validation.Schema do
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'suite'
|
||||
require 'hotch'
|
||||
require_relative "suite"
|
||||
require "hotch"
|
||||
|
||||
schema = Dry::Validation.Schema do
|
||||
configure { config.messages = :i18n }
|
||||
|
@ -11,7 +11,7 @@ schema = Dry::Validation.Schema do
|
|||
required(:address).filled(:hash?)
|
||||
end
|
||||
|
||||
input = { email: '', age: 18, address: {} }
|
||||
input = {email: "", age: 18, address: {}}
|
||||
|
||||
puts schema.(input).inspect
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'hotch'
|
||||
require 'i18n'
|
||||
require "hotch"
|
||||
require "i18n"
|
||||
|
||||
require 'dry-validation'
|
||||
require "dry-validation"
|
||||
|
||||
def profile(&block)
|
||||
Hotch(filter: 'Dry', &block)
|
||||
Hotch(filter: "Dry", &block)
|
||||
end
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'pry'
|
||||
require 'bundler/setup'
|
||||
require 'dry-validation'
|
||||
require "pry"
|
||||
require "bundler/setup"
|
||||
require "dry-validation"
|
||||
|
||||
module Types
|
||||
include Dry::Types()
|
||||
|
@ -28,4 +28,4 @@ class Context
|
|||
end
|
||||
end
|
||||
|
||||
Pry.start(Context.new, prompt: [proc { 'dry-validation> ' }, proc { 'dry-validation*> ' }])
|
||||
Pry.start(Context.new, prompt: [proc { "dry-validation> " }, proc { "dry-validation*> " }])
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry-validation'
|
||||
require "dry-validation"
|
||||
|
||||
schema = Dry::Validation.Schema do
|
||||
required(:email).filled
|
||||
|
@ -8,7 +8,7 @@ schema = Dry::Validation.Schema do
|
|||
required(:age).filled(:int?, gt?: 18)
|
||||
end
|
||||
|
||||
errors = schema.call(email: 'jane@doe.org', age: 19).messages
|
||||
errors = schema.call(email: "jane@doe.org", age: 19).messages
|
||||
|
||||
puts errors.inspect
|
||||
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'byebug'
|
||||
require 'dry-validation'
|
||||
require "byebug"
|
||||
require "dry-validation"
|
||||
|
||||
schema = Dry::Validation.Schema do
|
||||
key(:phone_numbers).each(:str?)
|
||||
end
|
||||
|
||||
errors = schema.call(phone_numbers: '').messages
|
||||
errors = schema.call(phone_numbers: "").messages
|
||||
|
||||
puts errors.inspect
|
||||
|
||||
errors = schema.call(phone_numbers: ['123456789', 123_456_789]).messages
|
||||
errors = schema.call(phone_numbers: ["123456789", 123_456_789]).messages
|
||||
|
||||
puts errors.inspect
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'json'
|
||||
require 'dry-validation'
|
||||
require "json"
|
||||
require "dry-validation"
|
||||
|
||||
contract = Class.new(Dry::Validation::Contract) do
|
||||
json do
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry-validation'
|
||||
require "dry-validation"
|
||||
|
||||
schema = Dry::Validation.Schema do
|
||||
configure do
|
||||
def self.messages
|
||||
super.merge(en: {
|
||||
errors: {
|
||||
john_email?: '%{value} is not a john email',
|
||||
example_email?: '%{value} is not a example email'
|
||||
john_email?: "%{value} is not a john email",
|
||||
example_email?: "%{value} is not a example email"
|
||||
}
|
||||
})
|
||||
end
|
||||
|
@ -17,14 +17,14 @@ schema = Dry::Validation.Schema do
|
|||
required(:email).filled
|
||||
|
||||
validate(example_email?: :email) do |value|
|
||||
value.end_with?('@example.com')
|
||||
value.end_with?("@example.com")
|
||||
end
|
||||
|
||||
validate(john_email?: :email) do |value|
|
||||
value.start_with?('john')
|
||||
value.start_with?("john")
|
||||
end
|
||||
end
|
||||
|
||||
errors = schema.call(email: 'jane@doe.org').messages
|
||||
errors = schema.call(email: "jane@doe.org").messages
|
||||
|
||||
puts errors.inspect
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry-validation'
|
||||
require "dry-validation"
|
||||
|
||||
schema = Dry::Validation.Schema do
|
||||
required(:address).schema do
|
||||
|
@ -19,6 +19,6 @@ errors = schema.call({}).messages
|
|||
|
||||
puts errors.inspect
|
||||
|
||||
errors = schema.call(address: { city: 'NYC' }).messages
|
||||
errors = schema.call(address: {city: "NYC"}).messages
|
||||
|
||||
puts errors.inspect
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry-validation'
|
||||
require "dry-validation"
|
||||
|
||||
contract = Class.new(Dry::Validation::Contract) do
|
||||
params do
|
||||
|
@ -9,6 +9,6 @@ contract = Class.new(Dry::Validation::Contract) do
|
|||
end
|
||||
end.new
|
||||
|
||||
result = contract.('email' => '', 'age' => '19')
|
||||
result = contract.("email" => "", "age" => "19")
|
||||
|
||||
puts result.inspect
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/validation'
|
||||
require "dry/validation"
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/validation/constants'
|
||||
require 'dry/validation/contract'
|
||||
require 'dry/validation/macros'
|
||||
require "dry/validation/constants"
|
||||
require "dry/validation/contract"
|
||||
require "dry/validation/macros"
|
||||
|
||||
# Main namespace
|
||||
#
|
||||
|
@ -16,15 +16,15 @@ module Dry
|
|||
extend Macros::Registrar
|
||||
|
||||
register_extension(:monads) do
|
||||
require 'dry/validation/extensions/monads'
|
||||
require "dry/validation/extensions/monads"
|
||||
end
|
||||
|
||||
register_extension(:hints) do
|
||||
require 'dry/validation/extensions/hints'
|
||||
require "dry/validation/extensions/hints"
|
||||
end
|
||||
|
||||
register_extension(:predicates_as_macros) do
|
||||
require 'dry/validation/extensions/predicates_as_macros'
|
||||
require "dry/validation/extensions/predicates_as_macros"
|
||||
end
|
||||
|
||||
# Define a contract and build its instance
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/schema/config'
|
||||
require 'dry/validation/macros'
|
||||
require "dry/schema/config"
|
||||
require "dry/validation/macros"
|
||||
|
||||
module Dry
|
||||
module Validation
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'pathname'
|
||||
require 'dry/core/constants'
|
||||
require "pathname"
|
||||
require "dry/core/constants"
|
||||
|
||||
module Dry
|
||||
module Validation
|
||||
include Dry::Core::Constants
|
||||
|
||||
DOT = '.'
|
||||
DOT = "."
|
||||
|
||||
# Root path is used for base errors in hash representation of error messages
|
||||
ROOT_PATH = [nil].freeze
|
||||
|
||||
# Path to the default errors locale file
|
||||
DEFAULT_ERRORS_NAMESPACE = 'dry_validation'
|
||||
DEFAULT_ERRORS_NAMESPACE = "dry_validation"
|
||||
|
||||
# Path to the default errors locale file
|
||||
DEFAULT_ERRORS_PATH = Pathname(__FILE__).join('../../../../config/errors.yml').realpath.freeze
|
||||
DEFAULT_ERRORS_PATH = Pathname(__FILE__).join("../../../../config/errors.yml").realpath.freeze
|
||||
|
||||
# Mapping for block kwarg options used by block_options
|
||||
#
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'concurrent/map'
|
||||
require "concurrent/map"
|
||||
|
||||
require 'dry/equalizer'
|
||||
require 'dry/initializer'
|
||||
require 'dry/schema/path'
|
||||
require "dry/equalizer"
|
||||
require "dry/initializer"
|
||||
require "dry/schema/path"
|
||||
|
||||
require 'dry/validation/config'
|
||||
require 'dry/validation/constants'
|
||||
require 'dry/validation/rule'
|
||||
require 'dry/validation/evaluator'
|
||||
require 'dry/validation/messages/resolver'
|
||||
require 'dry/validation/result'
|
||||
require 'dry/validation/contract/class_interface'
|
||||
require "dry/validation/config"
|
||||
require "dry/validation/constants"
|
||||
require "dry/validation/rule"
|
||||
require "dry/validation/evaluator"
|
||||
require "dry/validation/messages/resolver"
|
||||
require "dry/validation/result"
|
||||
require "dry/validation/contract/class_interface"
|
||||
|
||||
module Dry
|
||||
module Validation
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/schema'
|
||||
require 'dry/schema/messages'
|
||||
require 'dry/schema/path'
|
||||
require 'dry/schema/key_map'
|
||||
require "dry/schema"
|
||||
require "dry/schema/messages"
|
||||
require "dry/schema/path"
|
||||
require "dry/schema/key_map"
|
||||
|
||||
require 'dry/validation/constants'
|
||||
require 'dry/validation/macros'
|
||||
require 'dry/validation/schema_ext'
|
||||
require "dry/validation/constants"
|
||||
require "dry/validation/macros"
|
||||
require "dry/validation/schema_ext"
|
||||
|
||||
module Dry
|
||||
module Validation
|
||||
|
@ -23,7 +23,7 @@ module Dry
|
|||
# @api private
|
||||
def inherited(klass)
|
||||
super
|
||||
klass.instance_variable_set('@config', config.dup)
|
||||
klass.instance_variable_set("@config", config.dup)
|
||||
end
|
||||
|
||||
# Configuration
|
||||
|
@ -190,7 +190,7 @@ module Dry
|
|||
|
||||
# @api private
|
||||
def core_schema_opts
|
||||
{ parent: superclass&.__schema__, config: config }
|
||||
{parent: superclass&.__schema__, config: config}
|
||||
end
|
||||
|
||||
# @api private
|
||||
|
@ -198,7 +198,7 @@ module Dry
|
|||
return __schema__ if external_schemas.empty? && block.nil?
|
||||
|
||||
unless __schema__.nil?
|
||||
raise ::Dry::Validation::DuplicateSchemaError, 'Schema has already been defined'
|
||||
raise ::Dry::Validation::DuplicateSchemaError, "Schema has already been defined"
|
||||
end
|
||||
|
||||
schema_opts = core_schema_opts
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/initializer'
|
||||
require 'dry/core/deprecations'
|
||||
require "dry/initializer"
|
||||
require "dry/core/deprecations"
|
||||
|
||||
require 'dry/validation/constants'
|
||||
require 'dry/validation/failures'
|
||||
require "dry/validation/constants"
|
||||
require "dry/validation/failures"
|
||||
|
||||
module Dry
|
||||
module Validation
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/monads/result'
|
||||
require "dry/monads/result"
|
||||
|
||||
module Dry
|
||||
module Validation
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/monads/result'
|
||||
require "dry/monads/result"
|
||||
|
||||
module Dry
|
||||
module Validation
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/schema/predicate_registry'
|
||||
require 'dry/validation/contract'
|
||||
require "dry/schema/predicate_registry"
|
||||
require "dry/validation/contract"
|
||||
|
||||
module Dry
|
||||
module Validation
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/schema/path'
|
||||
require 'dry/validation/constants'
|
||||
require "dry/schema/path"
|
||||
require "dry/validation/constants"
|
||||
|
||||
module Dry
|
||||
module Validation
|
||||
|
@ -57,7 +57,7 @@ module Dry
|
|||
#
|
||||
# @api public
|
||||
def failure(message, tokens = EMPTY_HASH)
|
||||
opts << { message: message, tokens: tokens, path: path }
|
||||
opts << {message: message, tokens: tokens, path: path}
|
||||
self
|
||||
end
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/initializer'
|
||||
require 'dry/validation/constants'
|
||||
require "dry/initializer"
|
||||
require "dry/validation/constants"
|
||||
|
||||
module Dry
|
||||
module Validation
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/validation/constants'
|
||||
require 'dry/validation/function'
|
||||
require "dry/validation/constants"
|
||||
require "dry/validation/function"
|
||||
|
||||
module Dry
|
||||
module Validation
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/container'
|
||||
require 'dry/validation/macro'
|
||||
require "dry/container"
|
||||
require "dry/validation/macro"
|
||||
|
||||
module Dry
|
||||
module Validation
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/equalizer'
|
||||
require "dry/equalizer"
|
||||
|
||||
require 'dry/schema/constants'
|
||||
require 'dry/schema/message'
|
||||
require "dry/schema/constants"
|
||||
require "dry/schema/message"
|
||||
|
||||
module Dry
|
||||
module Validation
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/schema/message_set'
|
||||
require "dry/schema/message_set"
|
||||
|
||||
require 'dry/validation/constants'
|
||||
require 'dry/validation/message'
|
||||
require "dry/validation/constants"
|
||||
require "dry/validation/message"
|
||||
|
||||
module Dry
|
||||
module Validation
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/validation/message'
|
||||
require "dry/validation/message"
|
||||
|
||||
module Dry
|
||||
module Validation
|
||||
|
@ -95,7 +95,7 @@ module Dry
|
|||
def parse_token(token)
|
||||
case token
|
||||
when Array
|
||||
token.join(', ')
|
||||
token.join(", ")
|
||||
else
|
||||
token
|
||||
end
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'concurrent/map'
|
||||
require 'dry/equalizer'
|
||||
require "concurrent/map"
|
||||
require "dry/equalizer"
|
||||
|
||||
require 'dry/validation/constants'
|
||||
require 'dry/validation/message_set'
|
||||
require 'dry/validation/values'
|
||||
require "dry/validation/constants"
|
||||
require "dry/validation/message_set"
|
||||
require "dry/validation/values"
|
||||
|
||||
module Dry
|
||||
module Validation
|
||||
|
@ -179,7 +179,7 @@ module Dry
|
|||
super
|
||||
end
|
||||
|
||||
if RUBY_VERSION >= '2.7'
|
||||
if RUBY_VERSION >= "2.7"
|
||||
# Pattern matching
|
||||
#
|
||||
# @api private
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/equalizer'
|
||||
require "dry/equalizer"
|
||||
|
||||
require 'dry/validation/constants'
|
||||
require 'dry/validation/function'
|
||||
require "dry/validation/constants"
|
||||
require "dry/validation/function"
|
||||
|
||||
module Dry
|
||||
module Validation
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/schema/path'
|
||||
require "dry/schema/path"
|
||||
|
||||
module Dry
|
||||
module Schema
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/equalizer'
|
||||
require 'dry/schema/path'
|
||||
require 'dry/validation/constants'
|
||||
require "dry/equalizer"
|
||||
require "dry/schema/path"
|
||||
require "dry/validation/constants"
|
||||
|
||||
module Dry
|
||||
module Validation
|
||||
|
@ -53,7 +53,7 @@ module Dry
|
|||
vals = self.class.new(data.dig(*keys))
|
||||
vals.fetch_values(*last) { nil }
|
||||
else
|
||||
raise ArgumentError, '+key+ must be a valid path specification'
|
||||
raise ArgumentError, "+key+ must be a valid path specification"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -2,6 +2,6 @@
|
|||
|
||||
module Dry
|
||||
module Validation
|
||||
VERSION = '1.4.2'
|
||||
VERSION = "1.4.2"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -10,53 +10,53 @@ RSpec.describe Dry::Validation::Result do
|
|||
end
|
||||
|
||||
rule(:name) do
|
||||
key.failure('oops') if values[:name] != 'Jane'
|
||||
key.failure("oops") if values[:name] != "Jane"
|
||||
end
|
||||
end.new
|
||||
end
|
||||
|
||||
let(:result) { schema.(input) }
|
||||
|
||||
context 'with valid input' do
|
||||
let(:input) { { name: 'Jane' } }
|
||||
context "with valid input" do
|
||||
let(:input) { {name: "Jane"} }
|
||||
|
||||
describe '#success?' do
|
||||
it 'returns true' do
|
||||
describe "#success?" do
|
||||
it "returns true" do
|
||||
expect(result).to be_success
|
||||
end
|
||||
end
|
||||
|
||||
describe '#hints' do
|
||||
it 'returns an empty array' do
|
||||
describe "#hints" do
|
||||
it "returns an empty array" do
|
||||
expect(result.hints).to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with invalid input' do
|
||||
let(:input) { { name: '' } }
|
||||
context "with invalid input" do
|
||||
let(:input) { {name: ""} }
|
||||
|
||||
describe '#failure?' do
|
||||
it 'returns true' do
|
||||
describe "#failure?" do
|
||||
it "returns true" do
|
||||
expect(result).to be_failure
|
||||
end
|
||||
end
|
||||
|
||||
describe '#hints' do
|
||||
it 'returns hint messages excluding errors' do
|
||||
expect(result.hints.to_h).to eql(name: ['length must be within 2 - 4'])
|
||||
describe "#hints" do
|
||||
it "returns hint messages excluding errors" do
|
||||
expect(result.hints.to_h).to eql(name: ["length must be within 2 - 4"])
|
||||
end
|
||||
end
|
||||
|
||||
describe '#messages' do
|
||||
it 'returns hints + error messages' do
|
||||
expect(result.messages.to_h).to eql(name: ['must be filled', 'length must be within 2 - 4'])
|
||||
describe "#messages" do
|
||||
it "returns hints + error messages" do
|
||||
expect(result.messages.to_h).to eql(name: ["must be filled", "length must be within 2 - 4"])
|
||||
end
|
||||
end
|
||||
|
||||
describe '#errors' do
|
||||
it 'returns errors excluding hints' do
|
||||
expect(result.errors.to_h).to eql(name: ['must be filled'])
|
||||
describe "#errors" do
|
||||
it "returns errors excluding hints" do
|
||||
expect(result.errors.to_h).to eql(name: ["must be filled"])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,11 +13,11 @@ RSpec.describe Dry::Validation::Result do
|
|||
|
||||
let(:result) { schema.(input) }
|
||||
|
||||
context 'with valid input' do
|
||||
let(:input) { { name: 'Jane' } }
|
||||
context "with valid input" do
|
||||
let(:input) { {name: "Jane"} }
|
||||
|
||||
describe '#to_monad' do
|
||||
it 'returns a Success value' do
|
||||
describe "#to_monad" do
|
||||
it "returns a Success value" do
|
||||
monad = result.to_monad
|
||||
|
||||
expect(monad).to be_a Dry::Monads::Result
|
||||
|
@ -27,11 +27,11 @@ RSpec.describe Dry::Validation::Result do
|
|||
end
|
||||
end
|
||||
|
||||
context 'with invalid input' do
|
||||
let(:input) { { name: '' } }
|
||||
context "with invalid input" do
|
||||
let(:input) { {name: ""} }
|
||||
|
||||
describe '#to_monad' do
|
||||
it 'returns a Failure value' do
|
||||
describe "#to_monad" do
|
||||
it "returns a Failure value" do
|
||||
monad = result.to_monad
|
||||
|
||||
expect(monad).to be_a_failure
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/validation/extensions/predicates_as_macros'
|
||||
require "dry/validation/extensions/predicates_as_macros"
|
||||
|
||||
RSpec.describe Dry::Validation::Contract do
|
||||
context 'with predicates_as_macros extension' do
|
||||
context "with predicates_as_macros extension" do
|
||||
before { Dry::Validation.load_extensions(:predicates_as_macros) }
|
||||
|
||||
subject(:contract) do
|
||||
|
@ -26,7 +26,7 @@ RSpec.describe Dry::Validation::Contract do
|
|||
end
|
||||
end
|
||||
|
||||
it 'macros succeed on predicate success' do
|
||||
it "macros succeed on predicate success" do
|
||||
age_contract = Class.new(contract) do
|
||||
schema do
|
||||
required(:age).filled(:integer)
|
||||
|
@ -38,7 +38,7 @@ RSpec.describe Dry::Validation::Contract do
|
|||
expect(age_contract.(age: 19)).to be_success
|
||||
end
|
||||
|
||||
it 'macros fail on predicate failure' do
|
||||
it "macros fail on predicate failure" do
|
||||
age_contract = Class.new(contract) do
|
||||
schema do
|
||||
required(:age).filled(:integer)
|
||||
|
@ -50,7 +50,7 @@ RSpec.describe Dry::Validation::Contract do
|
|||
expect(age_contract.(age: 17)).to be_failure
|
||||
end
|
||||
|
||||
it 'failure message is built from predicate name and arguments' do
|
||||
it "failure message is built from predicate name and arguments" do
|
||||
age_contract = Class.new(contract) do
|
||||
schema do
|
||||
required(:age).filled(:integer)
|
||||
|
@ -63,7 +63,7 @@ RSpec.describe Dry::Validation::Contract do
|
|||
|
||||
expect(
|
||||
result.errors.first.text
|
||||
).to eq('must be greater than or equal to 18')
|
||||
).to eq("must be greater than or equal to 18")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/validation/contract'
|
||||
require "dry/validation/contract"
|
||||
|
||||
RSpec.describe Dry::Validation::Contract, '#call' do
|
||||
RSpec.describe Dry::Validation::Contract, "#call" do
|
||||
subject(:contract) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
def self.name
|
||||
'TestContract'
|
||||
"TestContract"
|
||||
end
|
||||
|
||||
params do
|
||||
|
@ -27,111 +27,111 @@ RSpec.describe Dry::Validation::Contract, '#call' do
|
|||
|
||||
rule(:login) do
|
||||
if key?
|
||||
key.failure('too short') if value.length < 3
|
||||
key.failure("too short") if value.length < 3
|
||||
end
|
||||
end
|
||||
|
||||
rule(address: { geolocation: [:lon, :lat] }) do
|
||||
rule(address: {geolocation: [:lon, :lat]}) do
|
||||
if key?
|
||||
lon, lat = value
|
||||
key('address.geolocation.lat').failure('invalid') if lat < 10
|
||||
key('address.geolocation.lon').failure('invalid') if lon < 10
|
||||
key("address.geolocation.lat").failure("invalid") if lat < 10
|
||||
key("address.geolocation.lon").failure("invalid") if lon < 10
|
||||
end
|
||||
end
|
||||
|
||||
rule(:password) do
|
||||
key.failure('is required') if values[:login] && !values[:password]
|
||||
key.failure("is required") if values[:login] && !values[:password]
|
||||
end
|
||||
|
||||
rule(:age) do
|
||||
key.failure('must be greater or equal 18') if value < 18
|
||||
key.failure("must be greater or equal 18") if value < 18
|
||||
end
|
||||
|
||||
rule(:age) do
|
||||
key.failure('must be greater than 0') if value < 0
|
||||
key.failure("must be greater than 0") if value < 0
|
||||
end
|
||||
|
||||
rule(address: :zip) do
|
||||
address = values[:address]
|
||||
if address && address[:country] == 'Russia' && address[:zip] != /\A\d{6}\z/
|
||||
key.failure('must have 6 digit')
|
||||
if address && address[:country] == "Russia" && address[:zip] != /\A\d{6}\z/
|
||||
key.failure("must have 6 digit")
|
||||
end
|
||||
end
|
||||
|
||||
rule('address.geolocation.lon') do
|
||||
key.failure('invalid longitude') if key? && !(-180.0...180.0).cover?(value)
|
||||
rule("address.geolocation.lon") do
|
||||
key.failure("invalid longitude") if key? && !(-180.0...180.0).cover?(value)
|
||||
end
|
||||
end.new
|
||||
end
|
||||
|
||||
it 'applies rule to input processed by the schema' do
|
||||
result = contract.(email: 'john@doe.org', age: 19)
|
||||
it "applies rule to input processed by the schema" do
|
||||
result = contract.(email: "john@doe.org", age: 19)
|
||||
|
||||
expect(result).to be_success
|
||||
expect(result.errors.to_h).to eql({})
|
||||
end
|
||||
|
||||
it 'applies rule to an optional field when value is present' do
|
||||
result = contract.(email: 'john@doe.org', age: 19, login: 'ab')
|
||||
it "applies rule to an optional field when value is present" do
|
||||
result = contract.(email: "john@doe.org", age: 19, login: "ab")
|
||||
|
||||
expect(result).to be_failure
|
||||
expect(result.errors.to_h).to eql(login: ['too short'], password: ['is required'])
|
||||
expect(result.errors.to_h).to eql(login: ["too short"], password: ["is required"])
|
||||
end
|
||||
|
||||
it 'applies rule to an optional nested field when value is present' do
|
||||
it "applies rule to an optional nested field when value is present" do
|
||||
result = contract.(
|
||||
email: 'john@doe.org',
|
||||
email: "john@doe.org",
|
||||
age: 19,
|
||||
address: {
|
||||
geolocation: { lat: 11, lon: 1 },
|
||||
country: 'Poland',
|
||||
zip: '12345'
|
||||
geolocation: {lat: 11, lon: 1},
|
||||
country: "Poland",
|
||||
zip: "12345"
|
||||
}
|
||||
)
|
||||
|
||||
expect(result).to be_failure
|
||||
expect(result.errors.to_h).to eql(address: { geolocation: { lon: ['invalid'] } })
|
||||
expect(result.errors.to_h).to eql(address: {geolocation: {lon: ["invalid"]}})
|
||||
end
|
||||
|
||||
it 'returns rule errors' do
|
||||
result = contract.(email: 'john@doe.org', login: 'jane', age: 19)
|
||||
it "returns rule errors" do
|
||||
result = contract.(email: "john@doe.org", login: "jane", age: 19)
|
||||
|
||||
expect(result).to be_failure
|
||||
expect(result.errors.to_h).to eql(password: ['is required'])
|
||||
expect(result.errors.to_h).to eql(password: ["is required"])
|
||||
end
|
||||
|
||||
it "doesn't execute rules when basic checks failed" do
|
||||
result = contract.(email: 'john@doe.org', age: 'not-an-integer')
|
||||
result = contract.(email: "john@doe.org", age: "not-an-integer")
|
||||
|
||||
expect(result).to be_failure
|
||||
expect(result.errors.to_h).to eql(age: ['must be an integer'])
|
||||
expect(result.errors.to_h).to eql(age: ["must be an integer"])
|
||||
end
|
||||
|
||||
it 'gathers errors from multiple rules for the same key' do
|
||||
result = contract.(email: 'john@doe.org', age: -1)
|
||||
it "gathers errors from multiple rules for the same key" do
|
||||
result = contract.(email: "john@doe.org", age: -1)
|
||||
|
||||
expect(result).to be_failure
|
||||
expect(result.errors.to_h).to eql(age: ['must be greater or equal 18', 'must be greater than 0'])
|
||||
expect(result.errors.to_h).to eql(age: ["must be greater or equal 18", "must be greater than 0"])
|
||||
end
|
||||
|
||||
it 'builds nested message keys for nested rules' do
|
||||
result = contract.(email: 'john@doe.org', age: 20, address: { country: 'Russia', zip: 'abc' })
|
||||
it "builds nested message keys for nested rules" do
|
||||
result = contract.(email: "john@doe.org", age: 20, address: {country: "Russia", zip: "abc"})
|
||||
|
||||
expect(result).to be_failure
|
||||
expect(result.errors.to_h).to eql(address: { zip: ['must have 6 digit'] })
|
||||
expect(result.errors.to_h).to eql(address: {zip: ["must have 6 digit"]})
|
||||
end
|
||||
|
||||
it 'builds deeply nested messages for deeply nested rules' do
|
||||
it "builds deeply nested messages for deeply nested rules" do
|
||||
result = contract.(
|
||||
email: 'john@doe.org',
|
||||
email: "john@doe.org",
|
||||
age: 20,
|
||||
address: {
|
||||
country: 'UK', zip: 'irrelevant',
|
||||
geolocation: { lon: '365', lat: '78' }
|
||||
country: "UK", zip: "irrelevant",
|
||||
geolocation: {lon: "365", lat: "78"}
|
||||
}
|
||||
)
|
||||
|
||||
expect(result).to be_failure
|
||||
expect(result.errors.to_h).to eql(address: { geolocation: { lon: ['invalid longitude'] } })
|
||||
expect(result.errors.to_h).to eql(address: {geolocation: {lon: ["invalid longitude"]}})
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/validation/contract'
|
||||
require "dry/validation/contract"
|
||||
|
||||
RSpec.describe Dry::Validation, '.Contract' do
|
||||
RSpec.describe Dry::Validation, ".Contract" do
|
||||
subject(:contract) do
|
||||
Dry::Validation.Contract do
|
||||
params do
|
||||
|
@ -11,7 +11,7 @@ RSpec.describe Dry::Validation, '.Contract' do
|
|||
end
|
||||
end
|
||||
|
||||
it 'returns an instance of Dry::Validation::Contract' do
|
||||
it "returns an instance of Dry::Validation::Contract" do
|
||||
expect(contract).to be_a(Dry::Validation::Contract)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/validation/contract'
|
||||
require "dry/validation/contract"
|
||||
|
||||
RSpec.describe Dry::Validation::Contract, 'setting default locale' do
|
||||
RSpec.describe Dry::Validation::Contract, "setting default locale" do
|
||||
subject(:contract) do
|
||||
Dry::Validation.Contract do
|
||||
config.messages.default_locale = :pl
|
||||
config.messages.backend = :i18n
|
||||
config.messages.load_paths << SPEC_ROOT.join('fixtures/messages/errors.pl.yml')
|
||||
config.messages.load_paths << SPEC_ROOT.join("fixtures/messages/errors.pl.yml")
|
||||
|
||||
params do
|
||||
required(:email).filled(:string)
|
||||
end
|
||||
|
||||
rule(:email) do
|
||||
key.failure(:invalid) unless values[:email].include?('@')
|
||||
key.failure(:invalid) unless values[:email].include?("@")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'uses configured default locale' do
|
||||
expect(contract.(email: 'foo').errors.to_h).to eql(email: ['oh nie zły email'])
|
||||
it "uses configured default locale" do
|
||||
expect(contract.(email: "foo").errors.to_h).to eql(email: ["oh nie zły email"])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/validation/contract'
|
||||
require "dry/validation/contract"
|
||||
|
||||
RSpec.describe Dry::Validation::Contract, '.json' do
|
||||
RSpec.describe Dry::Validation::Contract, ".json" do
|
||||
subject(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
json do
|
||||
|
@ -11,19 +11,19 @@ RSpec.describe Dry::Validation::Contract, '.json' do
|
|||
end
|
||||
end
|
||||
|
||||
it 'defines a JSON schema' do
|
||||
it "defines a JSON schema" do
|
||||
expect(contract_class.schema).to be_a(Dry::Schema::JSON)
|
||||
expect(contract_class.json).to be_a(Dry::Schema::JSON)
|
||||
|
||||
expect(contract_class.schema).to be(contract_class.json)
|
||||
end
|
||||
|
||||
it 'returns nil if schema is not defined' do
|
||||
it "returns nil if schema is not defined" do
|
||||
contract_class = Class.new(Dry::Validation::Contract)
|
||||
expect(contract_class.schema).to be(nil)
|
||||
end
|
||||
|
||||
it 'raises an error if schema is already defined' do
|
||||
it "raises an error if schema is already defined" do
|
||||
expect do
|
||||
contract_class.json do
|
||||
required(:login).filled(:string)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/validation/contract'
|
||||
require "dry/validation/contract"
|
||||
|
||||
RSpec.describe Dry::Validation::Contract, '.params' do
|
||||
RSpec.describe Dry::Validation::Contract, ".params" do
|
||||
subject(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
params do
|
||||
|
@ -11,19 +11,19 @@ RSpec.describe Dry::Validation::Contract, '.params' do
|
|||
end
|
||||
end
|
||||
|
||||
it 'defines a Params schema' do
|
||||
it "defines a Params schema" do
|
||||
expect(contract_class.schema).to be_a(Dry::Schema::Params)
|
||||
expect(contract_class.params).to be_a(Dry::Schema::Params)
|
||||
|
||||
expect(contract_class.schema).to be(contract_class.params)
|
||||
end
|
||||
|
||||
it 'returns nil if schema is not defined' do
|
||||
it "returns nil if schema is not defined" do
|
||||
contract_class = Class.new(Dry::Validation::Contract)
|
||||
expect(contract_class.schema).to be(nil)
|
||||
end
|
||||
|
||||
it 'raises an error if schema is already defined' do
|
||||
it "raises an error if schema is already defined" do
|
||||
expect do
|
||||
contract_class.params do
|
||||
required(:login).filled(:string)
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/validation/contract'
|
||||
require "dry/validation/contract"
|
||||
|
||||
RSpec.describe Dry::Validation::Contract, 'Rule#each' do
|
||||
RSpec.describe Dry::Validation::Contract, "Rule#each" do
|
||||
subject(:contract) { contract_class.new }
|
||||
|
||||
context 'using a block' do
|
||||
context "using a block" do
|
||||
let(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
def self.name
|
||||
'TestContract'
|
||||
"TestContract"
|
||||
end
|
||||
|
||||
params do
|
||||
|
@ -20,11 +20,11 @@ RSpec.describe Dry::Validation::Contract, 'Rule#each' do
|
|||
end
|
||||
|
||||
rule(:nums).each do
|
||||
key.failure('invalid') if value < 3
|
||||
key.failure("invalid") if value < 3
|
||||
end
|
||||
|
||||
rule(hash: :another_nums).each do
|
||||
key.failure('invalid') if value < 3
|
||||
key.failure("invalid") if value < 3
|
||||
end
|
||||
|
||||
rule(:nums).each do |context:|
|
||||
|
@ -34,34 +34,34 @@ RSpec.describe Dry::Validation::Contract, 'Rule#each' do
|
|||
end
|
||||
end
|
||||
|
||||
it 'applies rule only when the value is an array' do
|
||||
expect(contract.(nums: 'oops').errors.to_h).to eql(nums: ['must be an array'])
|
||||
it "applies rule only when the value is an array" do
|
||||
expect(contract.(nums: "oops").errors.to_h).to eql(nums: ["must be an array"])
|
||||
end
|
||||
|
||||
it 'applies rule when an item passed schema checks' do
|
||||
expect(contract.(nums: ['oops', 1, 4, 0]).errors.to_h)
|
||||
.to eql(nums: { 0 => ['must be an integer'], 1 => ['invalid'], 3 => ['invalid'] })
|
||||
it "applies rule when an item passed schema checks" do
|
||||
expect(contract.(nums: ["oops", 1, 4, 0]).errors.to_h)
|
||||
.to eql(nums: {0 => ["must be an integer"], 1 => ["invalid"], 3 => ["invalid"]})
|
||||
end
|
||||
|
||||
it 'applies rule to nested values when an item passed schema checks' do
|
||||
expect(contract.(nums: [4], hash: { another_nums: ['oops', 1, 4] }).errors.to_h)
|
||||
.to eql(hash: { another_nums: { 0 => ['must be an integer'], 1 => ['invalid'] } })
|
||||
it "applies rule to nested values when an item passed schema checks" do
|
||||
expect(contract.(nums: [4], hash: {another_nums: ["oops", 1, 4]}).errors.to_h)
|
||||
.to eql(hash: {another_nums: {0 => ["must be an integer"], 1 => ["invalid"]}})
|
||||
end
|
||||
|
||||
it 'passes block options' do
|
||||
it "passes block options" do
|
||||
expect(contract.(nums: [10, 20]).context[:sum]).to eql(30)
|
||||
end
|
||||
end
|
||||
|
||||
context 'using a simple macro' do
|
||||
context "using a simple macro" do
|
||||
let(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
def self.name
|
||||
'TestContract'
|
||||
"TestContract"
|
||||
end
|
||||
|
||||
register_macro(:even?) do
|
||||
key.failure('invalid') unless value.even?
|
||||
key.failure("invalid") unless value.even?
|
||||
end
|
||||
|
||||
params do
|
||||
|
@ -72,34 +72,34 @@ RSpec.describe Dry::Validation::Contract, 'Rule#each' do
|
|||
end
|
||||
|
||||
rule(:nums).each(:even?)
|
||||
rule('hash.another_nums').each(:even?)
|
||||
rule("hash.another_nums").each(:even?)
|
||||
end
|
||||
end
|
||||
|
||||
it 'applies rule when an item passed schema checks' do
|
||||
it "applies rule when an item passed schema checks" do
|
||||
expect(contract.(nums: [2, 3]).errors.to_h)
|
||||
.to eql(nums: { 1 => ['invalid'] })
|
||||
.to eql(nums: {1 => ["invalid"]})
|
||||
end
|
||||
|
||||
it 'applies rule to nested values when an item passed schema checks' do
|
||||
expect(contract.(nums: [4], hash: { another_nums: [2, 3] }).errors.to_h)
|
||||
.to eql(hash: { another_nums: { 1 => ['invalid'] } })
|
||||
it "applies rule to nested values when an item passed schema checks" do
|
||||
expect(contract.(nums: [4], hash: {another_nums: [2, 3]}).errors.to_h)
|
||||
.to eql(hash: {another_nums: {1 => ["invalid"]}})
|
||||
end
|
||||
end
|
||||
|
||||
context 'using multiple macros' do
|
||||
context "using multiple macros" do
|
||||
let(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
def self.name
|
||||
'TestContract'
|
||||
"TestContract"
|
||||
end
|
||||
|
||||
register_macro(:even?) do
|
||||
key.failure('invalid') unless value.even?
|
||||
key.failure("invalid") unless value.even?
|
||||
end
|
||||
|
||||
register_macro(:below_ten?) do
|
||||
key.failure('too big') unless value < 10
|
||||
key.failure("too big") unless value < 10
|
||||
end
|
||||
|
||||
params do
|
||||
|
@ -114,27 +114,27 @@ RSpec.describe Dry::Validation::Contract, 'Rule#each' do
|
|||
end
|
||||
end
|
||||
|
||||
it 'applies rules when an item passed schema checks' do
|
||||
it "applies rules when an item passed schema checks" do
|
||||
expect(contract.(nums: [2, 15]).errors.to_h)
|
||||
.to eql(nums: { 1 => ['invalid', 'too big'] })
|
||||
.to eql(nums: {1 => ["invalid", "too big"]})
|
||||
end
|
||||
|
||||
it 'applies rules for nested values when an item passed schema checks' do
|
||||
expect(contract.(nums: [2], hash: { another_nums: [2, 15] }).errors.to_h)
|
||||
.to eql(hash: { another_nums: { 1 => ['invalid', 'too big'] } })
|
||||
it "applies rules for nested values when an item passed schema checks" do
|
||||
expect(contract.(nums: [2], hash: {another_nums: [2, 15]}).errors.to_h)
|
||||
.to eql(hash: {another_nums: {1 => ["invalid", "too big"]}})
|
||||
end
|
||||
end
|
||||
|
||||
context 'using a macro with args' do
|
||||
context "using a macro with args" do
|
||||
let(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
def self.name
|
||||
'TestContract'
|
||||
"TestContract"
|
||||
end
|
||||
|
||||
register_macro(:min) do |macro:|
|
||||
min = macro.args[0]
|
||||
key.failure('invalid') if value < min
|
||||
key.failure("invalid") if value < min
|
||||
end
|
||||
|
||||
params do
|
||||
|
@ -149,27 +149,27 @@ RSpec.describe Dry::Validation::Contract, 'Rule#each' do
|
|||
end
|
||||
end
|
||||
|
||||
it 'applies rule when an item passed schema checks' do
|
||||
expect(contract.(nums: ['oops', 1, 4, 0]).errors.to_h)
|
||||
.to eql(nums: { 0 => ['must be an integer'], 1 => ['invalid'], 3 => ['invalid'] })
|
||||
it "applies rule when an item passed schema checks" do
|
||||
expect(contract.(nums: ["oops", 1, 4, 0]).errors.to_h)
|
||||
.to eql(nums: {0 => ["must be an integer"], 1 => ["invalid"], 3 => ["invalid"]})
|
||||
end
|
||||
|
||||
it 'applies rule to nested values when an item passed schema checks' do
|
||||
expect(contract.(nums: [4], hash: { another_nums: ['oops', 1, 4] }).errors.to_h)
|
||||
.to eql(hash: { another_nums: { 0 => ['must be an integer'], 1 => ['invalid'] } })
|
||||
it "applies rule to nested values when an item passed schema checks" do
|
||||
expect(contract.(nums: [4], hash: {another_nums: ["oops", 1, 4]}).errors.to_h)
|
||||
.to eql(hash: {another_nums: {0 => ["must be an integer"], 1 => ["invalid"]}})
|
||||
end
|
||||
end
|
||||
|
||||
context 'using a macro with multiple args' do
|
||||
context "using a macro with multiple args" do
|
||||
let(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
def self.name
|
||||
'TestContract'
|
||||
"TestContract"
|
||||
end
|
||||
|
||||
register_macro(:between) do |macro:|
|
||||
min, max = macro.args[0..1]
|
||||
key.failure('invalid') unless (min..max).cover?(value)
|
||||
key.failure("invalid") unless (min..max).cover?(value)
|
||||
end
|
||||
|
||||
params do
|
||||
|
@ -184,32 +184,32 @@ RSpec.describe Dry::Validation::Contract, 'Rule#each' do
|
|||
end
|
||||
end
|
||||
|
||||
it 'applies rule when an item passed schema checks' do
|
||||
expect(contract.(nums: ['oops', 4, 0, 6]).errors.to_h)
|
||||
.to eql(nums: { 0 => ['must be an integer'], 2 => ['invalid'], 3 => ['invalid'] })
|
||||
it "applies rule when an item passed schema checks" do
|
||||
expect(contract.(nums: ["oops", 4, 0, 6]).errors.to_h)
|
||||
.to eql(nums: {0 => ["must be an integer"], 2 => ["invalid"], 3 => ["invalid"]})
|
||||
end
|
||||
|
||||
it 'applies rule with nested values when an item passed schema checks' do
|
||||
expect(contract.(nums: [4], hash: { another_nums: ['oops', 4, 0] }).errors.to_h)
|
||||
.to eql(hash: { another_nums: { 0 => ['must be an integer'], 2 => ['invalid'] } })
|
||||
it "applies rule with nested values when an item passed schema checks" do
|
||||
expect(contract.(nums: [4], hash: {another_nums: ["oops", 4, 0]}).errors.to_h)
|
||||
.to eql(hash: {another_nums: {0 => ["must be an integer"], 2 => ["invalid"]}})
|
||||
end
|
||||
end
|
||||
|
||||
context 'using multiple macros with args' do
|
||||
context "using multiple macros with args" do
|
||||
let(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
def self.name
|
||||
'TestContract'
|
||||
"TestContract"
|
||||
end
|
||||
|
||||
register_macro(:min) do |macro:|
|
||||
min = macro.args[0]
|
||||
key.failure('invalid') if value < min
|
||||
key.failure("invalid") if value < min
|
||||
end
|
||||
|
||||
register_macro(:max) do |macro:|
|
||||
max = macro.args[0]
|
||||
key.failure('invalid') if value > max
|
||||
key.failure("invalid") if value > max
|
||||
end
|
||||
|
||||
params do
|
||||
|
@ -224,14 +224,14 @@ RSpec.describe Dry::Validation::Contract, 'Rule#each' do
|
|||
end
|
||||
end
|
||||
|
||||
it 'applies rules when an item passed schema checks' do
|
||||
expect(contract.(nums: ['oops', 4, 0, 6]).errors.to_h)
|
||||
.to eql(nums: { 0 => ['must be an integer'], 2 => ['invalid'], 3 => ['invalid'] })
|
||||
it "applies rules when an item passed schema checks" do
|
||||
expect(contract.(nums: ["oops", 4, 0, 6]).errors.to_h)
|
||||
.to eql(nums: {0 => ["must be an integer"], 2 => ["invalid"], 3 => ["invalid"]})
|
||||
end
|
||||
|
||||
it 'applies rules for nested values when an item passed schema checks' do
|
||||
expect(contract.(nums: [4], hash: { another_nums: ['oops', 4, 0] }).errors.to_h)
|
||||
.to eql(hash: { another_nums: { 0 => ['must be an integer'], 2 => ['invalid'] } })
|
||||
it "applies rules for nested values when an item passed schema checks" do
|
||||
expect(contract.(nums: [4], hash: {another_nums: ["oops", 4, 0]}).errors.to_h)
|
||||
.to eql(hash: {another_nums: {0 => ["must be an integer"], 2 => ["invalid"]}})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/validation/contract'
|
||||
require "dry/validation/contract"
|
||||
|
||||
RSpec.describe Dry::Validation::Contract, '.rule' do
|
||||
RSpec.describe Dry::Validation::Contract, ".rule" do
|
||||
subject(:contract) { contract_class.new }
|
||||
|
||||
context 'with a nested hash' do
|
||||
context "with a nested hash" do
|
||||
let(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
params do
|
||||
|
@ -18,30 +18,30 @@ RSpec.describe Dry::Validation::Contract, '.rule' do
|
|||
end
|
||||
|
||||
rule(:email) do
|
||||
key.failure('invalid email') unless value.include?('@')
|
||||
key.failure("invalid email") unless value.include?("@")
|
||||
end
|
||||
|
||||
rule('address.zipcode') do
|
||||
key.failure('bad format') unless value.include?('-')
|
||||
rule("address.zipcode") do
|
||||
key.failure("bad format") unless value.include?("-")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when nested values fail both schema and rule checks' do
|
||||
it 'produces schema and rule errors' do
|
||||
expect(contract.(email: 'jane@doe.org', address: { city: 'NYC', zipcode: '123' }).errors.to_h)
|
||||
.to eql(address: { street: ['is missing'], zipcode: ['bad format'] })
|
||||
context "when nested values fail both schema and rule checks" do
|
||||
it "produces schema and rule errors" do
|
||||
expect(contract.(email: "jane@doe.org", address: {city: "NYC", zipcode: "123"}).errors.to_h)
|
||||
.to eql(address: {street: ["is missing"], zipcode: ["bad format"]})
|
||||
end
|
||||
end
|
||||
|
||||
context 'when empty hash is provided' do
|
||||
it 'produces missing-key errors' do
|
||||
expect(contract.({}).errors.to_h).to eql(email: ['is missing'], address: ['is missing'])
|
||||
context "when empty hash is provided" do
|
||||
it "produces missing-key errors" do
|
||||
expect(contract.({}).errors.to_h).to eql(email: ["is missing"], address: ["is missing"])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a rule that depends on two nested values' do
|
||||
context "with a rule that depends on two nested values" do
|
||||
let(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
params do
|
||||
|
@ -52,19 +52,19 @@ RSpec.describe Dry::Validation::Contract, '.rule' do
|
|||
end
|
||||
|
||||
rule(event: %i[active_from active_until]) do
|
||||
key.failure('invalid dates') if value[0] < value[1]
|
||||
key.failure("invalid dates") if value[0] < value[1]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'does not execute rule when the schema checks failed' do
|
||||
result = contract.(event: { active_from: Date.today, active_until: nil })
|
||||
it "does not execute rule when the schema checks failed" do
|
||||
result = contract.(event: {active_from: Date.today, active_until: nil})
|
||||
|
||||
expect(result.errors.to_h).to eql(event: { active_until: ['must be a date'] })
|
||||
expect(result.errors.to_h).to eql(event: {active_until: ["must be a date"]})
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a nested array' do
|
||||
context "with a nested array" do
|
||||
let(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
params do
|
||||
|
@ -73,21 +73,21 @@ RSpec.describe Dry::Validation::Contract, '.rule' do
|
|||
end
|
||||
end
|
||||
|
||||
rule('address.phones').each do
|
||||
key.failure('invalid phone') unless value.start_with?('+48')
|
||||
rule("address.phones").each do
|
||||
key.failure("invalid phone") unless value.start_with?("+48")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when one of the values fails' do
|
||||
it 'produces an error for the invalid value' do
|
||||
expect(contract.(address: { phones: ['+48123', '+47412', nil] }).errors.to_h)
|
||||
.to eql(address: { phones: { 1 => ['invalid phone'], 2 => ['must be a string'] } })
|
||||
context "when one of the values fails" do
|
||||
it "produces an error for the invalid value" do
|
||||
expect(contract.(address: {phones: ["+48123", "+47412", nil]}).errors.to_h)
|
||||
.to eql(address: {phones: {1 => ["invalid phone"], 2 => ["must be a string"]}})
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a path intersection' do
|
||||
context 'when the longest path is a first' do
|
||||
context "with a path intersection" do
|
||||
context "when the longest path is a first" do
|
||||
let(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
params do
|
||||
|
@ -97,19 +97,19 @@ RSpec.describe Dry::Validation::Contract, '.rule' do
|
|||
end
|
||||
|
||||
rule(:addresses).each do
|
||||
key(path.keys + [:phone]).failure('invalid phone')
|
||||
key.failure('invalid list')
|
||||
key(path.keys + [:phone]).failure("invalid phone")
|
||||
key.failure("invalid list")
|
||||
end
|
||||
end
|
||||
|
||||
it 'produces an error for all paths' do
|
||||
expect(contract.(addresses: [{ phone: '+48123' }]).errors.to_h)
|
||||
.to eql(addresses: { 0 => [['invalid list'], [{ phone: 'invalid phone' }]] })
|
||||
it "produces an error for all paths" do
|
||||
expect(contract.(addresses: [{phone: "+48123"}]).errors.to_h)
|
||||
.to eql(addresses: {0 => [["invalid list"], [{phone: "invalid phone"}]]})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the longest path is a last' do
|
||||
context "when the longest path is a last" do
|
||||
let(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
params do
|
||||
|
@ -119,14 +119,14 @@ RSpec.describe Dry::Validation::Contract, '.rule' do
|
|||
end
|
||||
|
||||
rule(:addresses).each do
|
||||
key.failure('invalid list')
|
||||
key(path.keys + [:phone]).failure('invalid phone')
|
||||
key.failure("invalid list")
|
||||
key(path.keys + [:phone]).failure("invalid phone")
|
||||
end
|
||||
end
|
||||
|
||||
it 'produces an error for all paths' do
|
||||
expect(contract.(addresses: [{ phone: '+48123' }]).errors.to_h)
|
||||
.to eql(addresses: { 0 => [['invalid list'], [{ phone: 'invalid phone' }]] })
|
||||
it "produces an error for all paths" do
|
||||
expect(contract.(addresses: [{phone: "+48123"}]).errors.to_h)
|
||||
.to eql(addresses: {0 => [["invalid list"], [{phone: "invalid phone"}]]})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/validation/contract'
|
||||
require "dry/validation/contract"
|
||||
|
||||
RSpec.describe Dry::Validation::Contract, 'Rule#validate' do
|
||||
RSpec.describe Dry::Validation::Contract, "Rule#validate" do
|
||||
subject(:contract) { contract_class.new }
|
||||
|
||||
context 'using a block' do
|
||||
context "using a block" do
|
||||
let(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
def self.name
|
||||
'TestContract'
|
||||
"TestContract"
|
||||
end
|
||||
|
||||
params do
|
||||
|
@ -17,26 +17,26 @@ RSpec.describe Dry::Validation::Contract, 'Rule#validate' do
|
|||
end
|
||||
|
||||
rule(:num).validate do
|
||||
key.failure('invalid') if value < 3
|
||||
key.failure("invalid") if value < 3
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'applies rule when an item passed schema checks' do
|
||||
it "applies rule when an item passed schema checks" do
|
||||
expect(contract.(num: 2).errors.to_h)
|
||||
.to eql(num: ['invalid'])
|
||||
.to eql(num: ["invalid"])
|
||||
end
|
||||
end
|
||||
|
||||
context 'using a simple macro' do
|
||||
context "using a simple macro" do
|
||||
let(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
def self.name
|
||||
'TestContract'
|
||||
"TestContract"
|
||||
end
|
||||
|
||||
register_macro(:even?) do
|
||||
key.failure('invalid') unless value.even?
|
||||
key.failure("invalid") unless value.even?
|
||||
end
|
||||
|
||||
params do
|
||||
|
@ -47,25 +47,25 @@ RSpec.describe Dry::Validation::Contract, 'Rule#validate' do
|
|||
end
|
||||
end
|
||||
|
||||
it 'applies first rule when an item passed schema checks' do
|
||||
it "applies first rule when an item passed schema checks" do
|
||||
expect(contract.(num: 3).errors.to_h)
|
||||
.to eql(num: ['invalid'])
|
||||
.to eql(num: ["invalid"])
|
||||
end
|
||||
end
|
||||
|
||||
context 'using multiple macros' do
|
||||
context "using multiple macros" do
|
||||
let(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
def self.name
|
||||
'TestContract'
|
||||
"TestContract"
|
||||
end
|
||||
|
||||
register_macro(:even?) do
|
||||
key.failure('invalid') unless value.even?
|
||||
key.failure("invalid") unless value.even?
|
||||
end
|
||||
|
||||
register_macro(:below_ten?) do
|
||||
key.failure('too big') unless value < 10
|
||||
key.failure("too big") unless value < 10
|
||||
end
|
||||
|
||||
params do
|
||||
|
@ -76,22 +76,22 @@ RSpec.describe Dry::Validation::Contract, 'Rule#validate' do
|
|||
end
|
||||
end
|
||||
|
||||
it 'applies rules when an item passed schema checks' do
|
||||
it "applies rules when an item passed schema checks" do
|
||||
expect(contract.(num: 15).errors.to_h)
|
||||
.to eql(num: ['invalid', 'too big'])
|
||||
.to eql(num: ["invalid", "too big"])
|
||||
end
|
||||
end
|
||||
|
||||
context 'using a macro with args' do
|
||||
context "using a macro with args" do
|
||||
let(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
def self.name
|
||||
'TestContract'
|
||||
"TestContract"
|
||||
end
|
||||
|
||||
register_macro(:min) do |macro:|
|
||||
min = macro.args[0]
|
||||
key.failure('invalid') if value < min
|
||||
key.failure("invalid") if value < min
|
||||
end
|
||||
|
||||
params do
|
||||
|
@ -102,22 +102,22 @@ RSpec.describe Dry::Validation::Contract, 'Rule#validate' do
|
|||
end
|
||||
end
|
||||
|
||||
it 'applies rule when an item passed schema checks' do
|
||||
it "applies rule when an item passed schema checks" do
|
||||
expect(contract.(num: 2).errors.to_h)
|
||||
.to eql(num: ['invalid'])
|
||||
.to eql(num: ["invalid"])
|
||||
end
|
||||
end
|
||||
|
||||
context 'using a macro with multiple args' do
|
||||
context "using a macro with multiple args" do
|
||||
let(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
def self.name
|
||||
'TestContract'
|
||||
"TestContract"
|
||||
end
|
||||
|
||||
register_macro(:between) do |macro:|
|
||||
min, max = macro.args[0..1]
|
||||
key.failure('invalid') unless (min..max).cover?(value)
|
||||
key.failure("invalid") unless (min..max).cover?(value)
|
||||
end
|
||||
|
||||
params do
|
||||
|
@ -128,27 +128,27 @@ RSpec.describe Dry::Validation::Contract, 'Rule#validate' do
|
|||
end
|
||||
end
|
||||
|
||||
it 'applies rule when an item passed schema checks' do
|
||||
it "applies rule when an item passed schema checks" do
|
||||
expect(contract.(num: 2).errors.to_h)
|
||||
.to eql(num: ['invalid'])
|
||||
.to eql(num: ["invalid"])
|
||||
end
|
||||
end
|
||||
|
||||
context 'using multiple macros with args' do
|
||||
context "using multiple macros with args" do
|
||||
let(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
def self.name
|
||||
'TestContract'
|
||||
"TestContract"
|
||||
end
|
||||
|
||||
register_macro(:min) do |macro:|
|
||||
min = macro.args[0]
|
||||
key.failure('too small') if value < min
|
||||
key.failure("too small") if value < min
|
||||
end
|
||||
|
||||
register_macro(:max) do |macro:|
|
||||
max = macro.args[0]
|
||||
key.failure('too big') if value > max
|
||||
key.failure("too big") if value > max
|
||||
end
|
||||
|
||||
params do
|
||||
|
@ -159,14 +159,14 @@ RSpec.describe Dry::Validation::Contract, 'Rule#validate' do
|
|||
end
|
||||
end
|
||||
|
||||
it 'applies first rule when an item passed schema checks' do
|
||||
it "applies first rule when an item passed schema checks" do
|
||||
expect(contract.(num: 2).errors.to_h)
|
||||
.to eql(num: ['too small'])
|
||||
.to eql(num: ["too small"])
|
||||
end
|
||||
|
||||
it 'applies second rule when an item passed schema checks' do
|
||||
it "applies second rule when an item passed schema checks" do
|
||||
expect(contract.(num: 6).errors.to_h)
|
||||
.to eql(num: ['too big'])
|
||||
.to eql(num: ["too big"])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/validation/contract'
|
||||
require "dry/validation/contract"
|
||||
|
||||
RSpec.describe Dry::Validation::Contract, '.rule' do
|
||||
RSpec.describe Dry::Validation::Contract, ".rule" do
|
||||
subject(:contract) { contract_class.new }
|
||||
|
||||
let(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
def self.name
|
||||
'TestContract'
|
||||
"TestContract"
|
||||
end
|
||||
|
||||
params do
|
||||
|
@ -24,154 +24,154 @@ RSpec.describe Dry::Validation::Contract, '.rule' do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when the name matches one of the keys' do
|
||||
context "when the name matches one of the keys" do
|
||||
before do
|
||||
contract_class.rule(:login) do
|
||||
key.failure('is too short') if values[:login].size < 3
|
||||
key.failure("is too short") if values[:login].size < 3
|
||||
end
|
||||
end
|
||||
|
||||
it 'applies rule when value passed schema checks' do
|
||||
expect(contract.(email: 'jane@doe.org', login: 'ab').errors.to_h)
|
||||
.to eql(login: ['is too short'])
|
||||
it "applies rule when value passed schema checks" do
|
||||
expect(contract.(email: "jane@doe.org", login: "ab").errors.to_h)
|
||||
.to eql(login: ["is too short"])
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the name does not match one of the keys' do
|
||||
context "when the name does not match one of the keys" do
|
||||
before do
|
||||
contract_class.rule do
|
||||
key(:custom).failure('this works')
|
||||
key(:custom).failure("this works")
|
||||
end
|
||||
end
|
||||
|
||||
it 'applies the rule regardless of the schema result' do
|
||||
expect(contract.(email: 'jane@doe.org', login: 'jane').errors.to_h)
|
||||
.to eql(custom: ['this works'])
|
||||
it "applies the rule regardless of the schema result" do
|
||||
expect(contract.(email: "jane@doe.org", login: "jane").errors.to_h)
|
||||
.to eql(custom: ["this works"])
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a hash as the key identifier' do
|
||||
context "with a hash as the key identifier" do
|
||||
before do
|
||||
contract_class.rule(details: { address: :street }) do
|
||||
key.failure('cannot be empty') if values[:details][:address][:street].strip.empty?
|
||||
contract_class.rule(details: {address: :street}) do
|
||||
key.failure("cannot be empty") if values[:details][:address][:street].strip.empty?
|
||||
end
|
||||
end
|
||||
|
||||
it 'applies the rule when nested value passed schema checks' do
|
||||
expect(contract.(email: 'jane@doe.org', login: 'jane', details: nil).errors.to_h)
|
||||
.to eql(details: ['must be a hash'])
|
||||
it "applies the rule when nested value passed schema checks" do
|
||||
expect(contract.(email: "jane@doe.org", login: "jane", details: nil).errors.to_h)
|
||||
.to eql(details: ["must be a hash"])
|
||||
|
||||
expect(contract.(email: 'jane@doe.org', login: 'jane', details: { address: nil }).errors.to_h)
|
||||
.to eql(details: { address: ['must be a hash'] })
|
||||
expect(contract.(email: "jane@doe.org", login: "jane", details: {address: nil}).errors.to_h)
|
||||
.to eql(details: {address: ["must be a hash"]})
|
||||
|
||||
expect(contract.(email: 'jane@doe.org', login: 'jane', details: { address: { street: ' ' } }).errors.to_h)
|
||||
.to eql(details: { address: { street: ['cannot be empty'] } })
|
||||
expect(contract.(email: "jane@doe.org", login: "jane", details: {address: {street: " "}}).errors.to_h)
|
||||
.to eql(details: {address: {street: ["cannot be empty"]}})
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a rule for nested hash and another rule for its member' do
|
||||
context "with a rule for nested hash and another rule for its member" do
|
||||
before do
|
||||
contract_class.rule(details: :address) do
|
||||
key.failure('invalid no matter what')
|
||||
key.failure("invalid no matter what")
|
||||
end
|
||||
|
||||
contract_class.rule(details: :address) do
|
||||
key.failure('seriously invalid')
|
||||
key.failure("seriously invalid")
|
||||
end
|
||||
|
||||
contract_class.rule(details: { address: :street }) do
|
||||
key.failure('cannot be empty') if values[:details][:address][:street].strip.empty?
|
||||
contract_class.rule(details: {address: :street}) do
|
||||
key.failure("cannot be empty") if values[:details][:address][:street].strip.empty?
|
||||
end
|
||||
|
||||
contract_class.rule(details: { address: :street }) do
|
||||
key.failure('must include a number') unless values[:details][:address][:street].match?(/\d+/)
|
||||
contract_class.rule(details: {address: :street}) do
|
||||
key.failure("must include a number") unless values[:details][:address][:street].match?(/\d+/)
|
||||
end
|
||||
end
|
||||
|
||||
it 'applies the rule when nested value passed schema checks' do
|
||||
expect(contract.(email: 'jane@doe.org', login: 'jane', details: { address: { street: ' ' } }).errors.to_h)
|
||||
it "applies the rule when nested value passed schema checks" do
|
||||
expect(contract.(email: "jane@doe.org", login: "jane", details: {address: {street: " "}}).errors.to_h)
|
||||
.to eql(
|
||||
details: { address: [
|
||||
['invalid no matter what', 'seriously invalid'],
|
||||
{ street: ['cannot be empty', 'must include a number'] }
|
||||
] }
|
||||
details: {address: [
|
||||
["invalid no matter what", "seriously invalid"],
|
||||
{street: ["cannot be empty", "must include a number"]}
|
||||
]}
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a rule that sets a general base error for the whole input' do
|
||||
context "with a rule that sets a general base error for the whole input" do
|
||||
before do
|
||||
contract_class.rule do
|
||||
key.failure('this whole thing is invalid')
|
||||
key.failure("this whole thing is invalid")
|
||||
end
|
||||
end
|
||||
|
||||
it 'sets a base error not attached to any key' do
|
||||
expect(contract.(email: 'jane@doe.org', login: '').errors.to_h)
|
||||
.to eql(login: ['must be filled'], nil => ['this whole thing is invalid'])
|
||||
it "sets a base error not attached to any key" do
|
||||
expect(contract.(email: "jane@doe.org", login: "").errors.to_h)
|
||||
.to eql(login: ["must be filled"], nil => ["this whole thing is invalid"])
|
||||
|
||||
expect(contract.(email: 'jane@doe.org', login: '').errors.filter(:base?).map(&:to_s))
|
||||
.to eql(['this whole thing is invalid'])
|
||||
expect(contract.(email: "jane@doe.org", login: "").errors.filter(:base?).map(&:to_s))
|
||||
.to eql(["this whole thing is invalid"])
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a list of keys' do
|
||||
context "with a list of keys" do
|
||||
before do
|
||||
contract_class.rule(:email, :login) do
|
||||
if !values[:email].empty? && !values[:login].empty?
|
||||
key(:login).failure('is not needed when email is provided')
|
||||
key(:login).failure("is not needed when email is provided")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'applies the rule when all values passed schema checks' do
|
||||
it "applies the rule when all values passed schema checks" do
|
||||
expect(contract.(email: nil, login: nil).errors.to_h)
|
||||
.to eql(email: ['must be filled'], login: ['must be filled'])
|
||||
.to eql(email: ["must be filled"], login: ["must be filled"])
|
||||
|
||||
expect(contract.(email: 'jane@doe.org', login: 'jane').errors.to_h)
|
||||
.to eql(login: ['is not needed when email is provided'])
|
||||
expect(contract.(email: "jane@doe.org", login: "jane").errors.to_h)
|
||||
.to eql(login: ["is not needed when email is provided"])
|
||||
end
|
||||
end
|
||||
|
||||
context 'when keys are missing in the schema' do
|
||||
it 'raises error with a list of symbol keys' do
|
||||
context "when keys are missing in the schema" do
|
||||
it "raises error with a list of symbol keys" do
|
||||
expect { contract_class.rule(:invalid, :wrong) }
|
||||
.to raise_error(
|
||||
Dry::Validation::InvalidKeysError,
|
||||
'TestContract.rule specifies keys that are not defined by the schema: [:invalid, :wrong]'
|
||||
"TestContract.rule specifies keys that are not defined by the schema: [:invalid, :wrong]"
|
||||
)
|
||||
end
|
||||
|
||||
it 'raises error with a hash path' do
|
||||
it "raises error with a hash path" do
|
||||
expect { contract_class.rule(invalid: :wrong) }
|
||||
.to raise_error(
|
||||
Dry::Validation::InvalidKeysError,
|
||||
'TestContract.rule specifies keys that are not defined by the schema: [{:invalid=>:wrong}]'
|
||||
"TestContract.rule specifies keys that are not defined by the schema: [{:invalid=>:wrong}]"
|
||||
)
|
||||
end
|
||||
|
||||
it 'raises error with a dot notation' do
|
||||
expect { contract_class.rule('invalid.wrong') }
|
||||
it "raises error with a dot notation" do
|
||||
expect { contract_class.rule("invalid.wrong") }
|
||||
.to raise_error(
|
||||
Dry::Validation::InvalidKeysError,
|
||||
'TestContract.rule specifies keys that are not defined by the schema: ["invalid.wrong"]'
|
||||
)
|
||||
end
|
||||
|
||||
it 'raises error with a hash path with multiple nested keys' do
|
||||
it "raises error with a hash path with multiple nested keys" do
|
||||
expect { contract_class.rule(invalid: %i[wrong not_here]) }
|
||||
.to raise_error(
|
||||
Dry::Validation::InvalidKeysError,
|
||||
'TestContract.rule specifies keys that are not defined by the schema: [[:invalid, :wrong], [:invalid, :not_here]]'
|
||||
"TestContract.rule specifies keys that are not defined by the schema: [[:invalid, :wrong], [:invalid, :not_here]]"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'abstract contract' do
|
||||
describe "abstract contract" do
|
||||
let(:abstract_contract) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
rule do
|
||||
base.failure('error from abstract contract')
|
||||
base.failure("error from abstract contract")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -184,9 +184,9 @@ RSpec.describe Dry::Validation::Contract, '.rule' do
|
|||
end
|
||||
end
|
||||
|
||||
it 'applies rules from the parent abstract contract' do
|
||||
expect(contract.(name: '').errors.to_h).to eql(
|
||||
nil => ['error from abstract contract'], name: ['must be filled']
|
||||
it "applies rules from the parent abstract contract" do
|
||||
expect(contract.(name: "").errors.to_h).to eql(
|
||||
nil => ["error from abstract contract"], name: ["must be filled"]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/validation/contract'
|
||||
require "dry/validation/contract"
|
||||
|
||||
RSpec.describe Dry::Validation::Contract, '.schema' do
|
||||
context 'defining a schema via block' do
|
||||
RSpec.describe Dry::Validation::Contract, ".schema" do
|
||||
context "defining a schema via block" do
|
||||
subject(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
schema do
|
||||
|
@ -12,16 +12,16 @@ RSpec.describe Dry::Validation::Contract, '.schema' do
|
|||
end
|
||||
end
|
||||
|
||||
it 'defines a schema' do
|
||||
it "defines a schema" do
|
||||
expect(contract_class.schema).to be_a(Dry::Schema::Processor)
|
||||
end
|
||||
|
||||
it 'returns nil if schema is not defined' do
|
||||
it "returns nil if schema is not defined" do
|
||||
contract_class = Class.new(Dry::Validation::Contract)
|
||||
expect(contract_class.schema).to be(nil)
|
||||
end
|
||||
|
||||
it 'raises an error if schema is already defined' do
|
||||
it "raises an error if schema is already defined" do
|
||||
expect do
|
||||
contract_class.schema do
|
||||
required(:login).filled(:string)
|
||||
|
@ -30,7 +30,7 @@ RSpec.describe Dry::Validation::Contract, '.schema' do
|
|||
end
|
||||
end
|
||||
|
||||
context 'setting an external schema' do
|
||||
context "setting an external schema" do
|
||||
subject(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
schema(Test::UserSchema) do
|
||||
|
@ -45,30 +45,30 @@ RSpec.describe Dry::Validation::Contract, '.schema' do
|
|||
end
|
||||
end
|
||||
|
||||
it 'defines a schema' do
|
||||
it "defines a schema" do
|
||||
expect(contract_class.schema).to be_a(Dry::Schema::Processor)
|
||||
end
|
||||
|
||||
it 'extends the schema' do
|
||||
it "extends the schema" do
|
||||
contract = contract_class.new
|
||||
|
||||
expect(contract.(email: '', name: '').errors.to_h)
|
||||
.to eql(email: ['must be filled'], name: ['must be filled'])
|
||||
expect(contract.(email: "", name: "").errors.to_h)
|
||||
.to eql(email: ["must be filled"], name: ["must be filled"])
|
||||
end
|
||||
|
||||
context 'schema without block argument' do
|
||||
context "schema without block argument" do
|
||||
subject(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
schema Test::UserSchema
|
||||
end
|
||||
end
|
||||
|
||||
it 'uses the external schema' do
|
||||
it "uses the external schema" do
|
||||
expect(contract_class.schema).to be_a(Dry::Schema::Processor)
|
||||
end
|
||||
end
|
||||
|
||||
context 'setting multiple external schemas' do
|
||||
context "setting multiple external schemas" do
|
||||
subject(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
schema(Test::UserSchema, Test::CompanySchema) do
|
||||
|
@ -83,12 +83,12 @@ RSpec.describe Dry::Validation::Contract, '.schema' do
|
|||
end
|
||||
end
|
||||
|
||||
it 'extends the schemas' do
|
||||
it "extends the schemas" do
|
||||
contract = contract_class.new
|
||||
expect(contract.(email: '', name: '', company: '').errors.to_h)
|
||||
.to eql(email: ['must be filled'],
|
||||
name: ['must be filled'],
|
||||
company: ['must be filled'])
|
||||
expect(contract.(email: "", name: "", company: "").errors.to_h)
|
||||
.to eql(email: ["must be filled"],
|
||||
name: ["must be filled"],
|
||||
company: ["must be filled"])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe Dry::Validation::Evaluator do
|
||||
describe '#schema_error?' do
|
||||
describe "#schema_error?" do
|
||||
let(:contract) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
schema do
|
||||
|
@ -10,20 +10,20 @@ RSpec.describe Dry::Validation::Evaluator do
|
|||
end
|
||||
|
||||
rule(:name) do
|
||||
key.failure('first introduce a valid email') if schema_error?(:email)
|
||||
key.failure("first introduce a valid email") if schema_error?(:email)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'checks for errors in given key' do
|
||||
expect(contract.new.(email: nil, name: 'foo').errors.to_h).to eql(
|
||||
email: ['must be a string'],
|
||||
name: ['first introduce a valid email']
|
||||
it "checks for errors in given key" do
|
||||
expect(contract.new.(email: nil, name: "foo").errors.to_h).to eql(
|
||||
email: ["must be a string"],
|
||||
name: ["first introduce a valid email"]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#rule_error?' do
|
||||
describe "#rule_error?" do
|
||||
let(:contract) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
schema do
|
||||
|
@ -31,15 +31,15 @@ RSpec.describe Dry::Validation::Evaluator do
|
|||
end
|
||||
|
||||
rule(:foo) do
|
||||
key.failure('failure added')
|
||||
key.failure('failure added after checking') if rule_error?
|
||||
key.failure("failure added")
|
||||
key.failure("failure added after checking") if rule_error?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'checks for errors in current rule' do
|
||||
expect(contract.new.(foo: 'some@email.com').errors.to_h).to eql(
|
||||
foo: ['failure added', 'failure added after checking']
|
||||
it "checks for errors in current rule" do
|
||||
expect(contract.new.(foo: "some@email.com").errors.to_h).to eql(
|
||||
foo: ["failure added", "failure added after checking"]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,109 +13,109 @@ RSpec.describe Dry::Validation::Evaluator do
|
|||
end
|
||||
end
|
||||
|
||||
context 'setting key failures using default rule path' do
|
||||
context "setting key failures using default rule path" do
|
||||
before do
|
||||
contract_class.rule(:email) do
|
||||
key.failure('is invalid')
|
||||
key.failure("is invalid")
|
||||
end
|
||||
end
|
||||
|
||||
it 'sets error under specified key' do
|
||||
expect(contract.(email: 'foo').errors.to_h).to eql(email: ['is invalid'])
|
||||
it "sets error under specified key" do
|
||||
expect(contract.(email: "foo").errors.to_h).to eql(email: ["is invalid"])
|
||||
end
|
||||
end
|
||||
|
||||
context 'setting key failures using via explicit path' do
|
||||
context 'with a string message' do
|
||||
context "setting key failures using via explicit path" do
|
||||
context "with a string message" do
|
||||
before do
|
||||
contract_class.rule(:email) do
|
||||
key(:contact).failure('is invalid')
|
||||
key(:contact).failure("is invalid")
|
||||
end
|
||||
end
|
||||
|
||||
it 'sets error under specified key' do
|
||||
expect(contract.(email: 'foo').errors.to_h).to eql(contact: ['is invalid'])
|
||||
it "sets error under specified key" do
|
||||
expect(contract.(email: "foo").errors.to_h).to eql(contact: ["is invalid"])
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a nested key as a hash and a string message' do
|
||||
context "with a nested key as a hash and a string message" do
|
||||
before do
|
||||
contract_class.rule(:email) do
|
||||
key(contact: :details).failure('is invalid')
|
||||
key(contact: :details).failure("is invalid")
|
||||
end
|
||||
end
|
||||
|
||||
it 'sets error under specified key' do
|
||||
expect(contract.(email: 'foo').errors.to_h).to eql(contact: { details: ['is invalid'] })
|
||||
it "sets error under specified key" do
|
||||
expect(contract.(email: "foo").errors.to_h).to eql(contact: {details: ["is invalid"]})
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a symbol' do
|
||||
context "with a symbol" do
|
||||
before do
|
||||
contract_class.config.messages.load_paths << SPEC_ROOT
|
||||
.join('fixtures/messages/errors.en.yml').realpath
|
||||
.join("fixtures/messages/errors.en.yml").realpath
|
||||
|
||||
contract_class.rule(:email) do
|
||||
key(:contact).failure(:wrong)
|
||||
end
|
||||
end
|
||||
|
||||
it 'sets error under specified key' do
|
||||
expect(contract.(email: 'foo').errors.to_h).to eql(contact: ['not right'])
|
||||
it "sets error under specified key" do
|
||||
expect(contract.(email: "foo").errors.to_h).to eql(contact: ["not right"])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'setting base failures' do
|
||||
context "setting base failures" do
|
||||
before do
|
||||
contract_class.rule(:email) do
|
||||
base.failure('is invalid')
|
||||
base.failure("is invalid")
|
||||
end
|
||||
end
|
||||
|
||||
it 'sets error under specified key' do
|
||||
expect(contract.(email: 'foo').errors.to_h).to eql(nil => ['is invalid'])
|
||||
it "sets error under specified key" do
|
||||
expect(contract.(email: "foo").errors.to_h).to eql(nil => ["is invalid"])
|
||||
end
|
||||
end
|
||||
|
||||
context 'setting failures with meta data' do
|
||||
context "setting failures with meta data" do
|
||||
before do
|
||||
contract_class.rule(:email) do
|
||||
key.failure(text: 'is invalid', code: 102)
|
||||
key.failure(text: "is invalid", code: 102)
|
||||
end
|
||||
end
|
||||
|
||||
it 'sets error under specified key' do
|
||||
errors = contract.(email: 'foo').errors
|
||||
it "sets error under specified key" do
|
||||
errors = contract.(email: "foo").errors
|
||||
|
||||
expect(errors.to_h).to eql(email: [text: 'is invalid', code: 102])
|
||||
expect(errors.to_h).to eql(email: [text: "is invalid", code: 102])
|
||||
expect(errors.first.meta).to eql(code: 102)
|
||||
end
|
||||
|
||||
context 'without :text key' do
|
||||
context "without :text key" do
|
||||
before do
|
||||
contract_class.rule(:email) do
|
||||
key.failure(code: 102)
|
||||
end
|
||||
end
|
||||
|
||||
it 'raises argument error if no text key provided' do
|
||||
it "raises argument error if no text key provided" do
|
||||
expect {
|
||||
contract.(email: 'foo').errors
|
||||
contract.(email: "foo").errors
|
||||
}.to raise_error(ArgumentError, /Hash must contain :text key/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when localized message id is invalid' do
|
||||
context "when localized message id is invalid" do
|
||||
before do
|
||||
contract_class.rule(:email) do
|
||||
key.failure([:oops_bad_id])
|
||||
end
|
||||
end
|
||||
|
||||
it 'raises a meaningful error' do
|
||||
expect { contract.(email: 'foo') }.to raise_error(ArgumentError, /oops_bad_id/)
|
||||
it "raises a meaningful error" do
|
||||
expect { contract.(email: "foo") }.to raise_error(ArgumentError, /oops_bad_id/)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe Dry::Validation::Evaluator, 'using context' do
|
||||
RSpec.describe Dry::Validation::Evaluator, "using context" do
|
||||
before(:all) do
|
||||
Dry::Validation.load_extensions(:hints)
|
||||
end
|
||||
|
||||
context 'when key does not exist' do
|
||||
context "when key does not exist" do
|
||||
subject(:contract) do
|
||||
Dry::Validation.Contract do
|
||||
schema do
|
||||
|
@ -15,25 +15,25 @@ RSpec.describe Dry::Validation::Evaluator, 'using context' do
|
|||
|
||||
rule(:user_id) do |context:|
|
||||
if values[:user_id].equal?(312)
|
||||
context[:user] = 'jane'
|
||||
context[:user] = "jane"
|
||||
else
|
||||
key(:user).failure('must be jane')
|
||||
key(:user).failure("must be jane")
|
||||
end
|
||||
end
|
||||
|
||||
rule(:email) do |context:|
|
||||
key.failure('is invalid') if context[:user] == 'jane' && values[:email] != 'jane@doe.org'
|
||||
key.failure("is invalid") if context[:user] == "jane" && values[:email] != "jane@doe.org"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it 'stores new values between rule execution' do
|
||||
expect(contract.(user_id: 3, email: 'john@doe.org').errors.to_h).to eql(user: ['must be jane'])
|
||||
expect(contract.(user_id: 312, email: 'john@doe.org').errors.to_h).to eql(email: ['is invalid'])
|
||||
it "stores new values between rule execution" do
|
||||
expect(contract.(user_id: 3, email: "john@doe.org").errors.to_h).to eql(user: ["must be jane"])
|
||||
expect(contract.(user_id: 312, email: "john@doe.org").errors.to_h).to eql(email: ["is invalid"])
|
||||
end
|
||||
|
||||
it 'exposes context in result' do
|
||||
expect(contract.(user_id: 312, email: 'jane@doe.org').context[:user]).to eql('jane')
|
||||
it "exposes context in result" do
|
||||
expect(contract.(user_id: 312, email: "jane@doe.org").context[:user]).to eql("jane")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/validation/contract'
|
||||
require "dry/validation/contract"
|
||||
|
||||
RSpec.describe Dry::Validation::Contract, '.option' do
|
||||
RSpec.describe Dry::Validation::Contract, ".option" do
|
||||
subject(:contract_class) do
|
||||
Class.new(Dry::Validation::Contract) do
|
||||
option :db
|
||||
|
@ -12,18 +12,18 @@ RSpec.describe Dry::Validation::Contract, '.option' do
|
|||
end
|
||||
|
||||
rule(:email) do
|
||||
key.failure('is taken') unless db.unique?(values[:email])
|
||||
key.failure("is taken") unless db.unique?(values[:email])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
let(:db) { double(:db) }
|
||||
|
||||
it 'allows injecting objects to the constructor' do
|
||||
expect(db).to receive(:unique?).with('jane@doe.org').and_return(false)
|
||||
it "allows injecting objects to the constructor" do
|
||||
expect(db).to receive(:unique?).with("jane@doe.org").and_return(false)
|
||||
|
||||
contract = contract_class.new(db: db)
|
||||
|
||||
expect(contract.(email: 'jane@doe.org').errors.to_h).to eql(email: ['is taken'])
|
||||
expect(contract.(email: "jane@doe.org").errors.to_h).to eql(email: ["is taken"])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/validation/contract'
|
||||
require 'dry/schema/messages/i18n'
|
||||
require "dry/validation/contract"
|
||||
require "dry/schema/messages/i18n"
|
||||
|
||||
RSpec.describe Dry::Validation::Contract, '.inherited' do
|
||||
RSpec.describe Dry::Validation::Contract, ".inherited" do
|
||||
subject(:child_class) do
|
||||
Class.new(parent_class) do
|
||||
params do
|
||||
|
@ -26,15 +26,15 @@ RSpec.describe Dry::Validation::Contract, '.inherited' do
|
|||
end
|
||||
end
|
||||
|
||||
it 'inherits schema params' do
|
||||
it "inherits schema params" do
|
||||
expect(child_class.__schema__.key_map.map(&:name).sort).to eql(%w[email name])
|
||||
end
|
||||
|
||||
it 'inherits rules' do
|
||||
it "inherits rules" do
|
||||
expect(child_class.rules.map(&:keys).sort).to eql([[:email], [:name]])
|
||||
end
|
||||
|
||||
it 'inherits configuration' do
|
||||
it "inherits configuration" do
|
||||
expect(child_class.config.messages.backend).to eql(parent_class.config.messages.backend)
|
||||
expect(child_class.config.messages.load_paths).to eql(parent_class.config.messages.load_paths)
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe Dry::Validation::Contract, '.macros' do
|
||||
RSpec.describe Dry::Validation::Contract, ".macros" do
|
||||
subject!(:contract_class) do
|
||||
Class.new(parent_class) do
|
||||
register_macro(:other_macro) {}
|
||||
|
@ -13,14 +13,14 @@ RSpec.describe Dry::Validation::Contract, '.macros' do
|
|||
end
|
||||
end
|
||||
|
||||
it 'returns macros container inherited from the parent' do
|
||||
it "returns macros container inherited from the parent" do
|
||||
expect(contract_class.macros.key?(:check_things)).to be(true)
|
||||
expect(contract_class.macros.key?(:other_macro)).to be(true)
|
||||
|
||||
expect(parent_class.macros.key?(:other_macro)).to be(false)
|
||||
end
|
||||
|
||||
it 'does not mutate source macro container' do
|
||||
it "does not mutate source macro container" do
|
||||
expect(parent_class.superclass.macros.key?(:check_things)).to be(false)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,95 +1,95 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/validation/contract'
|
||||
require "dry/validation/contract"
|
||||
|
||||
RSpec.describe Dry::Validation::Contract do
|
||||
shared_context 'translated messages' 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
|
||||
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'
|
||||
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
|
||||
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'])
|
||||
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'])
|
||||
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'])
|
||||
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'])
|
||||
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
|
||||
context "using :yaml messages" do
|
||||
before do
|
||||
contract_class.config.messages.backend = :yaml
|
||||
end
|
||||
|
||||
include_context 'translated messages'
|
||||
include_context "translated messages"
|
||||
end
|
||||
|
||||
context 'using :i18n messages' do
|
||||
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_class.config.messages.load_paths << SPEC_ROOT.join("fixtures/messages/errors.pl.yml").realpath
|
||||
|
||||
contract
|
||||
end
|
||||
|
||||
include_context 'translated messages'
|
||||
include_context "translated messages"
|
||||
|
||||
it 'respects I18n.with_locale' do
|
||||
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'])
|
||||
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'])
|
||||
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'])
|
||||
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
|
||||
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
|
||||
config.messages.load_paths << SPEC_ROOT.join("fixtures/messages/errors.en.yml").realpath
|
||||
|
||||
params do
|
||||
required(:age).filled(:integer)
|
||||
|
@ -101,6 +101,6 @@ RSpec.describe Dry::Validation::Contract do
|
|||
end
|
||||
end
|
||||
|
||||
expect(contract.new.call(age: 4).errors.to_h).to eql(age: ['should be included in 1, 2, 3'])
|
||||
expect(contract.new.call(age: 4).errors.to_h).to eql(age: ["should be included in 1, 2, 3"])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/validation/contract'
|
||||
require "dry/validation/contract"
|
||||
|
||||
RSpec.describe Dry::Validation::Contract do
|
||||
subject(:contract) do
|
||||
|
@ -14,27 +14,27 @@ RSpec.describe Dry::Validation::Contract do
|
|||
end
|
||||
|
||||
rule(:email) do
|
||||
key.failure('must be unique')
|
||||
key.failure("must be unique")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#inspect' do
|
||||
it 'returns a string representation' do
|
||||
describe "#inspect" do
|
||||
it "returns a string representation" do
|
||||
expect(contract.inspect).to eql(
|
||||
%(#<Test::NewUserContract schema=#<Dry::Schema::Params keys=["email"] rules={:email=>"key?(:email) AND key[email](filled? AND str?)"}> rules=[#<Dry::Validation::Rule keys=[:email]>]>)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.new' do
|
||||
it 'raises error when schema is not defined' do
|
||||
Test::NewUserContract.instance_variable_set('@__schema__', nil)
|
||||
describe ".new" do
|
||||
it "raises error when schema is not defined" do
|
||||
Test::NewUserContract.instance_variable_set("@__schema__", nil)
|
||||
|
||||
expect { Test::NewUserContract.new }
|
||||
.to raise_error(
|
||||
Dry::Validation::SchemaMissingError,
|
||||
'Test::NewUserContract cannot be instantiated without a schema defined'
|
||||
"Test::NewUserContract cannot be instantiated without a schema defined"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/validation/evaluator'
|
||||
require "dry/validation/evaluator"
|
||||
|
||||
RSpec.describe Dry::Validation::Evaluator do
|
||||
subject(:evaluator) do
|
||||
|
@ -12,27 +12,27 @@ RSpec.describe Dry::Validation::Evaluator do
|
|||
end
|
||||
|
||||
let(:options) do
|
||||
{ keys: [:email], result: {}, values: values, _context: {} }
|
||||
{keys: [:email], result: {}, values: values, _context: {}}
|
||||
end
|
||||
|
||||
let(:values) do
|
||||
{}
|
||||
end
|
||||
|
||||
describe 'delegation' do
|
||||
describe "delegation" do
|
||||
let(:block) do
|
||||
proc {
|
||||
key.failure('it works') if works?
|
||||
key.failure("it works") if works?
|
||||
}
|
||||
end
|
||||
|
||||
it 'delegates to the contract' do
|
||||
it "delegates to the contract" do
|
||||
expect(contract).to receive(:works?).and_return(true)
|
||||
expect(evaluator.failures[0][:path].to_a).to eql([:email])
|
||||
expect(evaluator.failures[0][:message]).to eql('it works')
|
||||
expect(evaluator.failures[0][:message]).to eql("it works")
|
||||
end
|
||||
|
||||
describe 'with custom methods defined on the contract' do
|
||||
describe "with custom methods defined on the contract" do
|
||||
let(:contract) do
|
||||
double(contract: :my_contract)
|
||||
end
|
||||
|
@ -41,8 +41,8 @@ RSpec.describe Dry::Validation::Evaluator do
|
|||
proc { key.failure("message with #{contract}") }
|
||||
end
|
||||
|
||||
it 'forwards to the contract' do
|
||||
expect(evaluator.failures[0][:message]).to eql('message with my_contract')
|
||||
it "forwards to the contract" do
|
||||
expect(evaluator.failures[0][:message]).to eql("message with my_contract")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe Dry::Validation::Macros, ':acceptance' do
|
||||
RSpec.describe Dry::Validation::Macros, ":acceptance" do
|
||||
subject(:contract) do
|
||||
Dry::Validation::Contract.build do
|
||||
schema do
|
||||
|
@ -11,11 +11,11 @@ RSpec.describe Dry::Validation::Macros, ':acceptance' do
|
|||
end
|
||||
end
|
||||
|
||||
it 'succeeds when value is true' do
|
||||
it "succeeds when value is true" do
|
||||
expect(contract.(terms: true)).to be_success
|
||||
end
|
||||
|
||||
it 'fails when value is not true' do
|
||||
expect(contract.(terms: false).errors.to_h).to eql(terms: ['must accept terms'])
|
||||
it "fails when value is not true" do
|
||||
expect(contract.(terms: false).errors.to_h).to eql(terms: ["must accept terms"])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe 'Defining custom macros' do
|
||||
RSpec.describe "Defining custom macros" do
|
||||
subject(:contract) do
|
||||
contract_class.new
|
||||
end
|
||||
|
@ -17,49 +17,49 @@ RSpec.describe 'Defining custom macros' do
|
|||
class Test::BaseContract < Dry::Validation::Contract; end
|
||||
end
|
||||
|
||||
context 'using a macro without options' do
|
||||
shared_context 'a contract with a custom macro' do
|
||||
context "using a macro without options" do
|
||||
shared_context "a contract with a custom macro" do
|
||||
before do
|
||||
contract_class.rule(:numbers).validate(:even_numbers)
|
||||
end
|
||||
|
||||
it 'succeeds with valid input' do
|
||||
it "succeeds with valid input" do
|
||||
expect(contract.(numbers: [2, 4, 6])).to be_success
|
||||
end
|
||||
|
||||
it 'fails with invalid input' do
|
||||
expect(contract.(numbers: [1, 2, 3]).errors.to_h).to eql(numbers: ['all numbers must be even'])
|
||||
it "fails with invalid input" do
|
||||
expect(contract.(numbers: [1, 2, 3]).errors.to_h).to eql(numbers: ["all numbers must be even"])
|
||||
end
|
||||
end
|
||||
|
||||
context 'using macro from the global registry' do
|
||||
context "using macro from the global registry" do
|
||||
before do
|
||||
Dry::Validation.register_macro(:even_numbers) do
|
||||
key.failure('all numbers must be even') unless values[key_name].all?(&:even?)
|
||||
key.failure("all numbers must be even") unless values[key_name].all?(&:even?)
|
||||
end
|
||||
end
|
||||
|
||||
after do
|
||||
Dry::Validation::Macros.container._container.delete('even_numbers')
|
||||
Dry::Validation::Macros.container._container.delete("even_numbers")
|
||||
end
|
||||
|
||||
include_context 'a contract with a custom macro'
|
||||
include_context "a contract with a custom macro"
|
||||
end
|
||||
|
||||
context 'using macro from contract itself' do
|
||||
context "using macro from contract itself" do
|
||||
before do
|
||||
Test::BaseContract.register_macro(:even_numbers) do
|
||||
key.failure('all numbers must be even') unless values[key_name].all?(&:even?)
|
||||
key.failure("all numbers must be even") unless values[key_name].all?(&:even?)
|
||||
end
|
||||
end
|
||||
|
||||
after do
|
||||
Test::BaseContract.macros._container.delete('even_numbers')
|
||||
Test::BaseContract.macros._container.delete("even_numbers")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'using a macro with options' do
|
||||
context "using a macro with options" do
|
||||
before do
|
||||
Test::BaseContract.register_macro(:min) do |context:, macro:|
|
||||
num = macro.args[0]
|
||||
|
@ -71,16 +71,16 @@ RSpec.describe 'Defining custom macros' do
|
|||
end
|
||||
|
||||
after do
|
||||
Test::BaseContract.macros._container.delete('min')
|
||||
Test::BaseContract.macros._container.delete("min")
|
||||
end
|
||||
|
||||
it 'fails with invalid input' do
|
||||
it "fails with invalid input" do
|
||||
expect(contract.(numbers: [1]).errors.to_h)
|
||||
.to eql(numbers: ['must have at least 3 items'])
|
||||
.to eql(numbers: ["must have at least 3 items"])
|
||||
end
|
||||
end
|
||||
|
||||
context 'using a macro with a range option' do
|
||||
context "using a macro with a range option" do
|
||||
before do
|
||||
Test::BaseContract.register_macro(:in_range) do |macro:|
|
||||
range = macro.args[0]
|
||||
|
@ -93,14 +93,14 @@ RSpec.describe 'Defining custom macros' do
|
|||
end
|
||||
|
||||
after do
|
||||
Test::BaseContract.macros._container.delete('in_range')
|
||||
Test::BaseContract.macros._container.delete("in_range")
|
||||
end
|
||||
|
||||
it 'succeeds with valid input' do
|
||||
it "succeeds with valid input" do
|
||||
expect(contract.(numbers: [1, 2, 3])).to be_success
|
||||
end
|
||||
|
||||
it 'fails with invalid input' do
|
||||
it "fails with invalid input" do
|
||||
expect(contract.(numbers: [1, 2, 6])).to be_failure
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe Dry::Validation::Messages::Resolver, '#message' do
|
||||
shared_context 'resolving' do
|
||||
RSpec.describe Dry::Validation::Messages::Resolver, "#message" do
|
||||
shared_context "resolving" do
|
||||
subject(:resolver) do
|
||||
contract_class.new(schema: proc {}).message_resolver
|
||||
end
|
||||
|
@ -17,30 +17,30 @@ RSpec.describe Dry::Validation::Messages::Resolver, '#message' do
|
|||
I18n.available_locales << :pl
|
||||
end
|
||||
|
||||
context ':en' do
|
||||
context ":en" do
|
||||
let(:locale) { :en }
|
||||
|
||||
it 'returns message text for base rule' do
|
||||
it "returns message text for base rule" do
|
||||
expect(resolver.message(:not_weekend, path: [nil], locale: locale))
|
||||
.to eql(['this only works on weekends', {}])
|
||||
.to eql(["this only works on weekends", {}])
|
||||
end
|
||||
|
||||
it 'returns message text for flat rule' do
|
||||
expect(resolver.message(:taken, path: [:email], tokens: { email: 'jane@doe.org' }, locale: locale))
|
||||
.to eql(['looks like jane@doe.org is taken', {}])
|
||||
it "returns message text for flat rule" do
|
||||
expect(resolver.message(:taken, path: [:email], tokens: {email: "jane@doe.org"}, locale: locale))
|
||||
.to eql(["looks like jane@doe.org is taken", {}])
|
||||
end
|
||||
|
||||
it 'returns message text for nested rule when it is defined under root' do
|
||||
it "returns message text for nested rule when it is defined under root" do
|
||||
expect(resolver.message(:invalid, path: %i[address city], locale: locale))
|
||||
.to eql(['is not a valid city name', {}])
|
||||
.to eql(["is not a valid city name", {}])
|
||||
end
|
||||
|
||||
it 'returns message text for nested rule' do
|
||||
it "returns message text for nested rule" do
|
||||
expect(resolver.message(:invalid, path: %i[address street], locale: locale))
|
||||
.to eql(["doesn't look good", {}])
|
||||
end
|
||||
|
||||
it 'raises error when template was not found' do
|
||||
it "raises error when template was not found" do
|
||||
expect { resolver.message(:not_here, path: [:email]) }
|
||||
.to raise_error(Dry::Validation::MissingMessageError, <<~STR)
|
||||
Message template for :not_here under "email" was not found
|
||||
|
@ -48,44 +48,44 @@ RSpec.describe Dry::Validation::Messages::Resolver, '#message' do
|
|||
end
|
||||
end
|
||||
|
||||
context ':pl' do
|
||||
context ":pl" do
|
||||
let(:locale) { :pl }
|
||||
|
||||
it 'returns message text for base rule' do
|
||||
it "returns message text for base rule" do
|
||||
expect(resolver.message(:not_weekend, path: [nil], locale: locale))
|
||||
.to eql(['to działa tylko w weekendy', {}])
|
||||
.to eql(["to działa tylko w weekendy", {}])
|
||||
end
|
||||
|
||||
it 'returns message text for flat rule' do
|
||||
expect(resolver.message(:taken, path: [:email], tokens: { email: 'jane@doe.org' }, locale: locale))
|
||||
.to eql(['wygląda, że jane@doe.org jest zajęty', {}])
|
||||
it "returns message text for flat rule" do
|
||||
expect(resolver.message(:taken, path: [:email], tokens: {email: "jane@doe.org"}, locale: locale))
|
||||
.to eql(["wygląda, że jane@doe.org jest zajęty", {}])
|
||||
end
|
||||
|
||||
it 'returns message text for nested rule when it is defined under root' do
|
||||
it "returns message text for nested rule when it is defined under root" do
|
||||
expect(resolver.message(:invalid, path: %i[address city], locale: locale))
|
||||
.to eql(['nie jest poprawną nazwą miasta', {}])
|
||||
.to eql(["nie jest poprawną nazwą miasta", {}])
|
||||
end
|
||||
|
||||
it 'returns message text for nested rule' do
|
||||
it "returns message text for nested rule" do
|
||||
expect(resolver.message(:invalid, path: %i[address street], locale: locale))
|
||||
.to eql(['nie wygląda dobrze', {}])
|
||||
.to eql(["nie wygląda dobrze", {}])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'using :yaml' do
|
||||
context "using :yaml" do
|
||||
before do
|
||||
contract_class.config.messages.backend = :yaml
|
||||
end
|
||||
|
||||
include_context 'resolving'
|
||||
include_context "resolving"
|
||||
end
|
||||
|
||||
context 'using :i18n' do
|
||||
context "using :i18n" do
|
||||
before do
|
||||
contract_class.config.messages.backend = :i18n
|
||||
end
|
||||
|
||||
include_context 'resolving'
|
||||
include_context "resolving"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,63 +1,63 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
RSpec.describe Dry::Validation::Result do
|
||||
describe '#inspect' do
|
||||
describe "#inspect" do
|
||||
let(:params) do
|
||||
double(:params, message_set: [], to_h: { email: 'jane@doe.org' })
|
||||
double(:params, message_set: [], to_h: {email: "jane@doe.org"})
|
||||
end
|
||||
|
||||
it 'returns a string representation' do
|
||||
it "returns a string representation" do
|
||||
result = Dry::Validation::Result.new(params) do |r|
|
||||
r.add_error(Dry::Validation::Message.new('not valid', path: :email))
|
||||
r.add_error(Dry::Validation::Message.new("not valid", path: :email))
|
||||
end
|
||||
|
||||
expect(result.inspect).to eql('#<Dry::Validation::Result{:email=>"jane@doe.org"} errors={:email=>["not valid"]}>')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#errors' do
|
||||
describe "#errors" do
|
||||
subject(:errors) { result.errors }
|
||||
|
||||
let(:params) do
|
||||
double(:params, message_set: [], to_h: { email: 'jane@doe.org' })
|
||||
double(:params, message_set: [], to_h: {email: "jane@doe.org"})
|
||||
end
|
||||
|
||||
let(:result) do
|
||||
Dry::Validation::Result.new(params) do |r|
|
||||
r.add_error(Dry::Validation::Message.new('root error', path: [nil]))
|
||||
r.add_error(Dry::Validation::Message.new('email error', path: [:email]))
|
||||
r.add_error(Dry::Validation::Message.new("root error", path: [nil]))
|
||||
r.add_error(Dry::Validation::Message.new("email error", path: [:email]))
|
||||
end
|
||||
end
|
||||
|
||||
describe '#[]' do
|
||||
it 'returns error messages for the provided key' do
|
||||
expect(errors[:email]).to eql(['email error'])
|
||||
describe "#[]" do
|
||||
it "returns error messages for the provided key" do
|
||||
expect(errors[:email]).to eql(["email error"])
|
||||
end
|
||||
|
||||
it 'returns [] for base errors' do
|
||||
expect(errors[nil]).to eql(['root error'])
|
||||
it "returns [] for base errors" do
|
||||
expect(errors[nil]).to eql(["root error"])
|
||||
end
|
||||
end
|
||||
|
||||
describe '#empty?' do
|
||||
describe "#empty?" do
|
||||
let(:result) { Dry::Validation::Result.new(params) }
|
||||
|
||||
it 'should return the correct value whilst adding errors' do
|
||||
it "should return the correct value whilst adding errors" do
|
||||
expect(result.errors).to be_empty
|
||||
result.add_error(Dry::Validation::Message.new('root error', path: [nil]))
|
||||
result.add_error(Dry::Validation::Message.new("root error", path: [nil]))
|
||||
expect(result.errors).not_to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#inspect' do
|
||||
describe "#inspect" do
|
||||
let(:params) do
|
||||
double(:params, message_set: [], to_h: {})
|
||||
end
|
||||
|
||||
let(:context) do
|
||||
context = Concurrent::Map.new
|
||||
context[:data] = 'foo'
|
||||
context[:data] = "foo"
|
||||
context
|
||||
end
|
||||
|
||||
|
@ -65,7 +65,7 @@ RSpec.describe Dry::Validation::Result do
|
|||
Dry::Validation::Result.new(params, context)
|
||||
end
|
||||
|
||||
example 'results are inspectable' do
|
||||
example "results are inspectable" do
|
||||
expect(result.inspect).to be_a(String)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require_relative 'support/coverage'
|
||||
require_relative 'support/warnings'
|
||||
require_relative "support/coverage"
|
||||
require_relative "support/warnings"
|
||||
|
||||
begin
|
||||
require 'pry'
|
||||
require 'pry-byebug'
|
||||
require "pry"
|
||||
require "pry-byebug"
|
||||
rescue LoadError
|
||||
end
|
||||
|
||||
require 'i18n'
|
||||
require 'dry/validation'
|
||||
require "i18n"
|
||||
require "dry/validation"
|
||||
|
||||
SPEC_ROOT = Pathname(__dir__)
|
||||
|
||||
Dir[SPEC_ROOT.join('support/**/*.rb')].each(&method(:require))
|
||||
Dir[SPEC_ROOT.join("support/**/*.rb")].each(&method(:require))
|
||||
|
||||
RSpec.configure do |config|
|
||||
unless RUBY_VERSION >= '2.7'
|
||||
config.exclude_pattern = '**/pattern_matching_spec.rb'
|
||||
unless RUBY_VERSION >= "2.7"
|
||||
config.exclude_pattern = "**/pattern_matching_spec.rb"
|
||||
end
|
||||
|
||||
config.disable_monkey_patching!
|
||||
|
||||
config.before do
|
||||
stub_const('Test', Module.new)
|
||||
stub_const("Test", Module.new)
|
||||
end
|
||||
|
||||
config.after do
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'dry/validation/values'
|
||||
require "dry/validation/values"
|
||||
|
||||
RSpec.describe Dry::Validation::Values do
|
||||
subject(:values) do
|
||||
|
@ -8,92 +8,92 @@ RSpec.describe Dry::Validation::Values do
|
|||
end
|
||||
|
||||
let(:data) do
|
||||
{ name: 'Jane', address: { city: 'Paris', geo: { lat: 1, lon: 2 } }, phones: [123, 431] }
|
||||
{name: "Jane", address: {city: "Paris", geo: {lat: 1, lon: 2}}, phones: [123, 431]}
|
||||
end
|
||||
|
||||
describe '#[]' do
|
||||
it 'works with a symbol' do
|
||||
expect(values[:name]).to eql('Jane')
|
||||
describe "#[]" do
|
||||
it "works with a symbol" do
|
||||
expect(values[:name]).to eql("Jane")
|
||||
end
|
||||
|
||||
it 'works with a dot-notation path' do
|
||||
expect(values['address.city']).to eql('Paris')
|
||||
it "works with a dot-notation path" do
|
||||
expect(values["address.city"]).to eql("Paris")
|
||||
end
|
||||
|
||||
it 'works with a path' do
|
||||
expect(values[:address, :city]).to eql('Paris')
|
||||
it "works with a path" do
|
||||
expect(values[:address, :city]).to eql("Paris")
|
||||
end
|
||||
|
||||
it 'works with a hash' do
|
||||
expect(values[address: :city]).to eql('Paris')
|
||||
it "works with a hash" do
|
||||
expect(values[address: :city]).to eql("Paris")
|
||||
end
|
||||
|
||||
it 'works with a hash pointing to multiple values' do
|
||||
expect(values[address: { geo: [:lat, :lon] }]).to eql([1, 2])
|
||||
it "works with a hash pointing to multiple values" do
|
||||
expect(values[address: {geo: [:lat, :lon]}]).to eql([1, 2])
|
||||
end
|
||||
|
||||
it 'works with an array' do
|
||||
expect(values[%i[address city]]).to eql('Paris')
|
||||
it "works with an array" do
|
||||
expect(values[%i[address city]]).to eql("Paris")
|
||||
end
|
||||
|
||||
it 'raises on unpexpected argument type' do
|
||||
it "raises on unpexpected argument type" do
|
||||
expect { values[123] }
|
||||
.to raise_error(
|
||||
ArgumentError, '+key+ must be a valid path specification'
|
||||
ArgumentError, "+key+ must be a valid path specification"
|
||||
)
|
||||
end
|
||||
|
||||
it 'accepts missing keys returning nil' do
|
||||
expect(values[address: { geo: [:population, :lon] }]).to eql([nil, 2])
|
||||
it "accepts missing keys returning nil" do
|
||||
expect(values[address: {geo: [:population, :lon]}]).to eql([nil, 2])
|
||||
end
|
||||
end
|
||||
|
||||
describe '#key?' do
|
||||
it 'returns true when a symbol key is present' do
|
||||
describe "#key?" do
|
||||
it "returns true when a symbol key is present" do
|
||||
expect(values.key?(:name)).to be(true)
|
||||
end
|
||||
|
||||
it 'returns false when a symbol key is not present' do
|
||||
it "returns false when a symbol key is not present" do
|
||||
expect(values.key?(:not_here)).to be(false)
|
||||
end
|
||||
|
||||
it 'returns true when a nested key is present' do
|
||||
it "returns true when a nested key is present" do
|
||||
expect(values.key?([:address, :city])).to be(true)
|
||||
end
|
||||
|
||||
it 'returns false when a nested key is not present' do
|
||||
it "returns false when a nested key is not present" do
|
||||
expect(values.key?([:address, :not_here])).to be(false)
|
||||
end
|
||||
|
||||
it 'returns true when nested keys are all present' do
|
||||
it "returns true when nested keys are all present" do
|
||||
expect(values.key?([:address, :geo, [:lat, :lon]])).to be(true)
|
||||
end
|
||||
|
||||
it 'returns false when nested keys are not all present' do
|
||||
it "returns false when nested keys are not all present" do
|
||||
expect(values.key?([:address, :geo, [:lat, :lon, :other]])).to be(false)
|
||||
end
|
||||
|
||||
it 'returns true when a path to an array element is present' do
|
||||
it "returns true when a path to an array element is present" do
|
||||
expect(values.key?([:phones, 1])).to be(true)
|
||||
end
|
||||
|
||||
it 'returns false when a path to an array element is not present' do
|
||||
it "returns false when a path to an array element is not present" do
|
||||
expect(values.key?([:phones, 5])).to be(false)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#dig' do
|
||||
it 'returns a value from a nested hash when it exists' do
|
||||
expect(values.dig(:address, :city)).to eql('Paris')
|
||||
describe "#dig" do
|
||||
it "returns a value from a nested hash when it exists" do
|
||||
expect(values.dig(:address, :city)).to eql("Paris")
|
||||
end
|
||||
|
||||
it 'returns nil otherwise' do
|
||||
it "returns nil otherwise" do
|
||||
expect(values.dig(:oops, :not_here)).to be(nil)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#method_missing' do
|
||||
it 'forwards to data' do
|
||||
describe "#method_missing" do
|
||||
it "forwards to data" do
|
||||
result = []
|
||||
|
||||
values.each do |k, v|
|
||||
|
@ -103,14 +103,14 @@ RSpec.describe Dry::Validation::Values do
|
|||
expect(result).to eql(values.to_a)
|
||||
end
|
||||
|
||||
it 'raises NoMethodError when data does not respond to the meth' do
|
||||
it "raises NoMethodError when data does not respond to the meth" do
|
||||
expect { values.not_really_implemented }
|
||||
.to raise_error(NoMethodError, /not_really_implemented/)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#method' do
|
||||
it 'returns Method objects for a forwarded method' do
|
||||
describe "#method" do
|
||||
it "returns Method objects for a forwarded method" do
|
||||
expect(values.method(:dig)).to be_instance_of(Method)
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue