-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Inclusion and exclusion validation specs.
- Loading branch information
1 parent
0f25554
commit ca351ae
Showing
5 changed files
with
219 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,28 @@ | ||
require File.join(File.dirname(__FILE__), 'clusivity.rb') | ||
|
||
module Errapi::Validations | ||
class Exclusion | ||
class Exclusion < Base | ||
include Clusivity | ||
|
||
def initialize options = {} | ||
@delimiter = options[:from] || options[:in] || options[:within] | ||
check_delimiter! ":from (or :in or :within)" | ||
unless key = exactly_one_option?(OPTIONS, options) | ||
raise ArgumentError, "Either :from or :in or :within must be supplied (but only one of them)." | ||
end | ||
|
||
@delimiter = options[key] | ||
check_delimiter! OPTIONS_DESCRIPTION | ||
end | ||
|
||
def validate value, context, options = {} | ||
allowed_values = members options[:source] | ||
if include? allowed_values, value | ||
context.add_error reason: :not_included, check_value: allowed_values | ||
excluded_values = members OPTIONS_DESCRIPTION, options | ||
if include? excluded_values, value | ||
context.add_error reason: :excluded, check_value: excluded_values | ||
end | ||
end | ||
|
||
private | ||
|
||
OPTIONS = %i(from in within) | ||
OPTIONS_DESCRIPTION = ":from (or :in or :within)" | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,28 @@ | ||
require File.join(File.dirname(__FILE__), 'clusivity.rb') | ||
|
||
module Errapi::Validations | ||
class Inclusion | ||
class Inclusion < Base | ||
include Clusivity | ||
|
||
def initialize options = {} | ||
@delimiter = options[:in] || options[:within] | ||
check_delimiter! ":in (or :within)" | ||
unless key = exactly_one_option?(OPTIONS, options) | ||
raise ArgumentError, "Either :in or :within must be supplied (but not both)." | ||
end | ||
|
||
@delimiter = options[key] | ||
check_delimiter! OPTIONS_DESCRIPTION | ||
end | ||
|
||
def validate value, context, options = {} | ||
excluded_values = members options[:source] | ||
unless include? excluded_values, value | ||
context.add_error reason: :excluded, check_value: excluded_values | ||
allowed_values = members OPTIONS_DESCRIPTION, options | ||
unless include? allowed_values, value | ||
context.add_error reason: :not_included, check_value: allowed_values | ||
end | ||
end | ||
|
||
private | ||
|
||
OPTIONS = %i(in within) | ||
OPTIONS_DESCRIPTION = ":in (or :within)" | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
require 'helper' | ||
|
||
RSpec.describe Errapi::Validations::Exclusion do | ||
let(:context){ double add_error: nil } | ||
let(:validation_options){ {} } | ||
subject{ described_class.new validation_options } | ||
|
||
it "should require at least one option to be set" do | ||
expect{ described_class.new }.to raise_error(/either :from or :in or :within/i) | ||
end | ||
|
||
it "should not accept an object without the #include? method as an option" do | ||
%i(in within).each do |option| | ||
[ nil, true, false, Object.new ].each do |invalid_option| | ||
expect{ described_class.new({ option => invalid_option }) }.to raise_error(/an object with the #include\? method/i) | ||
end | ||
end | ||
end | ||
|
||
describe "with a callable returning an invalid list" do | ||
let(:validation_options){ { from: Proc.new{ :foo } } } | ||
|
||
it "should raise an error when validating" do | ||
expect{ validate 'foo' }.to raise_error(/must return an object with the #include\? method/i) | ||
end | ||
end | ||
|
||
describe "with a symbol returning an invalid list" do | ||
let(:validation_options){ { from: :excluded_values } } | ||
|
||
it "should raise an error when validating" do | ||
expect{ validate 'foo', source: OpenStruct.new(excluded_values: :foo) }.to raise_error(/must return an object with the #include\? method/i) | ||
end | ||
end | ||
|
||
shared_examples_for "an exclusion validation" do | ||
let(:runtime_options){ {} } | ||
let(:validation_options){ { exclusion_option => %w(foo bar baz) } } | ||
|
||
it "should not accept a value in the supplied list" do | ||
%w(foo bar baz).each.with_index do |invalid_value,i| | ||
validate invalid_value, runtime_options | ||
expect(context).to have_received(:add_error).with(reason: :excluded, check_value: %w(foo bar baz)).exactly(i + 1).times | ||
end | ||
end | ||
|
||
it "should accept a value not in the supplied list" do | ||
%w(qux corge grault).each do |valid_value| | ||
validate valid_value, runtime_options | ||
expect(context).not_to have_received(:add_error) | ||
end | ||
end | ||
end | ||
|
||
shared_examples_for "a callable exclusion option" do | ||
describe "as a list" do | ||
let(:validation_options){ { from: %w(foo bar baz) } } | ||
it_should_behave_like "an exclusion validation" | ||
end | ||
|
||
describe "as a callable" do | ||
let(:validation_options){ { from: ->(source){ source.excluded_values } } } | ||
let(:runtime_options){ { source: OpenStruct.new(excluded_values: %w(foo bar baz)) } } | ||
it_should_behave_like "an exclusion validation" | ||
end | ||
|
||
describe "as a symbol" do | ||
let(:validation_options){ { from: :excluded_values } } | ||
let(:runtime_options){ { source: OpenStruct.new(excluded_values: %w(foo bar baz)) } } | ||
it_should_behave_like "an exclusion validation" | ||
end | ||
end | ||
|
||
describe "with the :from option" do | ||
let(:exclusion_option){ :from } | ||
it_should_behave_like "a callable exclusion option" | ||
end | ||
|
||
describe "with the :in option" do | ||
let(:exclusion_option){ :in } | ||
it_should_behave_like "a callable exclusion option" | ||
end | ||
|
||
describe "with the :within option" do | ||
let(:exclusion_option){ :within } | ||
it_should_behave_like "a callable exclusion option" | ||
end | ||
|
||
def validate value, options = {} | ||
subject.validate value, context, options | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
require 'helper' | ||
|
||
RSpec.describe Errapi::Validations::Inclusion do | ||
let(:context){ double add_error: nil } | ||
let(:validation_options){ {} } | ||
subject{ described_class.new validation_options } | ||
|
||
it "should require at least one option to be set" do | ||
expect{ described_class.new }.to raise_error(/either :in or :within/i) | ||
end | ||
|
||
it "should not accept an object without the #include? method as an option" do | ||
%i(in within).each do |option| | ||
[ nil, true, false, Object.new ].each do |invalid_option| | ||
expect{ described_class.new({ option => invalid_option }) }.to raise_error(/an object with the #include\? method/i) | ||
end | ||
end | ||
end | ||
|
||
describe "with a callable returning an invalid list" do | ||
let(:validation_options){ { in: Proc.new{ :foo } } } | ||
|
||
it "should raise an error when validating" do | ||
expect{ validate 'foo' }.to raise_error(/must return an object with the #include\? method/i) | ||
end | ||
end | ||
|
||
describe "with a symbol returning an invalid list" do | ||
let(:validation_options){ { in: :allowed_values } } | ||
|
||
it "should raise an error when validating" do | ||
expect{ validate 'foo', source: OpenStruct.new(allowed_values: :foo) }.to raise_error(/must return an object with the #include\? method/i) | ||
end | ||
end | ||
|
||
shared_examples_for "an inclusion validation" do | ||
let(:runtime_options){ {} } | ||
let(:validation_options){ { inclusion_option => %w(foo bar baz) } } | ||
|
||
it "should not accept a value not in the supplied list" do | ||
%w(qux corge grault).each.with_index do |invalid_value,i| | ||
validate invalid_value, runtime_options | ||
expect(context).to have_received(:add_error).with(reason: :not_included, check_value: %w(foo bar baz)).exactly(i + 1).times | ||
end | ||
end | ||
|
||
it "should accept a value in the supplied list" do | ||
%w(foo bar baz).each do |valid_value| | ||
validate valid_value, runtime_options | ||
expect(context).not_to have_received(:add_error) | ||
end | ||
end | ||
end | ||
|
||
shared_examples_for "a callable inclusion option" do | ||
describe "as a list" do | ||
let(:validation_options){ { in: %w(foo bar baz) } } | ||
it_should_behave_like "an inclusion validation" | ||
end | ||
|
||
describe "as a callable" do | ||
let(:validation_options){ { in: ->(source){ source.allowed_values } } } | ||
let(:runtime_options){ { source: OpenStruct.new(allowed_values: %w(foo bar baz)) } } | ||
it_should_behave_like "an inclusion validation" | ||
end | ||
|
||
describe "as a symbol" do | ||
let(:validation_options){ { in: :allowed_values } } | ||
let(:runtime_options){ { source: OpenStruct.new(allowed_values: %w(foo bar baz)) } } | ||
it_should_behave_like "an inclusion validation" | ||
end | ||
end | ||
|
||
describe "with the :in option" do | ||
let(:inclusion_option){ :in } | ||
it_should_behave_like "a callable inclusion option" | ||
end | ||
|
||
describe "with the :within option" do | ||
let(:inclusion_option){ :within } | ||
it_should_behave_like "a callable inclusion option" | ||
end | ||
|
||
def validate value, options = {} | ||
subject.validate value, context, options | ||
end | ||
end |