/
be_a_new.rb
76 lines (67 loc) · 2.1 KB
/
be_a_new.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
module RSpec::Rails::Matchers
class BeANew < RSpec::Matchers::BuiltIn::BaseMatcher
def initialize(expected)
@expected = expected
end
# @api private
def matches?(actual)
@actual = actual
actual.is_a?(expected) && actual.new_record? && attributes_match?(actual)
end
# Use this to specify the specific attributes to match on the new record.
#
# @example
#
# it "assigns a new Thing with the submitted attributes" do
# post :create, :thing => { :name => "Illegal Value" }
# assigns(:thing).should be_a_new(Thing).with(:name => nil)
# end
def with(expected_attributes)
attributes.merge!(expected_attributes)
self
end
# @api private
def failure_message_for_should
[].tap do |message|
unless actual.is_a?(expected) && actual.new_record?
message << "expected #{actual.inspect} to be a new #{expected.inspect}"
end
unless attributes_match?(actual)
if unmatched_attributes.size > 1
message << "attributes #{unmatched_attributes.inspect} were not set on #{actual.inspect}"
else
message << "attribute #{unmatched_attributes.inspect} was not set on #{actual.inspect}"
end
end
end.join(' and ')
end
private
def attributes
@attributes ||= {}
end
def attributes_match?(actual)
attributes.stringify_keys.all? do |key, value|
actual.attributes[key].eql?(value)
end
end
def unmatched_attributes
attributes.stringify_keys.reject do |key, value|
actual.attributes[key].eql?(value)
end
end
end
# Passes if actual is an instance of `model_class` and returns `false` for
# `persisted?`. Typically used to specify instance variables assigned to
# views by controller actions
#
# @example
#
# get :new
# assigns(:thing).should be_a_new(Thing)
#
# post :create, :thing => { :name => "Illegal Value" }
# assigns(:thing).should be_a_new(Thing).with(:name => nil)
def be_a_new(model_class)
BeANew.new(model_class)
end
end