rspec-validates_timeliness 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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