shoulda-matchers 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (89) hide show
  1. data/.gitignore +11 -0
  2. data/.travis.yml +13 -0
  3. data/Appraisals +4 -6
  4. data/CONTRIBUTING.md +38 -0
  5. data/Gemfile +8 -5
  6. data/Gemfile.lock +77 -41
  7. data/NEWS.md +32 -0
  8. data/README.md +84 -0
  9. data/Rakefile +5 -36
  10. data/features/rails_integration.feature +88 -0
  11. data/features/step_definitions/rails_steps.rb +111 -0
  12. data/features/support/env.rb +5 -0
  13. data/gemfiles/3.0.gemfile +14 -0
  14. data/gemfiles/3.0.gemfile.lock +142 -0
  15. data/gemfiles/3.1.gemfile +16 -0
  16. data/gemfiles/3.1.gemfile.lock +164 -0
  17. data/lib/shoulda/matchers/action_controller/assign_to_matcher.rb +6 -9
  18. data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +1 -3
  19. data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +10 -6
  20. data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +1 -4
  21. data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +6 -6
  22. data/lib/shoulda/matchers/action_controller/respond_with_content_type_matcher.rb +11 -10
  23. data/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +0 -2
  24. data/lib/shoulda/matchers/action_controller/route_matcher.rb +17 -14
  25. data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +24 -16
  26. data/lib/shoulda/matchers/action_controller/set_the_flash_matcher.rb +52 -15
  27. data/lib/shoulda/matchers/action_mailer.rb +1 -1
  28. data/lib/shoulda/matchers/action_mailer/{have_sent_email.rb → have_sent_email_matcher.rb} +37 -21
  29. data/lib/shoulda/matchers/active_model.rb +1 -0
  30. data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +9 -10
  31. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +60 -33
  32. data/lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb +0 -1
  33. data/lib/shoulda/matchers/active_model/helpers.rb +13 -9
  34. data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +63 -0
  35. data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +38 -8
  36. data/lib/shoulda/matchers/active_model/validation_matcher.rb +1 -5
  37. data/lib/shoulda/matchers/active_record.rb +3 -1
  38. data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +127 -0
  39. data/lib/shoulda/matchers/active_record/association_matcher.rb +19 -7
  40. data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +20 -5
  41. data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +4 -10
  42. data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +3 -7
  43. data/lib/shoulda/matchers/active_record/query_the_database_matcher.rb +107 -0
  44. data/lib/shoulda/matchers/active_record/serialize_matcher.rb +111 -0
  45. data/lib/shoulda/matchers/integrations/rspec.rb +0 -1
  46. data/lib/shoulda/matchers/version.rb +1 -1
  47. data/shoulda-matchers.gemspec +30 -0
  48. data/spec/fixtures/addresses.yml +3 -0
  49. data/spec/fixtures/friendships.yml +0 -0
  50. data/spec/fixtures/posts.yml +5 -0
  51. data/spec/fixtures/products.yml +0 -0
  52. data/spec/fixtures/taggings.yml +0 -0
  53. data/spec/fixtures/tags.yml +9 -0
  54. data/spec/fixtures/users.yml +6 -0
  55. data/spec/shoulda/action_controller/assign_to_matcher_spec.rb +61 -0
  56. data/spec/shoulda/action_controller/filter_param_matcher_spec.rb +20 -0
  57. data/spec/shoulda/action_controller/redirect_to_matcher_spec.rb +40 -0
  58. data/spec/shoulda/action_controller/render_template_matcher_spec.rb +69 -0
  59. data/spec/shoulda/action_controller/render_with_layout_matcher_spec.rb +47 -0
  60. data/spec/shoulda/action_controller/respond_with_content_type_matcher_spec.rb +28 -0
  61. data/spec/shoulda/action_controller/respond_with_matcher_spec.rb +83 -0
  62. data/spec/shoulda/action_controller/route_matcher_spec.rb +65 -0
  63. data/spec/shoulda/action_controller/set_session_matcher_spec.rb +46 -0
  64. data/spec/shoulda/action_controller/set_the_flash_matcher_spec.rb +124 -0
  65. data/spec/shoulda/action_mailer/have_sent_email_spec.rb +293 -0
  66. data/spec/shoulda/active_model/allow_mass_assignment_of_matcher_spec.rb +95 -0
  67. data/spec/shoulda/active_model/allow_value_matcher_spec.rb +91 -0
  68. data/spec/shoulda/active_model/ensure_exclusion_of_matcher_spec.rb +57 -0
  69. data/spec/shoulda/active_model/ensure_inclusion_of_matcher_spec.rb +71 -0
  70. data/spec/shoulda/active_model/ensure_length_of_matcher_spec.rb +125 -0
  71. data/spec/shoulda/active_model/helpers_spec.rb +100 -0
  72. data/spec/shoulda/active_model/validate_acceptance_of_matcher_spec.rb +43 -0
  73. data/spec/shoulda/active_model/validate_confirmation_of_matcher_spec.rb +48 -0
  74. data/spec/shoulda/active_model/validate_format_of_matcher_spec.rb +38 -0
  75. data/spec/shoulda/active_model/validate_numericality_of_matcher_spec.rb +62 -0
  76. data/spec/shoulda/active_model/validate_presence_of_matcher_spec.rb +121 -0
  77. data/spec/shoulda/active_model/validate_uniqueness_of_matcher_spec.rb +143 -0
  78. data/spec/shoulda/active_record/accept_nested_attributes_for_matcher_spec.rb +84 -0
  79. data/spec/shoulda/active_record/association_matcher_spec.rb +449 -0
  80. data/spec/shoulda/active_record/have_db_column_matcher_spec.rb +185 -0
  81. data/spec/shoulda/active_record/have_db_index_matcher_spec.rb +88 -0
  82. data/spec/shoulda/active_record/have_readonly_attributes_matcher_spec.rb +46 -0
  83. data/spec/shoulda/active_record/query_the_database_matcher_spec.rb +45 -0
  84. data/spec/shoulda/active_record/serialize_matcher_spec.rb +81 -0
  85. data/spec/spec_helper.rb +31 -0
  86. data/spec/support/model_builder.rb +149 -0
  87. metadata +211 -60
  88. data/CONTRIBUTION_GUIDELINES.rdoc +0 -10
  89. data/README.rdoc +0 -80
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+
3
+ describe Shoulda::Matchers::ActiveModel::AllowMassAssignmentOfMatcher do
4
+ context "an attribute that is blacklisted from mass-assignment" do
5
+ let(:model) do
6
+ define_model(:example, :attr => :string) do
7
+ attr_protected :attr
8
+ end.new
9
+ end
10
+
11
+ it "should reject being mass-assignable" do
12
+ model.should_not allow_mass_assignment_of(:attr)
13
+ end
14
+ end
15
+
16
+ context "an attribute that is not whitelisted for mass-assignment" do
17
+ let(:model) do
18
+ define_model(:example, :attr => :string, :other => :string) do
19
+ attr_accessible :other
20
+ end.new
21
+ end
22
+
23
+ it "should reject being mass-assignable" do
24
+ model.should_not allow_mass_assignment_of(:attr)
25
+ end
26
+ end
27
+
28
+ context "an attribute that is whitelisted for mass-assignment" do
29
+ let(:model) do
30
+ define_model(:example, :attr => :string) do
31
+ attr_accessible :attr
32
+ end.new
33
+ end
34
+
35
+ it "should accept being mass-assignable" do
36
+ model.should allow_mass_assignment_of(:attr)
37
+ end
38
+ end
39
+
40
+ context "an attribute not included in the mass-assignment blacklist" do
41
+ let(:model) do
42
+ define_model(:example, :attr => :string, :other => :string) do
43
+ attr_protected :other
44
+ end.new
45
+ end
46
+
47
+ it "should accept being mass-assignable" do
48
+ model.should allow_mass_assignment_of(:attr)
49
+ end
50
+ end
51
+
52
+ context "an attribute on a class with no protected attributes" do
53
+ let(:model) { define_model(:example, :attr => :string).new }
54
+
55
+ it "should accept being mass-assignable" do
56
+ model.should allow_mass_assignment_of(:attr)
57
+ end
58
+
59
+ it "should assign a negative failure message" do
60
+ matcher = allow_mass_assignment_of(:attr)
61
+ matcher.matches?(model).should == true
62
+ matcher.negative_failure_message.should_not be_nil
63
+ end
64
+ end
65
+
66
+ context "an attribute on a class with all protected attributes" do
67
+ let(:model) do
68
+ define_model(:example, :attr => :string) do
69
+ attr_accessible
70
+ end.new
71
+ end
72
+
73
+ it "should reject being mass-assignable" do
74
+ model.should_not allow_mass_assignment_of(:attr)
75
+ end
76
+ end
77
+
78
+ if ::ActiveModel::VERSION::MAJOR == 3 && ::ActiveModel::VERSION::MINOR >= 1
79
+ context "an attribute included in the mass-assignment whitelist for admin role only" do
80
+ let(:model) do
81
+ define_model(:example, :attr => :string) do
82
+ attr_accessible :attr, :as => :admin
83
+ end.new
84
+ end
85
+
86
+ it "should reject being mass-assignable" do
87
+ model.should_not allow_mass_assignment_of(:attr)
88
+ end
89
+
90
+ it "should accept being mass-assignable for admin" do
91
+ model.should allow_mass_assignment_of(:attr).as(:admin)
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,91 @@
1
+ require 'spec_helper'
2
+
3
+ describe Shoulda::Matchers::ActiveModel::AllowValueMatcher do
4
+ context "an attribute with a format validation" do
5
+ let(:model) do
6
+ define_model :example, :attr => :string do
7
+ validates_format_of :attr, :with => /abc/
8
+ end.new
9
+ end
10
+
11
+ it "allows a good value" do
12
+ model.should allow_value("abcde").for(:attr)
13
+ end
14
+
15
+ it "rejects a bad value" do
16
+ model.should_not allow_value("xyz").for(:attr)
17
+ end
18
+
19
+ it "allows several good values" do
20
+ model.should allow_value("abcde", "deabc").for(:attr)
21
+ end
22
+
23
+ it "rejects several bad values" do
24
+ model.should_not allow_value("xyz", "zyx", nil, []).for(:attr)
25
+ end
26
+ end
27
+
28
+ context "an attribute with a format validation and a custom message" do
29
+ let(:model) do
30
+ define_model :example, :attr => :string do
31
+ validates_format_of :attr, :with => /abc/, :message => 'bad value'
32
+ end.new
33
+ end
34
+
35
+ it "allows a good value" do
36
+ model.should allow_value('abcde').for(:attr).with_message(/bad/)
37
+ end
38
+
39
+ it "rejects a bad value" do
40
+ model.should_not allow_value('xyz').for(:attr).with_message(/bad/)
41
+ end
42
+ end
43
+
44
+ context "an attribute with several validations" do
45
+ let(:model) do
46
+ define_model :example, :attr => :string do
47
+ validates_presence_of :attr
48
+ validates_length_of :attr, :within => 1..5
49
+ validates_numericality_of :attr, :greater_than_or_equal_to => 1,
50
+ :less_than_or_equal_to => 50000
51
+ end.new
52
+ end
53
+ bad_values = [nil, "", "abc", "0", "50001", "123456", []]
54
+
55
+ it "allows a good value" do
56
+ model.should allow_value("12345").for(:attr)
57
+ end
58
+
59
+ bad_values.each do |bad_value|
60
+ it "rejects a bad value (#{bad_value.inspect})" do
61
+ model.should_not allow_value(bad_value).for(:attr)
62
+ end
63
+ end
64
+
65
+ it "rejects bad values (#{bad_values.map(&:inspect).join(', ')})" do
66
+ model.should_not allow_value(*bad_values).for(:attr)
67
+ end
68
+ end
69
+
70
+ context "an AllowValueMatcher with multiple values" do
71
+ it "should describe itself" do
72
+ matcher = allow_value("foo", "bar").for(:baz)
73
+ matcher.description.should == 'allow baz to be set to any of ["foo", "bar"]'
74
+ end
75
+ end
76
+
77
+ context "an AllowValueMatcher with a single value" do
78
+ it "should describe itself" do
79
+ matcher = allow_value("foo").for(:baz)
80
+ matcher.description.should eq('allow baz to be set to "foo"')
81
+ end
82
+ end
83
+
84
+ context "an AllowValueMatcher with no values" do
85
+ it "raises an error" do
86
+ lambda do
87
+ allow_value.for(:baz)
88
+ end.should raise_error(ArgumentError, /at least one argument/)
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,57 @@
1
+ require 'spec_helper'
2
+
3
+ describe Shoulda::Matchers::ActiveModel::EnsureExclusionOfMatcher do
4
+
5
+ context "an attribute which must be excluded of a range" do
6
+ before do
7
+ @model = define_model(:example, :attr => :integer) do
8
+ validates_exclusion_of :attr, :in => 2..5
9
+ end.new
10
+ end
11
+
12
+ it "should accept ensuring the correct range" do
13
+ @model.should ensure_exclusion_of(:attr).in_range(2..5)
14
+ end
15
+
16
+ it "should reject ensuring excluded value" do
17
+ @model.should_not ensure_exclusion_of(:attr).in_range(2..6)
18
+ end
19
+
20
+ it "should not override the default message with a blank" do
21
+ @model.should ensure_exclusion_of(:attr).in_range(2..5).with_message(nil)
22
+ end
23
+ end
24
+
25
+ context "an attribute with a custom ranged value validation" do
26
+ before do
27
+ @model = define_model(:example, :attr => :string) do
28
+ validates_exclusion_of :attr, :in => 2..4, :message => 'not good'
29
+
30
+ end.new
31
+ end
32
+
33
+ it "should accept ensuring the correct range" do
34
+ @model.should ensure_exclusion_of(:attr).in_range(2..4).with_message(/not good/)
35
+ end
36
+ end
37
+
38
+ context "an attribute with custom range validations" do
39
+ before do
40
+ define_model :example, :attr => :integer do
41
+ validate :custom_validation
42
+ def custom_validation
43
+ if attr >= 2 && attr <= 5
44
+ errors.add(:attr, 'shoud be out of this range')
45
+ end
46
+ end
47
+ end
48
+ @model = Example.new
49
+ end
50
+
51
+ it "should accept ensuring the correct range and messages" do
52
+ @model.should ensure_exclusion_of(:attr).in_range(2..5).with_message(/shoud be out of this range/)
53
+ end
54
+
55
+ end
56
+
57
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe Shoulda::Matchers::ActiveModel::EnsureInclusionOfMatcher do
4
+
5
+ context "an attribute which must be included in a range" do
6
+ before do
7
+ @model = define_model(:example, :attr => :integer) do
8
+ validates_inclusion_of :attr, :in => 2..5
9
+ end.new
10
+ end
11
+
12
+ it "should accept ensuring the correct range" do
13
+ @model.should ensure_inclusion_of(:attr).in_range(2..5)
14
+ end
15
+
16
+ it "should reject ensuring a lower minimum value" do
17
+ @model.should_not ensure_inclusion_of(:attr).in_range(1..5)
18
+ end
19
+
20
+ it "should reject ensuring a higher minimum value" do
21
+ @model.should_not ensure_inclusion_of(:attr).in_range(3..5)
22
+ end
23
+
24
+ it "should reject ensuring a lower maximum value" do
25
+ @model.should_not ensure_inclusion_of(:attr).in_range(2..4)
26
+ end
27
+
28
+ it "should reject ensuring a higher maximum value" do
29
+ @model.should_not ensure_inclusion_of(:attr).in_range(2..6)
30
+ end
31
+
32
+ it "should not override the default message with a blank" do
33
+ @model.should ensure_inclusion_of(:attr).in_range(2..5).with_message(nil)
34
+ end
35
+ end
36
+
37
+ context "an attribute with a custom ranged value validation" do
38
+ before do
39
+ @model = define_model(:example, :attr => :string) do
40
+ validates_inclusion_of :attr, :in => 2..4, :message => 'not good'
41
+
42
+ end.new
43
+ end
44
+
45
+ it "should accept ensuring the correct range" do
46
+ @model.should ensure_inclusion_of(:attr).in_range(2..4).with_message(/not good/)
47
+ end
48
+ end
49
+
50
+ context "an attribute with custom range validations" do
51
+ before do
52
+ define_model :example, :attr => :integer do
53
+ validate :custom_validation
54
+ def custom_validation
55
+ if attr < 2
56
+ errors.add(:attr, 'too low')
57
+ elsif attr > 5
58
+ errors.add(:attr, 'too high')
59
+ end
60
+ end
61
+ end
62
+ @model = Example.new
63
+ end
64
+
65
+ it "should accept ensuring the correct range and messages" do
66
+ @model.should ensure_inclusion_of(:attr).in_range(2..5).with_low_message(/low/).with_high_message(/high/)
67
+ end
68
+
69
+ end
70
+
71
+ end
@@ -0,0 +1,125 @@
1
+ require 'spec_helper'
2
+
3
+ describe Shoulda::Matchers::ActiveModel::EnsureLengthOfMatcher do
4
+
5
+ context "an attribute with a non-zero minimum length validation" do
6
+ before do
7
+ @model = define_model(:example, :attr => :string) do
8
+ validates_length_of :attr, :minimum => 4
9
+ end.new
10
+ end
11
+
12
+ it "should accept ensuring the correct minimum length" do
13
+ @model.should ensure_length_of(:attr).is_at_least(4)
14
+ end
15
+
16
+ it "should reject ensuring a lower minimum length with any message" do
17
+ @model.should_not ensure_length_of(:attr).is_at_least(3).with_short_message(/.*/)
18
+ end
19
+
20
+ it "should reject ensuring a higher minimum length with any message" do
21
+ @model.should_not ensure_length_of(:attr).is_at_least(5).with_short_message(/.*/)
22
+ end
23
+
24
+ it "should not override the default message with a blank" do
25
+ @model.should ensure_length_of(:attr).is_at_least(4).with_short_message(nil)
26
+ end
27
+ end
28
+
29
+ context "an attribute with a minimum length validation of 0" do
30
+ before do
31
+ @model = define_model(:example, :attr => :string) do
32
+ validates_length_of :attr, :minimum => 0
33
+ end.new
34
+ end
35
+
36
+ it "should accept ensuring the correct minimum length" do
37
+ @model.should ensure_length_of(:attr).is_at_least(0)
38
+ end
39
+ end
40
+
41
+ context "an attribute with a maximum length" do
42
+ before do
43
+ @model = define_model(:example, :attr => :string) do
44
+ validates_length_of :attr, :maximum => 4
45
+ end.new
46
+ end
47
+
48
+ it "should accept ensuring the correct maximum length" do
49
+ @model.should ensure_length_of(:attr).is_at_most(4)
50
+ end
51
+
52
+ it "should reject ensuring a lower maximum length with any message" do
53
+ @model.should_not ensure_length_of(:attr).is_at_most(3).with_long_message(/.*/)
54
+ end
55
+
56
+ it "should reject ensuring a higher maximum length with any message" do
57
+ @model.should_not ensure_length_of(:attr).is_at_most(5).with_long_message(/.*/)
58
+ end
59
+
60
+ it "should not override the default message with a blank" do
61
+ @model.should ensure_length_of(:attr).is_at_most(4).with_long_message(nil)
62
+ end
63
+ end
64
+
65
+ context "an attribute with a required exact length" do
66
+ before do
67
+ @model = define_model(:example, :attr => :string) do
68
+ validates_length_of :attr, :is => 4
69
+ end.new
70
+ end
71
+
72
+ it "should accept ensuring the correct length" do
73
+ @model.should ensure_length_of(:attr).is_equal_to(4)
74
+ end
75
+
76
+ it "should reject ensuring a lower maximum length with any message" do
77
+ @model.should_not ensure_length_of(:attr).is_equal_to(3).with_message(/.*/)
78
+ end
79
+
80
+ it "should reject ensuring a higher maximum length with any message" do
81
+ @model.should_not ensure_length_of(:attr).is_equal_to(5).with_message(/.*/)
82
+ end
83
+
84
+ it "should not override the default message with a blank" do
85
+ @model.should ensure_length_of(:attr).is_equal_to(4).with_message(nil)
86
+ end
87
+ end
88
+
89
+ context "an attribute with a custom minimum length validation" do
90
+ before do
91
+ @model = define_model(:example, :attr => :string) do
92
+ validates_length_of :attr, :minimum => 4, :too_short => 'short'
93
+ end.new
94
+ end
95
+
96
+ it "should accept ensuring the correct minimum length" do
97
+ @model.should ensure_length_of(:attr).is_at_least(4).with_short_message(/short/)
98
+ end
99
+
100
+ end
101
+
102
+ context "an attribute with a custom maximum length validation" do
103
+ before do
104
+ @model = define_model(:example, :attr => :string) do
105
+ validates_length_of :attr, :maximum => 4, :too_long => 'long'
106
+ end.new
107
+ end
108
+
109
+ it "should accept ensuring the correct minimum length" do
110
+ @model.should ensure_length_of(:attr).is_at_most(4).with_long_message(/long/)
111
+ end
112
+
113
+ end
114
+
115
+ context "an attribute without a length validation" do
116
+ before do
117
+ @model = define_model(:example, :attr => :string).new
118
+ end
119
+
120
+ it "should reject ensuring a minimum length" do
121
+ @model.should_not ensure_length_of(:attr).is_at_least(1)
122
+ end
123
+ end
124
+
125
+ end
@@ -0,0 +1,100 @@
1
+ # encoding: UTF-8
2
+ require "spec_helper"
3
+
4
+ def store_translations(options = {:without => []})
5
+ options[:without] = Array.wrap(options[:without] || [])
6
+
7
+ translations = {
8
+ :activerecord => {
9
+ :errors => {
10
+ :models => {
11
+ :example => {
12
+ :attributes => {
13
+ :attr => {}
14
+ }
15
+ }
16
+ },
17
+ :messages => {}
18
+ }
19
+ },
20
+ :errors => {
21
+ :attributes => {
22
+ :attr => {}
23
+ },
24
+ :messages => {}
25
+ }
26
+ }
27
+
28
+ unless options[:without].include?(:model_attribute)
29
+ translations[:activerecord][:errors][:models][:example][:attributes][:attr][:blank] = 'Don’t you do that to me!'
30
+ end
31
+
32
+ unless options[:without].include?(:model)
33
+ translations[:activerecord][:errors][:models][:example][:blank] = 'Give it one more try!'
34
+ end
35
+
36
+ unless options[:without].include?(:message)
37
+ translations[:activerecord][:errors][:messages][:blank] = 'Oh no!'
38
+ end
39
+
40
+ unless options[:without].include?(:attribute)
41
+ translations[:errors][:attributes][:attr][:blank] = 'Seriously?'
42
+ end
43
+
44
+ I18n.backend.store_translations(:en, translations)
45
+ end
46
+
47
+ describe Shoulda::Matchers::ActiveModel::Helpers do
48
+ include Shoulda::Matchers::ActiveModel
49
+
50
+ describe "default_error_message" do
51
+ before do
52
+ define_model :example, :attr => :string do
53
+ validates_presence_of :attr
54
+ end
55
+ @model = Example.new
56
+ end
57
+
58
+ after { I18n.backend.reload! }
59
+
60
+ context "if the translation for the model attribute’s error exists" do
61
+ it "provides the right error message" do
62
+ store_translations
63
+ @model.should validate_presence_of(:attr)
64
+ end
65
+ end
66
+
67
+ context "if no translation for the model attribute’s error exists" do
68
+ context "and the translation for the model’s error exists" do
69
+ it "provides the right error message" do
70
+ store_translations(:without => :model_attribute)
71
+ @model.should validate_presence_of(:attr)
72
+ end
73
+ end
74
+
75
+ context "and no translation for the model’s error exists" do
76
+ context "and the translation for the message exists" do
77
+ it "provides the right error message" do
78
+ store_translations(:without => [:model_attribute, :model])
79
+ @model.should validate_presence_of(:attr)
80
+ end
81
+ end
82
+
83
+ context "and no translation for the message exists" do
84
+ context "and the translation for the attribute exists" do
85
+ it "provides the right error message" do
86
+ store_translations(:without => [:model_attribute, :model, :message])
87
+ @model.should validate_presence_of(:attr)
88
+ end
89
+ end
90
+
91
+ context "and no translation for the attribute exists" do
92
+ it "provides the general error message" do
93
+ @model.should validate_presence_of(:attr)
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end