warp 1.0.1 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.rspec +3 -0
- data/.travis.yml +35 -8
- data/Appraisals +67 -0
- data/Gemfile +4 -5
- data/README.md +57 -8
- data/Rakefile +4 -1
- data/gemfiles/rails_3.2_rspec_2.14.gemfile +22 -0
- data/gemfiles/rails_3.2_rspec_2.99.0.beta1.gemfile +22 -0
- data/gemfiles/rails_3.2_rspec_3.0.0.beta1.gemfile +23 -0
- data/gemfiles/rails_3.2_rspec_master.gemfile +23 -0
- data/gemfiles/rails_4.0_rspec_2.14.gemfile +22 -0
- data/gemfiles/rails_4.0_rspec_2.99.0.beta1.gemfile +22 -0
- data/gemfiles/rails_4.0_rspec_3.0.0.beta1.gemfile +23 -0
- data/gemfiles/rails_4.0_rspec_master.gemfile +23 -0
- data/gemfiles/rails_4.1.0.beta1_rspec_2.14.gemfile +23 -0
- data/gemfiles/rails_4.1.0.beta1_rspec_2.99.0.beta1.gemfile +23 -0
- data/gemfiles/rails_4.1.0.beta1_rspec_3.0.0.beta1.gemfile +24 -0
- data/gemfiles/rails_4.1.0.beta1_rspec_master.gemfile +24 -0
- data/lib/warp/controller_matchers/assign_matcher.rb +1 -3
- data/lib/warp/controller_matchers/set_flash_matcher.rb +19 -14
- data/lib/warp/matcher.rb +30 -0
- data/lib/warp/model_matchers/association_matcher.rb +56 -0
- data/lib/warp/model_matchers/attribute_matcher.rb +32 -0
- data/lib/warp/model_matchers/error_matcher.rb +12 -0
- data/lib/warp/model_matchers/matcher.rb +15 -0
- data/lib/warp/model_matchers/validation_matcher.rb +12 -0
- data/lib/warp/model_matchers.rb +10 -0
- data/lib/warp/version.rb +13 -1
- data/lib/warp.rb +4 -1
- data/spec/spec_helper.rb +15 -6
- data/spec/support/failure_message_helpers.rb +23 -0
- data/spec/support/match_helpers.rb +24 -12
- data/spec/support/model_helpers.rb +25 -0
- data/spec/support/with_contexts_helpers.rb +6 -0
- data/spec/warp/controller_matchers/assign_matcher_spec.rb +35 -33
- data/spec/warp/controller_matchers/set_flash_matcher_spec.rb +4 -12
- data/spec/warp/model_helpers/association_matcher_spec.rb +102 -0
- data/spec/warp/model_helpers/attribute_matcher_spec.rb +43 -0
- data/warp.gemspec +2 -4
- metadata +31 -33
- data/gemfiles/rails-3.2 +0 -17
- data/gemfiles/rails-4.0 +0 -17
- data/gemfiles/rails-4.1 +0 -18
data/lib/warp/matcher.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
module Warp
|
2
|
+
class Matcher
|
3
|
+
# Composable matchers are new in RSpec 3.
|
4
|
+
# Define basic helpers in their absence.
|
5
|
+
if defined?(RSpec::Matchers::Composable)
|
6
|
+
include RSpec::Matchers::Composable
|
7
|
+
else
|
8
|
+
def description_of(object)
|
9
|
+
object.inspect
|
10
|
+
end
|
11
|
+
|
12
|
+
def values_match?(expected, actual)
|
13
|
+
expected === actual || actual == expected
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# RSpec 2 and 3 have different methods
|
18
|
+
# that they call on matcher to get the
|
19
|
+
# failure messages.
|
20
|
+
if RSpec::Version::STRING[0] == "2"
|
21
|
+
def failure_message_for_should
|
22
|
+
failure_message
|
23
|
+
end
|
24
|
+
|
25
|
+
def failure_message_for_should_not
|
26
|
+
failure_message_when_negated
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module Warp
|
2
|
+
module ModelMatchers
|
3
|
+
class AssociationMatcher < Warp::ModelMatchers::Matcher
|
4
|
+
attr_reader :macro, :key
|
5
|
+
attr_reader :failure_message, :failure_message_when_negated, :description
|
6
|
+
|
7
|
+
def initialize(macro, key)
|
8
|
+
@macro = macro
|
9
|
+
@key = key
|
10
|
+
end
|
11
|
+
|
12
|
+
def matches?(model_or_instance)
|
13
|
+
if association = model(model_or_instance).reflect_on_association(key)
|
14
|
+
actual_macro = association.macro
|
15
|
+
@failure_message = "expected to have association #{macro} :#{key}, but had #{actual_macro} :#{key}"
|
16
|
+
@failure_message_when_negated = "expected to not have association #{macro} :#{key}"
|
17
|
+
actual_macro == macro
|
18
|
+
else
|
19
|
+
@failure_message = "expected to have association #{macro} :#{key}"
|
20
|
+
@failure_message_when_negated = "expected to not have association #{macro} :#{key}"
|
21
|
+
false
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def model(model_or_instance)
|
28
|
+
if model_or_instance.is_a? Class
|
29
|
+
model_or_instance
|
30
|
+
else
|
31
|
+
model_or_instance.class
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def have_many(key)
|
37
|
+
AssociationMatcher.new(:has_many, key)
|
38
|
+
end
|
39
|
+
|
40
|
+
def have_one(key)
|
41
|
+
AssociationMatcher.new(:has_one, key)
|
42
|
+
end
|
43
|
+
|
44
|
+
def belong_to(key)
|
45
|
+
AssociationMatcher.new(:belongs_to, key)
|
46
|
+
end
|
47
|
+
|
48
|
+
def have_and_belong_to_many(key)
|
49
|
+
if ActiveRecord::VERSION::STRING[0] == "4" && ActiveRecord::VERSION::STRING[3] != "0"
|
50
|
+
raise NotImplementedError, "In Rail 4.1+ the has_and_belongs_to_many helper produces a has_many :through association."
|
51
|
+
else
|
52
|
+
AssociationMatcher.new(:has_and_belongs_to_many, key)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Warp
|
2
|
+
module ModelMatchers
|
3
|
+
class AttributeMatcher < Warp::ModelMatchers::Matcher
|
4
|
+
attr_reader :attr_name
|
5
|
+
attr_reader :failure_message, :failure_message_when_negated, :description
|
6
|
+
|
7
|
+
def initialize(attr_name)
|
8
|
+
@attr_name = attr_name.to_sym
|
9
|
+
end
|
10
|
+
|
11
|
+
def matches?(model_or_instance)
|
12
|
+
if attributes(model_or_instance).any? {|actual| values_match?(attr_name, actual) }
|
13
|
+
@failure_message = "expected to have attribute #{description_of(attr_name)}"
|
14
|
+
@failure_message_when_negated = "expected to not have attribute #{description_of(attr_name)}"
|
15
|
+
true
|
16
|
+
else
|
17
|
+
@failure_message = "expected to have attribute #{description_of(attr_name)}"
|
18
|
+
@failure_message_when_negated = "expected to not have attribute #{description_of(attr_name)}"
|
19
|
+
false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def attributes(model_or_instance)
|
24
|
+
model(model_or_instance).column_names.map(&:to_sym)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def have_attribute(attr_name)
|
29
|
+
AttributeMatcher.new(attr_name)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
require "warp/model_matchers/matcher"
|
2
|
+
|
3
|
+
require "warp/model_matchers/association_matcher"
|
4
|
+
require "warp/model_matchers/attribute_matcher"
|
5
|
+
# require "warp/model_matchers/error_matcher"
|
6
|
+
# require "warp/model_matchers/validation_matcher"
|
7
|
+
|
8
|
+
RSpec.configure do |config|
|
9
|
+
config.include Warp::ModelMatchers
|
10
|
+
end
|
data/lib/warp/version.rb
CHANGED
@@ -1,3 +1,15 @@
|
|
1
1
|
module Warp
|
2
|
-
VERSION
|
2
|
+
module VERSION
|
3
|
+
MAJOR = 1
|
4
|
+
MINOR = 1
|
5
|
+
PATCH = 0
|
6
|
+
|
7
|
+
BETA = nil
|
8
|
+
|
9
|
+
def self.to_s
|
10
|
+
version_str = [MAJOR, MINOR, PATCH].map(&:to_s).join(".")
|
11
|
+
version_str << ".beta#{BETA}" if BETA
|
12
|
+
version_str
|
13
|
+
end
|
14
|
+
end
|
3
15
|
end
|
data/lib/warp.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -1,4 +1,15 @@
|
|
1
|
-
require
|
1
|
+
require "bundler"
|
2
|
+
|
3
|
+
require "simplecov"
|
4
|
+
|
5
|
+
if ENV["TRAVIS_CI"]
|
6
|
+
require "coveralls"
|
7
|
+
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
|
8
|
+
end
|
9
|
+
|
10
|
+
SimpleCov.start do
|
11
|
+
add_filter "/spec/"
|
12
|
+
end
|
2
13
|
|
3
14
|
if ENV["TRAVIS_CI"]
|
4
15
|
Bundler.require
|
@@ -6,16 +17,14 @@ else
|
|
6
17
|
Bundler.require(:default, :tools)
|
7
18
|
end
|
8
19
|
|
9
|
-
require "active_support/all"
|
10
|
-
require "action_controller"
|
11
|
-
|
12
|
-
require "warp"
|
13
|
-
|
14
20
|
Dir[File.expand_path("../support/**/*.rb", __FILE__)].each {|f| require f }
|
15
21
|
|
16
22
|
RSpec.configure do |config|
|
17
23
|
config.order = 'random'
|
18
24
|
|
19
25
|
config.extend ControllerHelpers
|
26
|
+
config.extend FailureMessageHelpers
|
27
|
+
config.extend ModelHelpers
|
20
28
|
config.extend WithContextsHelpers
|
29
|
+
config.include MatchHelpers
|
21
30
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module FailureMessageHelpers
|
2
|
+
if RSpec::Version::STRING[0] == "3"
|
3
|
+
FAILURE_MESSAGE_METHOD = :failure_message
|
4
|
+
FAILURE_MESSAGE_WHEN_NEGATED_METHOD = :failure_message_when_negated
|
5
|
+
else
|
6
|
+
FAILURE_MESSAGE_METHOD = :failure_message_for_should
|
7
|
+
FAILURE_MESSAGE_WHEN_NEGATED_METHOD = :failure_message_for_should_not
|
8
|
+
end
|
9
|
+
|
10
|
+
def describe_failure_message(&blk)
|
11
|
+
describe "##{FAILURE_MESSAGE_METHOD}" do
|
12
|
+
subject { super().send(FAILURE_MESSAGE_METHOD) }
|
13
|
+
instance_eval(&blk)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def describe_failure_message_when_negated(&blk)
|
18
|
+
describe "##{FAILURE_MESSAGE_WHEN_NEGATED_METHOD}" do
|
19
|
+
subject { super().send(FAILURE_MESSAGE_WHEN_NEGATED_METHOD) }
|
20
|
+
instance_eval(&blk)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -1,18 +1,30 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
matcher.matches?(value)
|
5
|
-
end
|
1
|
+
module MatchHelpers
|
2
|
+
class MatchMatcher
|
3
|
+
attr_reader :value, :matcher
|
6
4
|
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
def initialize(value)
|
6
|
+
@value = value
|
7
|
+
end
|
8
|
+
|
9
|
+
def matches?(matcher)
|
10
|
+
@matcher = matcher
|
11
|
+
matcher.matches?(value)
|
12
|
+
end
|
13
|
+
|
14
|
+
def description
|
15
|
+
"match #{value}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def failure_message
|
19
|
+
"expect #{matcher} to match #{value} but did not"
|
20
|
+
end
|
10
21
|
|
11
|
-
|
12
|
-
|
22
|
+
def failure_message_when_negated
|
23
|
+
"expect #{matcher} to not match #{value} but did"
|
24
|
+
end
|
13
25
|
end
|
14
26
|
|
15
|
-
|
16
|
-
|
27
|
+
def match(value)
|
28
|
+
MatchMatcher.new(value)
|
17
29
|
end
|
18
30
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module ModelHelpers
|
2
|
+
def build_model(&blk)
|
3
|
+
let(:model) do
|
4
|
+
Class.new(ActiveRecord::Base) do
|
5
|
+
def self.name
|
6
|
+
"TestModel"
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.primary_key
|
10
|
+
"id"
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.columns
|
14
|
+
@columns ||= []
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.column(name, sql_type = nil, default = nil, null = true)
|
18
|
+
columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
|
19
|
+
end
|
20
|
+
|
21
|
+
instance_eval(&blk)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -2,6 +2,8 @@ module WithContextsHelpers
|
|
2
2
|
class WithContextsBuilder
|
3
3
|
attr_accessor :contexts, :examples, :group
|
4
4
|
|
5
|
+
delegate :let, :before, :after, :subject, to: :group
|
6
|
+
|
5
7
|
def initialize(group)
|
6
8
|
@contexts = {}
|
7
9
|
@group = group
|
@@ -11,6 +13,10 @@ module WithContextsHelpers
|
|
11
13
|
self.contexts[name] = blk
|
12
14
|
end
|
13
15
|
|
16
|
+
def describe(name, &blk)
|
17
|
+
self.contexts[name] = blk
|
18
|
+
end
|
19
|
+
|
14
20
|
def behaviour(&blk)
|
15
21
|
self.examples = blk
|
16
22
|
end
|
@@ -35,9 +35,7 @@ describe Warp::ControllerMatchers::AssignMatcher do
|
|
35
35
|
|
36
36
|
specify { expect(subject).to match(_controller) }
|
37
37
|
|
38
|
-
|
39
|
-
subject { super().failure_message_when_negated }
|
40
|
-
|
38
|
+
describe_failure_message_when_negated do
|
41
39
|
specify { expect(subject).to eq "expected @assign to not be assigned" }
|
42
40
|
end
|
43
41
|
end
|
@@ -49,9 +47,7 @@ describe Warp::ControllerMatchers::AssignMatcher do
|
|
49
47
|
|
50
48
|
specify { expect(subject).to_not match(_controller) }
|
51
49
|
|
52
|
-
|
53
|
-
subject { super().failure_message }
|
54
|
-
|
50
|
+
describe_failure_message do
|
55
51
|
specify { expect(subject).to eq "expected @assign to be assigned" }
|
56
52
|
end
|
57
53
|
end
|
@@ -75,9 +71,7 @@ describe Warp::ControllerMatchers::AssignMatcher do
|
|
75
71
|
context "with the right value" do
|
76
72
|
specify { expect(subject).to match(_controller) }
|
77
73
|
|
78
|
-
|
79
|
-
subject { super().failure_message_when_negated }
|
80
|
-
|
74
|
+
describe_failure_message_when_negated do
|
81
75
|
specify { expect(subject).to eq "expected @assign to not be assigned with #{expected_assign_value.inspect}" }
|
82
76
|
end
|
83
77
|
end
|
@@ -87,9 +81,7 @@ describe Warp::ControllerMatchers::AssignMatcher do
|
|
87
81
|
|
88
82
|
specify { expect(subject).to_not match(_controller) }
|
89
83
|
|
90
|
-
|
91
|
-
subject { super().failure_message }
|
92
|
-
|
84
|
+
describe_failure_message do
|
93
85
|
specify { expect(subject).to eq "expected @assign to be assigned with #{expected_assign_value.inspect} but was assigned with #{actual_assign_value.inspect}" }
|
94
86
|
end
|
95
87
|
end
|
@@ -114,9 +106,7 @@ describe Warp::ControllerMatchers::AssignMatcher do
|
|
114
106
|
context "with the right class" do
|
115
107
|
specify { expect(subject).to match(_controller) }
|
116
108
|
|
117
|
-
|
118
|
-
subject { super().failure_message_when_negated }
|
119
|
-
|
109
|
+
describe_failure_message_when_negated do
|
120
110
|
specify { expect(subject).to eq "expected @assign to not be assigned with an instance of #{expected_assign_class.name}" }
|
121
111
|
end
|
122
112
|
end
|
@@ -126,9 +116,7 @@ describe Warp::ControllerMatchers::AssignMatcher do
|
|
126
116
|
|
127
117
|
specify { expect(subject).to_not match(_controller) }
|
128
118
|
|
129
|
-
|
130
|
-
subject { super().failure_message }
|
131
|
-
|
119
|
+
describe_failure_message do
|
132
120
|
specify { expect(subject).to eq "expected @assign to be assigned with an instance of #{expected_assign_class.name} but was assigned with an instance of #{actual_assign_class.name}"
|
133
121
|
}
|
134
122
|
end
|
@@ -164,9 +152,7 @@ describe Warp::ControllerMatchers::AssignMatcher do
|
|
164
152
|
context "with the right class" do
|
165
153
|
specify { expect(subject).to match(_controller) }
|
166
154
|
|
167
|
-
|
168
|
-
subject { super().failure_message_when_negated }
|
169
|
-
|
155
|
+
describe_failure_message_when_negated do
|
170
156
|
specify { expect(subject).to eq "expected @assign to not be assigned with a new instance of #{expected_assign_class.name}" }
|
171
157
|
end
|
172
158
|
end
|
@@ -178,9 +164,7 @@ describe Warp::ControllerMatchers::AssignMatcher do
|
|
178
164
|
|
179
165
|
specify { expect(subject).to match(_controller) }
|
180
166
|
|
181
|
-
|
182
|
-
subject { super().failure_message_when_negated }
|
183
|
-
|
167
|
+
describe_failure_message_when_negated do
|
184
168
|
specify { expect(subject).to eq "expected @assign to not be assigned with a new instance of #{expected_assign_class.name}" }
|
185
169
|
end
|
186
170
|
end
|
@@ -190,9 +174,7 @@ describe Warp::ControllerMatchers::AssignMatcher do
|
|
190
174
|
|
191
175
|
specify { expect(subject).to_not match(_controller) }
|
192
176
|
|
193
|
-
|
194
|
-
subject { super().failure_message }
|
195
|
-
|
177
|
+
describe_failure_message do
|
196
178
|
specify { expect(subject).to eq "expected @assign to be assigned with a new instance of #{expected_assign_class.name} but was assigned with a new instance of #{actual_assign_class.name}"
|
197
179
|
}
|
198
180
|
end
|
@@ -205,9 +187,7 @@ describe Warp::ControllerMatchers::AssignMatcher do
|
|
205
187
|
context "with the right class" do
|
206
188
|
specify { expect(subject).to_not match(_controller) }
|
207
189
|
|
208
|
-
|
209
|
-
subject { super().failure_message }
|
210
|
-
|
190
|
+
describe_failure_message do
|
211
191
|
specify { expect(subject).to eq "expected @assign to be assigned with a new instance of #{expected_assign_class.name} but was assigned with a persisted instance of #{actual_assign_class.name}"
|
212
192
|
}
|
213
193
|
end
|
@@ -218,15 +198,37 @@ describe Warp::ControllerMatchers::AssignMatcher do
|
|
218
198
|
|
219
199
|
specify { expect(subject).to_not match(_controller) }
|
220
200
|
|
221
|
-
|
222
|
-
subject { super().failure_message }
|
223
|
-
|
201
|
+
describe_failure_message do
|
224
202
|
specify { expect(subject).to eq "expected @assign to be assigned with a new instance of #{expected_assign_class.name} but was assigned with a persisted instance of #{actual_assign_class.name}"
|
225
203
|
}
|
226
204
|
end
|
227
205
|
end
|
228
206
|
end
|
229
207
|
end
|
208
|
+
|
209
|
+
context "multiple assertions" do
|
210
|
+
with_contexts do
|
211
|
+
context "with .with and .with_a" do
|
212
|
+
let(:matcher) { super().with(Object.new).with_a(Class.new) }
|
213
|
+
end
|
214
|
+
|
215
|
+
context "with .with_a and .with_a_new" do
|
216
|
+
let(:matcher) { super().with_a(Class.new).with_a_new(Class.new) }
|
217
|
+
end
|
218
|
+
|
219
|
+
context "with .with_a_new and .with" do
|
220
|
+
let(:matcher) { super().with_a_new(Class.new).with(Object.new) }
|
221
|
+
end
|
222
|
+
|
223
|
+
context "with .with, .with_a, and .with_a_new" do
|
224
|
+
let(:matcher) { super().with(Object.new).with_a(Class.new).with_a_new(Class.new) }
|
225
|
+
end
|
226
|
+
|
227
|
+
behaviour do
|
228
|
+
specify { expect{ subject }.to raise_error("Only one of .with, .with_a, and .with_a_new can be used with the assigns matcher.") }
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
230
232
|
end
|
231
233
|
end
|
232
234
|
end
|
@@ -39,9 +39,7 @@ describe Warp::ControllerMatchers::SetFlashMatcher do
|
|
39
39
|
|
40
40
|
specify { expect(subject).to match(_controller) }
|
41
41
|
|
42
|
-
|
43
|
-
subject { super().failure_message_when_negated }
|
44
|
-
|
42
|
+
describe_failure_message_when_negated do
|
45
43
|
specify { expect(subject).to eq "expected flash[:#{flash_key}] to not be set" }
|
46
44
|
end
|
47
45
|
end
|
@@ -49,9 +47,7 @@ describe Warp::ControllerMatchers::SetFlashMatcher do
|
|
49
47
|
context "with no flash set" do
|
50
48
|
specify { expect(subject).to_not match(_controller) }
|
51
49
|
|
52
|
-
|
53
|
-
subject { super().failure_message }
|
54
|
-
|
50
|
+
describe_failure_message do
|
55
51
|
specify { expect(subject).to eq "expected flash[:#{flash_key}] to be set" }
|
56
52
|
end
|
57
53
|
end
|
@@ -76,9 +72,7 @@ describe Warp::ControllerMatchers::SetFlashMatcher do
|
|
76
72
|
|
77
73
|
specify { expect(subject).to match(_controller) }
|
78
74
|
|
79
|
-
|
80
|
-
subject { super().failure_message_when_negated }
|
81
|
-
|
75
|
+
describe_failure_message_when_negated do
|
82
76
|
specify { expect(subject).to eq "expected flash[:#{flash_key}] to not be set to #{expected_flash_value.inspect}" }
|
83
77
|
end
|
84
78
|
end
|
@@ -88,9 +82,7 @@ describe Warp::ControllerMatchers::SetFlashMatcher do
|
|
88
82
|
|
89
83
|
specify { expect(subject).to_not match(_controller) }
|
90
84
|
|
91
|
-
|
92
|
-
subject { super().failure_message }
|
93
|
-
|
85
|
+
describe_failure_message do
|
94
86
|
specify { expect(subject).to eq "expected flash[:#{flash_key}] to be set to #{expected_flash_value.inspect}" }
|
95
87
|
end
|
96
88
|
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Warp::ModelMatchers::AssociationMatcher do
|
4
|
+
build_model do
|
5
|
+
belongs_to :foo
|
6
|
+
has_many :bars
|
7
|
+
has_one :baz
|
8
|
+
has_and_belongs_to_many :qux
|
9
|
+
end
|
10
|
+
|
11
|
+
with_contexts do
|
12
|
+
context "with model" do
|
13
|
+
let(:model_or_instance) { model }
|
14
|
+
end
|
15
|
+
|
16
|
+
context "with model instance" do
|
17
|
+
let(:model_or_instance) { model.new }
|
18
|
+
end
|
19
|
+
|
20
|
+
behaviour do
|
21
|
+
if ActiveRecord::VERSION::STRING[0] == "4" && ActiveRecord::VERSION::STRING[3] != "0"
|
22
|
+
specify { expect{ have_and_belong_to_many(:foo) }.to raise_error(NotImplementedError) }
|
23
|
+
end
|
24
|
+
|
25
|
+
with_contexts do
|
26
|
+
let(:no_association_key) { :foobar }
|
27
|
+
|
28
|
+
describe "#have_many" do
|
29
|
+
let(:matcher) { have_many(key) }
|
30
|
+
|
31
|
+
let(:matcher_macro) { :has_many }
|
32
|
+
let(:association_key) { :bars }
|
33
|
+
let(:wrong_association_key) { :foo }
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#have_one" do
|
37
|
+
let(:matcher) { have_one(key) }
|
38
|
+
|
39
|
+
let(:matcher_macro) { :has_one }
|
40
|
+
let(:association_key) { :baz }
|
41
|
+
let(:wrong_association_key) { :foo }
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#belong_to" do
|
45
|
+
let(:matcher) { belong_to(key) }
|
46
|
+
|
47
|
+
let(:matcher_macro) { :belongs_to }
|
48
|
+
let(:association_key) { :foo }
|
49
|
+
let(:wrong_association_key) { :bars }
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
unless ActiveRecord::VERSION::STRING[0] == "4" && ActiveRecord::VERSION::STRING[3] != "0"
|
54
|
+
describe "#have_and_belong_to_many" do
|
55
|
+
let(:matcher) { have_and_belong_to_many(key) }
|
56
|
+
|
57
|
+
let(:matcher_macro) { :has_and_belongs_to_many }
|
58
|
+
let(:association_key) { :qux }
|
59
|
+
let(:wrong_association_key) { :foo }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
behaviour do
|
64
|
+
subject { matcher.tap {|m| m.matches?(model_or_instance) } }
|
65
|
+
|
66
|
+
context "when an association exists" do
|
67
|
+
context "and the association macro matches" do
|
68
|
+
let(:key) { association_key }
|
69
|
+
|
70
|
+
specify { expect(subject).to match(model_or_instance) }
|
71
|
+
|
72
|
+
describe_failure_message_when_negated do
|
73
|
+
specify { expect(subject).to eq "expected to not have association #{matcher_macro} :#{key}" }
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "and the association macro doesn't match" do
|
78
|
+
let(:key) { wrong_association_key }
|
79
|
+
let(:actual_macro) { model.reflect_on_association(key).macro }
|
80
|
+
|
81
|
+
specify { expect(subject).to_not match(model_or_instance) }
|
82
|
+
|
83
|
+
describe_failure_message do
|
84
|
+
specify { expect(subject).to eq "expected to have association #{matcher_macro} :#{key}, but had #{actual_macro} :#{key}" }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context "when an association doesn't exists" do
|
90
|
+
let(:key) { no_association_key }
|
91
|
+
|
92
|
+
specify { expect(subject).to_not match(model_or_instance) }
|
93
|
+
|
94
|
+
describe_failure_message do
|
95
|
+
specify { expect(subject).to eq "expected to have association #{matcher_macro} :#{key}" }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|