rspec-validates_timeliness 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e33418e0bc1ca0d9159d7261d703e400d64c5580
4
+ data.tar.gz: d07b63180655408b4919558a75bf3e001ab186bc
5
+ SHA512:
6
+ metadata.gz: 533b1d9f4d0737feaee37c26ef12a0d66d67c28e213b743c7fb11a697af7d0affc1b33a92a6f044a152ab1f510b6c265e2b595045f92d6a33252a0d6cb4ee945
7
+ data.tar.gz: 1898aba67ad2dcc7ba31da36cee42b726efa18a88aedfa6e51a876e81c51d90960b4fcdc90b3d95fd860a6f855b295e4c7234cfc6480af135526c63a09d1804d
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.1
5
+ before_install: gem install bundler -v 1.12.5
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Yoshiyuki Hirano
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # RSpec::ValidatesTimeliness
2
+
3
+ Simple RSpec matchers for [validates_timeliness](https://github.com/adzap/validates_timeliness)
4
+
5
+ ## Matchers
6
+
7
+ - **validates_timeliness_of** tests usage of validates_timeliness
8
+ - **validates_datetime** tests usage of `validates_datetime` (alias of `validates_timeliness_of`).
9
+ - **validates_date** tests usage of `validates_date` (alias of `validates_timeliness_of`).
10
+ - **validates_time** tests usage of `validate_time` (alias of `validates_timeliness_of`).
11
+
12
+ ## Installation
13
+
14
+ Add this line to your application's Gemfile:
15
+
16
+ ```ruby
17
+ gem 'rspec-validates_timeliness'
18
+ ```
19
+
20
+ And then execute:
21
+
22
+ $ bundle
23
+
24
+ Or install it yourself as:
25
+
26
+ $ gem install rspec-validates_timeliness
27
+
28
+ ## Usage
29
+
30
+ Here is model:
31
+
32
+ ```ruby
33
+ class Person
34
+ include ActiveModel::model
35
+
36
+ validates_date :date_of_birth, before: lambda { 18.years.ago }
37
+ validates_time :breakfast_time, is_at: '7:00am'
38
+ validates_time :updated_at, between: ['9:00am', '5:00pm']
39
+
40
+ # validates_datetime :start_time, before: :finish_time **[CAUTION] Method symbol is not support**
41
+ # validates_date :created_at, on_or_after: :today **[CAUTION] Shorthand is not support**
42
+ end
43
+ ```
44
+
45
+ And with `rspec-validates_timeliness` we can now make simple assertions about those models:
46
+
47
+ ```ruby
48
+ require 'spec_helper'
49
+
50
+ describe Person, type: :model do
51
+ it { is_expected.to validates_date(:date_of_birth).before { 18.years.ago.to_date } }
52
+ it { is_expected.to validates_time(:breakfast_time).is_at('7:00am') }
53
+ it { is_expected.to validates_time(:updated_at).between(['9:00am', '5:00pm']) }
54
+ end
55
+ ```
56
+
57
+ ## Contributing
58
+
59
+ 1. Fork it
60
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
61
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
62
+ 4. Push to the branch (`git push origin my-new-feature`)
63
+ 5. Create new Pull Request
64
+
65
+ ## Changelog
66
+
67
+ * Release 0.0.1 (Jun 12, 2016)
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "rspec-validates_timeliness"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ require "pry"
10
+ Pry.start
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,7 @@
1
+ require 'rspec/core'
2
+ require 'rspec-validates_timeliness/matchers'
3
+ require 'rspec-validates_timeliness/version'
4
+
5
+ RSpec.configure do |config|
6
+ config.include RSpec::ValidatesTimeliness::Matchers
7
+ end
@@ -0,0 +1,15 @@
1
+ require 'active_support'
2
+ require 'active_support/core_ext'
3
+ require 'timecop'
4
+
5
+ require 'rspec-validates_timeliness/matchers/expected_value'
6
+ require 'rspec-validates_timeliness/matchers/message_builder'
7
+ require 'rspec-validates_timeliness/matchers/validation_matcher'
8
+ require 'rspec-validates_timeliness/matchers/validator_proxy'
9
+
10
+ module RSpec
11
+ module ValidatesTimeliness
12
+ module Matchers
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,44 @@
1
+ module RSpec::ValidatesTimeliness
2
+ module Matchers
3
+ class ExpectedValue
4
+ def initialize(value)
5
+ @value = evaluate(value)
6
+ end
7
+
8
+ def equal
9
+ @equal ||= value
10
+ end
11
+
12
+ def over
13
+ case value
14
+ when Time, DateTime
15
+ value + 1.second
16
+ when Date
17
+ value + 1.day
18
+ end
19
+ end
20
+
21
+ def under
22
+ case value
23
+ when Time, DateTime
24
+ value - 1.second
25
+ when Date
26
+ value - 1.day
27
+ end
28
+ end
29
+
30
+ private
31
+
32
+ attr_reader :value
33
+
34
+ def evaluate(value)
35
+ case value
36
+ when Proc then value.call
37
+ when Time, DateTime, Date then value
38
+ when String then value.to_time
39
+ else nil
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,28 @@
1
+ module RSpec::ValidatesTimeliness
2
+ module Matchers
3
+ class MessageBuilder
4
+ def initialize(base_message)
5
+ @base_message = base_message
6
+ @option_messages = []
7
+ end
8
+
9
+ def full_message
10
+ [base_message, option_message].join(' ')
11
+ end
12
+
13
+ alias to_s full_message
14
+
15
+ def <<(text)
16
+ option_messages << text
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :base_message, :option_messages
22
+
23
+ def option_message
24
+ option_messages.join(' and ')
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,143 @@
1
+ module RSpec::ValidatesTimeliness
2
+ module Matchers
3
+ def validates_timeliness_of(attr_name)
4
+ ValidationMatcher.new(attr_name)
5
+ end
6
+
7
+ alias validates_date validates_timeliness_of
8
+ alias validates_time validates_timeliness_of
9
+ alias validates_datetime validates_timeliness_of
10
+
11
+ class ValidationMatcher
12
+ attr_reader :description
13
+
14
+ def initialize(attr_name)
15
+ @attr_name = attr_name
16
+ @options = {}
17
+ @description = MessageBuilder.new(base_description)
18
+ end
19
+
20
+ def is_at(value = nil, &block)
21
+ options[__method__] = block_given? ? block : value
22
+ self
23
+ end
24
+
25
+ def after(value = nil, &block)
26
+ options[__method__] = block_given? ? block : value
27
+ self
28
+ end
29
+
30
+ def on_or_after(value = nil, &block)
31
+ options[__method__] = block_given? ? block : value
32
+ self
33
+ end
34
+
35
+ def before(value = nil, &block)
36
+ options[__method__] = block_given? ? block : value
37
+ self
38
+ end
39
+
40
+ def on_or_before(value = nil, &block)
41
+ options[__method__] = block_given? ? block : value
42
+ self
43
+ end
44
+
45
+ def between(value)
46
+ case value
47
+ when Array, Range
48
+ options[:on_or_after] = value.first
49
+ options[value.is_a?(Range) && value.exclude_end? ? :before : :on_or_before] = value.last
50
+ end
51
+
52
+ self
53
+ end
54
+
55
+ def matches?(subject)
56
+ @subject = subject
57
+
58
+ attribute_exist? && all_options_correct?
59
+ end
60
+
61
+ def failure_message
62
+ "Expected #{description}"
63
+ end
64
+
65
+ def failure_message_when_negated
66
+ "Did not expect #{description}"
67
+ end
68
+
69
+ private
70
+
71
+ attr_reader :attr_name, :options, :subject
72
+
73
+ def base_description
74
+ "validate that :#{attr_name} must be"
75
+ end
76
+
77
+ def attribute_exist?
78
+ subject.respond_to?(attr_name)
79
+ end
80
+
81
+ def all_options_correct?
82
+ options.compact.keys.all? do |option_name|
83
+ send(:"#{option_name}_correct?")
84
+ end
85
+ end
86
+
87
+ def run_correct
88
+ Timecop.freeze
89
+ yield
90
+ ensure
91
+ Timecop.return
92
+ end
93
+
94
+ def is_at_correct?
95
+ run_correct do
96
+ value = ExpectedValue.new(options[:is_at])
97
+ description << "at #{value.equal}"
98
+ valid?(value.equal) && invalid?(value.over) && invalid?(value.under)
99
+ end
100
+ end
101
+
102
+ def after_correct?
103
+ run_correct do
104
+ value = ExpectedValue.new(options[:after])
105
+ description << "after #{value.equal}"
106
+ valid?(value.over) && invalid?(value.equal) && invalid?(value.under)
107
+ end
108
+ end
109
+
110
+ def on_or_after_correct?
111
+ run_correct do
112
+ value = ExpectedValue.new(options[:on_or_after])
113
+ description << "on or after #{value.equal}"
114
+ valid?(value.equal) && valid?(value.over) && invalid?(value.under)
115
+ end
116
+ end
117
+
118
+ def before_correct?
119
+ run_correct do
120
+ value = ExpectedValue.new(options[:before])
121
+ description << "before #{value.equal}"
122
+ valid?(value.under) && invalid?(value.equal) && invalid?(value.over)
123
+ end
124
+ end
125
+
126
+ def on_or_before_correct?
127
+ run_correct do
128
+ value = ExpectedValue.new(options[:on_or_before])
129
+ description << "on or before #{value.equal}"
130
+ valid?(value.equal) && valid?(value.under) && invalid?(value.over)
131
+ end
132
+ end
133
+
134
+ def validator_proxy
135
+ @validator_proxy ||= ValidatorProxy.new(subject, attr_name)
136
+ end
137
+
138
+ delegate :valid?, to: :validator_proxy
139
+ delegate :invalid?, to: :validator_proxy
140
+ end
141
+ end
142
+ end
143
+
@@ -0,0 +1,36 @@
1
+ module RSpec::ValidatesTimeliness
2
+ module Matchers
3
+ class ValidatorProxy
4
+ def initialize(model, attr_name)
5
+ @model = model
6
+ @attr_name = attr_name
7
+ end
8
+
9
+ def valid?(value)
10
+ set_value(value)
11
+ validate!
12
+ error_message.blank?
13
+ end
14
+
15
+ def invalid?(value)
16
+ !valid?(value)
17
+ end
18
+
19
+ private
20
+
21
+ attr_reader :model, :attr_name
22
+
23
+ def set_value(value)
24
+ model.instance_variable_set(:"@#{attr_name}", value)
25
+ end
26
+
27
+ def validate!
28
+ model.validate
29
+ end
30
+
31
+ def error_message
32
+ model.errors.messages[attr_name]
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,5 @@
1
+ module RSpec
2
+ module ValidatesTimeliness
3
+ VERSION = '0.1.0'.freeze
4
+ end
5
+ end
@@ -0,0 +1,31 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'rspec-validates_timeliness/version'
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.platform = Gem::Platform::RUBY
7
+ gem.name = "rspec-validates_timeliness"
8
+ gem.version = RSpec::ValidatesTimeliness::VERSION
9
+ gem.summary = %q{Simple RSpec matchers for validates_timeliness}
10
+ gem.description = %q{Simple RSpec matchers for validates_timeliness}
11
+
12
+ gem.required_ruby_version = ">= 2.1.0"
13
+
14
+ gem.authors = ["Yoshiyuki Hirano"]
15
+ gem.email = ["yhirano@aiming-inc.com"]
16
+ gem.homepage = "https://github.com/yhirano55/rspec-validates_timeliness"
17
+
18
+ gem.files = `git ls-files`.split($/)
19
+ gem.executables = gem.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
21
+ gem.require_paths = ["lib"]
22
+
23
+ gem.add_dependency "rspec", ">= 3.0"
24
+ gem.add_dependency "validates_timeliness", "~> 4.0"
25
+ gem.add_dependency "timecop", ">= 0.8.0"
26
+ gem.add_dependency "activesupport", ">= 4.0"
27
+
28
+ gem.add_development_dependency "rake", "~> 10.0"
29
+ gem.add_development_dependency "pry"
30
+ gem.add_development_dependency "activemodel", ">= 4.0"
31
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ class ValidatesDate
4
+ include ActiveModel::Model
5
+
6
+ attr_reader :date_of_birth, :date_of_start, :date_of_finish, :date_of_expiry
7
+
8
+ validates_date :date_of_birth, is_at: lambda { Date.current }
9
+ validates_date :date_of_start, after: lambda { 1.week.ago }, before: lambda { 1.week.since }
10
+ validates_date :date_of_finish, on_or_after: lambda { 1.year.ago }, on_or_before: lambda { 1.year.since }
11
+ validates_date :date_of_expiry, between: [3.days.ago, 3.days.since]
12
+ end
13
+
14
+ describe ValidatesDate do
15
+ it { is_expected.to validates_date(:date_of_birth).is_at { Date.current } }
16
+ it { is_expected.to validates_date(:date_of_start).after { 1.week.ago.to_date }.before { 1.week.since.to_date } }
17
+ it { is_expected.to validates_date(:date_of_finish).on_or_after { 1.year.ago.to_date }.on_or_before { 1.year.since.to_date } }
18
+ it { is_expected.to validates_date(:date_of_expiry).between([3.days.ago.to_date, 3.days.since.to_date]) }
19
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ class ValidatesDateTime
4
+ include ActiveModel::Model
5
+
6
+ attr_reader :started_at, :finished_at, :created_at, :updated_at
7
+
8
+ validates_datetime :started_at, is_at: lambda { DateTime.current }
9
+ validates_datetime :finished_at, after: lambda { 1.week.ago.to_datetime }, before: lambda { 1.week.since.to_datetime }
10
+ validates_datetime :created_at, on_or_after: lambda { 1.year.ago.to_datetime }, on_or_before: lambda { 1.year.since.to_datetime }
11
+ validates_datetime :updated_at, between: [DateTime.new(2008, 9, 1, 10, 5, 0), DateTime.new(2009, 4, 1, 0, 30, 0)]
12
+ end
13
+
14
+ describe ValidatesDateTime do
15
+ it { is_expected.to validates_datetime(:started_at).is_at { DateTime.current } }
16
+ it { is_expected.to validates_datetime(:finished_at).after { 1.week.ago.to_datetime }.before { 1.week.since.to_datetime } }
17
+ it { is_expected.to validates_datetime(:created_at).on_or_after { 1.year.ago.to_datetime }.on_or_before { 1.year.since.to_datetime } }
18
+ it { is_expected.to validates_datetime(:updated_at).between([DateTime.new(2008, 9, 1, 10, 5, 0), DateTime.new(2009, 4, 1, 0, 30, 0)]) }
19
+ end
@@ -0,0 +1,19 @@
1
+ require 'spec_helper'
2
+
3
+ class ValidatesTime
4
+ include ActiveModel::Model
5
+
6
+ attr_reader :started_at, :finished_at, :created_at, :updated_at
7
+
8
+ validates_time :started_at, is_at: '9:00am'
9
+ validates_time :finished_at, after: '11:00am', before: '1:00pm'
10
+ validates_time :created_at, on_or_after: '6:00am', on_or_before: '8:00am'
11
+ validates_time :updated_at, between: ['10:00am', '5:00pm']
12
+ end
13
+
14
+ describe ValidatesTime do
15
+ it { is_expected.to validates_time(:started_at).is_at('9:00am') }
16
+ it { is_expected.to validates_time(:finished_at).after('11:00am').before('1:00pm') }
17
+ it { is_expected.to validates_time(:created_at).on_or_after('6:00am').on_or_before('8:00am') }
18
+ it { is_expected.to validates_time(:updated_at).between(['10:00am', '5:00pm']) }
19
+ end
@@ -0,0 +1,103 @@
1
+ require 'spec_helper'
2
+
3
+ describe RSpec::ValidatesTimeliness::Matchers::ExpectedValue do
4
+ describe '#equal' do
5
+ let(:result) { Date.current }
6
+ let(:model) { described_class.new(result) }
7
+
8
+ subject { model.equal }
9
+
10
+ it { is_expected.to eq result }
11
+ end
12
+
13
+ describe '#over' do
14
+ let(:model) { described_class.new(value) }
15
+
16
+ subject { model.over }
17
+
18
+ context 'value is kind of Date' do
19
+ let(:value) { Date.current }
20
+ let(:result) { value + 1.day }
21
+
22
+ it 'returns value + 1.day (tomorrow)' do
23
+ is_expected.to eq result
24
+ end
25
+ end
26
+
27
+ context 'value is not kind of Date' do
28
+ let(:value) { DateTime.current }
29
+ let(:result) { value + 1.second }
30
+
31
+ it 'returns value + 1.second' do
32
+ is_expected.to eq result
33
+ end
34
+ end
35
+ end
36
+
37
+ describe '#under' do
38
+ let(:model) { described_class.new(value) }
39
+
40
+ subject { model.under }
41
+
42
+ context 'value is kind of Date' do
43
+ let(:value) { Date.current }
44
+ let(:result) { value - 1.day }
45
+
46
+ it 'returns value - 1.day (yesterday)' do
47
+ is_expected.to eq result
48
+ end
49
+ end
50
+
51
+ context 'value is not kind of Date' do
52
+ let(:value) { DateTime.current }
53
+ let(:result) { value - 1.second }
54
+
55
+ it 'returns value - 1.second' do
56
+ is_expected.to eq result
57
+ end
58
+ end
59
+ end
60
+
61
+ describe '#evaluate' do
62
+ let(:model) { described_class.new(nil) }
63
+
64
+ subject { model.send(:evaluate, value) }
65
+
66
+ context 'velue is kind of Proc' do
67
+ let(:value) { proc { Date.today } }
68
+
69
+ it { is_expected.to eq value.call }
70
+ end
71
+
72
+ context 'value is kind of Time' do
73
+ let(:value) { Time.now }
74
+
75
+ it { is_expected.to eq value }
76
+ end
77
+
78
+ context 'value is kind of DateTime' do
79
+ let(:value) { DateTime.current }
80
+
81
+ it { is_expected.to eq value }
82
+ end
83
+
84
+ context 'value is kind of Date' do
85
+ let(:value) { Date.current }
86
+
87
+ it { is_expected.to eq value }
88
+ end
89
+
90
+ context 'value is kind of String' do
91
+ let(:value) { '9:00am' }
92
+ let(:result) { value.to_time }
93
+
94
+ it { is_expected.to eq result }
95
+ end
96
+
97
+ context 'value is not kind of Proc, Time, DateTime, Date' do
98
+ let(:value) { 12345 }
99
+
100
+ it { is_expected.to be_nil }
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+
3
+ describe RSpec::ValidatesTimeliness::Matchers::MessageBuilder do
4
+ describe '#full_message' do
5
+ let(:model) { described_class.new(base_message) }
6
+ let(:base_message) { 'abc' }
7
+ let(:option_messages) { %w(123 456 789) }
8
+ let(:result) { 'abc 123 and 456 and 789' }
9
+
10
+ before do
11
+ option_messages.each do |text|
12
+ model << text
13
+ end
14
+ end
15
+
16
+ subject { model.full_message }
17
+
18
+ it 'returns exactly full message' do
19
+ is_expected.to eq result
20
+ end
21
+ end
22
+
23
+ describe '#<<' do
24
+ let(:model) { described_class.new(nil) }
25
+ let(:text) { 'abc' }
26
+
27
+ before { model << text }
28
+
29
+ subject { model.instance_variable_get(:@option_messages) }
30
+
31
+ it 'pushes text to @option_messages' do
32
+ is_expected.to eq [text]
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,97 @@
1
+ require 'spec_helper'
2
+
3
+ describe RSpec::ValidatesTimeliness::Matchers::ValidationMatcher do
4
+ let(:attr_name) { :one }
5
+ let(:model) { described_class.new(attr_name) }
6
+
7
+ %i(is_at after on_or_after before on_or_before).each do |option_name|
8
+ describe "##{option_name}" do
9
+ shared_examples 'exactly chain' do
10
+ it 'returns itself' do
11
+ is_expected.to eq model
12
+ options = model.instance_variable_get(:@options)
13
+ expect(options[option_name]).to eq value
14
+ end
15
+ end
16
+
17
+ subject { model.try(option_name, value) }
18
+
19
+ context 'with not block given' do
20
+ let(:value) { Date.current }
21
+
22
+ it_behaves_like 'exactly chain'
23
+ end
24
+
25
+ context 'with block given' do
26
+ let(:value) { proc { Date.current } }
27
+
28
+ it_behaves_like 'exactly chain'
29
+ end
30
+ end
31
+ end
32
+
33
+ describe '#between' do
34
+ shared_examples 'exactly chain' do
35
+ it 'returns itself' do
36
+ is_expected.to eq model
37
+ options = model.instance_variable_get(:@options)
38
+ expect(options[:on_or_after]).to eq value.first
39
+ key = value.is_a?(Range) && value.exclude_end? ? :before : :on_or_before
40
+ expect(options[key]).to eq value.last
41
+ end
42
+ end
43
+
44
+ subject { model.between(value) }
45
+
46
+ context 'value is kind of Array' do
47
+ let(:value) { [1.week.ago.to_date, 1.week.since.to_date] }
48
+
49
+ it_behaves_like 'exactly chain'
50
+ end
51
+
52
+ context 'value is kind of Range' do
53
+ context 'with exclude_end' do
54
+ let(:value) { 1.week.ago.to_date..1.week.since.to_date }
55
+
56
+ it_behaves_like 'exactly chain'
57
+ end
58
+
59
+ context 'with not exclude_end' do
60
+ let(:value) { 1.week.ago.to_date...1.week.since.to_date }
61
+
62
+ it_behaves_like 'exactly chain'
63
+ end
64
+ end
65
+ end
66
+
67
+ describe '#matches' do
68
+ let(:expected) { nil }
69
+
70
+ before do
71
+ expect(model).to receive(:attribute_exist?).and_return(true)
72
+ expect(model).to receive(:all_options_correct?).and_return(true)
73
+ end
74
+
75
+ subject { model.matches?(expected) }
76
+
77
+ it { is_expected.to be_truthy }
78
+ end
79
+
80
+ describe '#failure_message' do
81
+ let(:base_description) { "validate that :#{attr_name} must be" }
82
+ let(:result) { "Expected #{base_description}" }
83
+
84
+ subject { model.failure_message }
85
+
86
+ it { is_expected.to match result }
87
+ end
88
+
89
+ describe '#failure_message_when_negated' do
90
+ let(:base_description) { "validate that :#{attr_name} must be" }
91
+ let(:result) { "Did not expect #{base_description}" }
92
+
93
+ subject { model.failure_message_when_negated }
94
+
95
+ it { is_expected.to match result }
96
+ end
97
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe RSpec::ValidatesTimeliness::Matchers::ValidatorProxy do
4
+ before do
5
+ class DummyModel
6
+ include ActiveModel::Model
7
+ attr_reader :one
8
+ validates :one, presence: true
9
+ end
10
+ end
11
+
12
+ let(:model) { DummyModel.new }
13
+ let(:attr_name) { :one }
14
+ let(:proxy) { described_class.new(model, attr_name) }
15
+
16
+ describe '#valid?' do
17
+ subject { proxy.valid?(value) }
18
+
19
+ context 'with valid' do
20
+ let(:value) { true }
21
+
22
+ it { is_expected.to be_truthy }
23
+ end
24
+
25
+ context 'with invalid' do
26
+ let(:value) { nil }
27
+
28
+ it { is_expected.to be_falsey }
29
+ end
30
+ end
31
+
32
+ describe '#invalid?' do
33
+ subject { proxy.invalid?(value) }
34
+
35
+ context 'with invalid' do
36
+ let(:value) { nil }
37
+
38
+ it { is_expected.to be_truthy }
39
+ end
40
+
41
+ context 'with valid' do
42
+ let(:value) { true }
43
+
44
+ it { is_expected.to be_falsey }
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe RSpec::ValidatesTimeliness::Matchers do
4
+ describe '#validates_timeliness_of' do
5
+ before do
6
+ class DummyModel
7
+ include RSpec::ValidatesTimeliness::Matchers
8
+ end
9
+ end
10
+
11
+ let(:model) { DummyModel.new }
12
+ let(:attr_name) { :one }
13
+
14
+ subject { model.validates_timeliness_of(attr_name) }
15
+
16
+ it { is_expected.to be_kind_of(RSpec::ValidatesTimeliness::Matchers::ValidationMatcher) }
17
+ end
18
+ end
@@ -0,0 +1,6 @@
1
+ require 'spec_helper'
2
+
3
+ describe RSpec::ValidatesTimeliness do
4
+ subject { described_class }
5
+ it { is_expected.to eq RSpec::ValidatesTimeliness }
6
+ end
@@ -0,0 +1,12 @@
1
+ require 'rspec-validates_timeliness'
2
+
3
+ # dependencies
4
+ require 'active_model'
5
+ require 'validates_timeliness'
6
+
7
+ # debug
8
+ require 'pry'
9
+
10
+ RSpec.configure do |config|
11
+ config.order = :random
12
+ end
metadata ADDED
@@ -0,0 +1,180 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rspec-validates_timeliness
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Yoshiyuki Hirano
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-06-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: validates_timeliness
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '4.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: timecop
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.8.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 0.8.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: activesupport
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '4.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '4.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '10.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '10.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: activemodel
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '4.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '4.0'
111
+ description: Simple RSpec matchers for validates_timeliness
112
+ email:
113
+ - yhirano@aiming-inc.com
114
+ executables:
115
+ - console
116
+ - setup
117
+ extensions: []
118
+ extra_rdoc_files: []
119
+ files:
120
+ - ".gitignore"
121
+ - ".rspec"
122
+ - ".travis.yml"
123
+ - Gemfile
124
+ - LICENSE.txt
125
+ - README.md
126
+ - Rakefile
127
+ - bin/console
128
+ - bin/setup
129
+ - lib/rspec-validates_timeliness.rb
130
+ - lib/rspec-validates_timeliness/matchers.rb
131
+ - lib/rspec-validates_timeliness/matchers/expected_value.rb
132
+ - lib/rspec-validates_timeliness/matchers/message_builder.rb
133
+ - lib/rspec-validates_timeliness/matchers/validation_matcher.rb
134
+ - lib/rspec-validates_timeliness/matchers/validator_proxy.rb
135
+ - lib/rspec-validates_timeliness/version.rb
136
+ - rspec-validates_timeliness.gemspec
137
+ - spec/acceptance/validates_date_spec.rb
138
+ - spec/acceptance/validates_date_time_spec.rb
139
+ - spec/acceptance/validates_time_spec.rb
140
+ - spec/lib/rspec-validates_timeliness/matchers/expected_value_spec.rb
141
+ - spec/lib/rspec-validates_timeliness/matchers/message_builder_spec.rb
142
+ - spec/lib/rspec-validates_timeliness/matchers/validation_matcher_spec.rb
143
+ - spec/lib/rspec-validates_timeliness/matchers/validator_proxy_spec.rb
144
+ - spec/lib/rspec-validates_timeliness/matchers_spec.rb
145
+ - spec/lib/rspec-validates_timeliness_spec.rb
146
+ - spec/spec_helper.rb
147
+ homepage: https://github.com/yhirano55/rspec-validates_timeliness
148
+ licenses: []
149
+ metadata: {}
150
+ post_install_message:
151
+ rdoc_options: []
152
+ require_paths:
153
+ - lib
154
+ required_ruby_version: !ruby/object:Gem::Requirement
155
+ requirements:
156
+ - - ">="
157
+ - !ruby/object:Gem::Version
158
+ version: 2.1.0
159
+ required_rubygems_version: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - ">="
162
+ - !ruby/object:Gem::Version
163
+ version: '0'
164
+ requirements: []
165
+ rubyforge_project:
166
+ rubygems_version: 2.5.1
167
+ signing_key:
168
+ specification_version: 4
169
+ summary: Simple RSpec matchers for validates_timeliness
170
+ test_files:
171
+ - spec/acceptance/validates_date_spec.rb
172
+ - spec/acceptance/validates_date_time_spec.rb
173
+ - spec/acceptance/validates_time_spec.rb
174
+ - spec/lib/rspec-validates_timeliness/matchers/expected_value_spec.rb
175
+ - spec/lib/rspec-validates_timeliness/matchers/message_builder_spec.rb
176
+ - spec/lib/rspec-validates_timeliness/matchers/validation_matcher_spec.rb
177
+ - spec/lib/rspec-validates_timeliness/matchers/validator_proxy_spec.rb
178
+ - spec/lib/rspec-validates_timeliness/matchers_spec.rb
179
+ - spec/lib/rspec-validates_timeliness_spec.rb
180
+ - spec/spec_helper.rb