gnip-gnip 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data/README +144 -0
  2. data/Rakefile +221 -0
  3. data/TODO +72 -0
  4. data/bin/gnip +651 -0
  5. data/doc/api.html +1201 -0
  6. data/gemspec.rb +25 -0
  7. data/gnip-ruby.gemspec +26 -0
  8. data/lib/gnip.rb +71 -0
  9. data/lib/gnip/activity.rb +665 -0
  10. data/lib/gnip/api.rb +191 -0
  11. data/lib/gnip/arguments.rb +21 -0
  12. data/lib/gnip/blankslate.rb +5 -0
  13. data/lib/gnip/config.rb +144 -0
  14. data/lib/gnip/filter.rb +311 -0
  15. data/lib/gnip/list.rb +126 -0
  16. data/lib/gnip/options.rb +96 -0
  17. data/lib/gnip/orderedhash.rb +199 -0
  18. data/lib/gnip/publisher.rb +316 -0
  19. data/lib/gnip/resource.rb +301 -0
  20. data/lib/gnip/template.rb +44 -0
  21. data/lib/gnip/util.rb +120 -0
  22. data/sample/data/activity.yml +21 -0
  23. data/test/auth.rb +60 -0
  24. data/test/config.yml +2 -0
  25. data/test/data/activity.xml +14 -0
  26. data/test/data/activity_only_required.xml +4 -0
  27. data/test/data/activity_with_payload.xml +22 -0
  28. data/test/data/activity_with_place.xml +18 -0
  29. data/test/data/activity_with_place_wo_bounds.xml +36 -0
  30. data/test/data/activity_with_unbounded_media_urls.xml +44 -0
  31. data/test/data/activity_without_bounds.xml +24 -0
  32. data/test/helper.rb +115 -0
  33. data/test/integration/auth.rb +12 -0
  34. data/test/integration/publisher.rb +86 -0
  35. data/test/lib/shoulda.rb +9 -0
  36. data/test/lib/shoulda/action_controller.rb +28 -0
  37. data/test/lib/shoulda/action_controller/helpers.rb +47 -0
  38. data/test/lib/shoulda/action_controller/macros.rb +277 -0
  39. data/test/lib/shoulda/action_controller/matchers.rb +37 -0
  40. data/test/lib/shoulda/action_controller/matchers/assign_to_matcher.rb +109 -0
  41. data/test/lib/shoulda/action_controller/matchers/filter_param_matcher.rb +57 -0
  42. data/test/lib/shoulda/action_controller/matchers/render_with_layout_matcher.rb +81 -0
  43. data/test/lib/shoulda/action_controller/matchers/respond_with_content_type_matcher.rb +70 -0
  44. data/test/lib/shoulda/action_controller/matchers/respond_with_matcher.rb +77 -0
  45. data/test/lib/shoulda/action_controller/matchers/route_matcher.rb +93 -0
  46. data/test/lib/shoulda/action_controller/matchers/set_session_matcher.rb +83 -0
  47. data/test/lib/shoulda/action_controller/matchers/set_the_flash_matcher.rb +85 -0
  48. data/test/lib/shoulda/action_mailer.rb +10 -0
  49. data/test/lib/shoulda/action_mailer/assertions.rb +38 -0
  50. data/test/lib/shoulda/action_view.rb +10 -0
  51. data/test/lib/shoulda/action_view/macros.rb +56 -0
  52. data/test/lib/shoulda/active_record.rb +16 -0
  53. data/test/lib/shoulda/active_record/assertions.rb +69 -0
  54. data/test/lib/shoulda/active_record/helpers.rb +40 -0
  55. data/test/lib/shoulda/active_record/macros.rb +586 -0
  56. data/test/lib/shoulda/active_record/matchers.rb +42 -0
  57. data/test/lib/shoulda/active_record/matchers/allow_mass_assignment_of_matcher.rb +83 -0
  58. data/test/lib/shoulda/active_record/matchers/allow_value_matcher.rb +102 -0
  59. data/test/lib/shoulda/active_record/matchers/association_matcher.rb +226 -0
  60. data/test/lib/shoulda/active_record/matchers/ensure_inclusion_of_matcher.rb +87 -0
  61. data/test/lib/shoulda/active_record/matchers/ensure_length_of_matcher.rb +141 -0
  62. data/test/lib/shoulda/active_record/matchers/have_db_column_matcher.rb +169 -0
  63. data/test/lib/shoulda/active_record/matchers/have_index_matcher.rb +105 -0
  64. data/test/lib/shoulda/active_record/matchers/have_named_scope_matcher.rb +125 -0
  65. data/test/lib/shoulda/active_record/matchers/have_readonly_attribute_matcher.rb +59 -0
  66. data/test/lib/shoulda/active_record/matchers/validate_acceptance_of_matcher.rb +41 -0
  67. data/test/lib/shoulda/active_record/matchers/validate_numericality_of_matcher.rb +39 -0
  68. data/test/lib/shoulda/active_record/matchers/validate_presence_of_matcher.rb +60 -0
  69. data/test/lib/shoulda/active_record/matchers/validate_uniqueness_of_matcher.rb +148 -0
  70. data/test/lib/shoulda/active_record/matchers/validation_matcher.rb +56 -0
  71. data/test/lib/shoulda/assertions.rb +59 -0
  72. data/test/lib/shoulda/autoload_macros.rb +46 -0
  73. data/test/lib/shoulda/context.rb +304 -0
  74. data/test/lib/shoulda/helpers.rb +8 -0
  75. data/test/lib/shoulda/macros.rb +73 -0
  76. data/test/lib/shoulda/private_helpers.rb +20 -0
  77. data/test/lib/shoulda/proc_extensions.rb +14 -0
  78. data/test/lib/shoulda/rails.rb +13 -0
  79. data/test/lib/shoulda/rspec.rb +9 -0
  80. data/test/lib/shoulda/tasks.rb +3 -0
  81. data/test/lib/shoulda/tasks/list_tests.rake +29 -0
  82. data/test/lib/shoulda/tasks/yaml_to_shoulda.rake +28 -0
  83. data/test/lib/shoulda/test_unit.rb +19 -0
  84. data/test/lib/xmlsimple.rb +1021 -0
  85. data/test/loader.rb +25 -0
  86. data/test/unit/activity.rb +26 -0
  87. data/test/unit/util.rb +39 -0
  88. metadata +158 -0
@@ -0,0 +1,85 @@
1
+ module Shoulda # :nodoc:
2
+ module ActionController # :nodoc:
3
+ module Matchers
4
+
5
+ # Ensures that the flash contains the given value. Can be a String, a
6
+ # Regexp, or nil (indicating that the flash should not be set).
7
+ #
8
+ # Example:
9
+ #
10
+ # it { should set_the_flash }
11
+ # it { should set_the_flash.to("Thank you for placing this order.") }
12
+ # it { should set_the_flash.to(/created/i) }
13
+ # it { should_not set_the_flash }
14
+ def set_the_flash
15
+ SetTheFlashMatcher.new
16
+ end
17
+
18
+ class SetTheFlashMatcher # :nodoc:
19
+
20
+ def to(value)
21
+ @value = value
22
+ self
23
+ end
24
+
25
+ def matches?(controller)
26
+ @controller = controller
27
+ sets_the_flash? && string_value_matches? && regexp_value_matches?
28
+ end
29
+
30
+ attr_reader :failure_message, :negative_failure_message
31
+
32
+ def description
33
+ description = "set the flash"
34
+ description << " to #{@value.inspect}" unless @value.nil?
35
+ description
36
+ end
37
+
38
+ def failure_message
39
+ "Expected #{expectation}"
40
+ end
41
+
42
+ def negative_failure_message
43
+ "Did not expect #{expectation}"
44
+ end
45
+
46
+ private
47
+
48
+ def sets_the_flash?
49
+ !flash.blank?
50
+ end
51
+
52
+ def string_value_matches?
53
+ return true unless String === @value
54
+ flash.values.any? {|value| value == @value }
55
+ end
56
+
57
+ def regexp_value_matches?
58
+ return true unless Regexp === @value
59
+ flash.values.any? {|value| value =~ @value }
60
+ end
61
+
62
+ def flash
63
+ @controller.response.session['flash']
64
+ end
65
+
66
+ def expectation
67
+ expectation = "the flash to be set"
68
+ expectation << " to #{@value.inspect}" unless @value.nil?
69
+ expectation << ", but #{flash_description}"
70
+ expectation
71
+ end
72
+
73
+ def flash_description
74
+ if flash.blank?
75
+ "no flash was set"
76
+ else
77
+ "was #{flash.inspect}"
78
+ end
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,10 @@
1
+ require 'shoulda'
2
+ require 'shoulda/action_mailer/assertions'
3
+
4
+ module Test # :nodoc: all
5
+ module Unit
6
+ class TestCase
7
+ include Shoulda::ActionMailer::Assertions
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,38 @@
1
+ module Shoulda # :nodoc:
2
+ module ActionMailer # :nodoc:
3
+ module Assertions
4
+ # Asserts that an email was delivered. Can take a block that can further
5
+ # narrow down the types of emails you're expecting.
6
+ #
7
+ # assert_sent_email
8
+ #
9
+ # Passes if ActionMailer::Base.deliveries has an email
10
+ #
11
+ # assert_sent_email do |email|
12
+ # email.subject =~ /hi there/ && email.to.include?('none@none.com')
13
+ # end
14
+ #
15
+ # Passes if there is an email with subject containing 'hi there' and
16
+ # 'none@none.com' as one of the recipients.
17
+ #
18
+ def assert_sent_email
19
+ emails = ::ActionMailer::Base.deliveries
20
+ assert !emails.empty?, "No emails were sent"
21
+ if block_given?
22
+ matching_emails = emails.select {|email| yield email }
23
+ assert !matching_emails.empty?, "None of the emails matched."
24
+ end
25
+ end
26
+
27
+ # Asserts that no ActionMailer mails were delivered
28
+ #
29
+ # assert_did_not_send_email
30
+ def assert_did_not_send_email
31
+ msg = "Sent #{::ActionMailer::Base.deliveries.size} emails.\n"
32
+ ::ActionMailer::Base.deliveries.each { |m| msg << " '#{m.subject}' sent to #{m.to.to_sentence}\n" }
33
+ assert ::ActionMailer::Base.deliveries.empty?, msg
34
+ end
35
+ end
36
+ end
37
+ end
38
+
@@ -0,0 +1,10 @@
1
+ require 'shoulda'
2
+ require 'shoulda/action_view/macros'
3
+
4
+ module Test # :nodoc: all
5
+ module Unit
6
+ class TestCase
7
+ extend Shoulda::ActionView::Macros
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,56 @@
1
+ module Shoulda # :nodoc:
2
+ module ActionView # :nodoc:
3
+ # = Macro test helpers for your view
4
+ #
5
+ # By using the macro helpers you can quickly and easily create concise and
6
+ # easy to read test suites.
7
+ #
8
+ # This code segment:
9
+ # context "on GET to :new" do
10
+ # setup do
11
+ # get :new
12
+ # end
13
+ #
14
+ # should_render_a_form
15
+ # should_render_page_with_metadata :title => /index/
16
+ #
17
+ # should "do something else really cool" do
18
+ # assert_select '#really_cool'
19
+ # end
20
+ # end
21
+ #
22
+ # Would produce 3 tests for the +show+ action
23
+ module Macros
24
+
25
+ # Macro that creates a test asserting that the rendered view contains a <form> element.
26
+ def should_render_a_form
27
+ should "display a form" do
28
+ assert_select "form", true, "The template doesn't contain a <form> element"
29
+ end
30
+ end
31
+
32
+ # Macro that creates a test asserting that the rendered view contains the selected metatags.
33
+ # Values can be string or Regexps.
34
+ # Example:
35
+ #
36
+ # should_render_page_with_metadata :description => "Description of this page", :keywords => /post/
37
+ #
38
+ # You can also use this method to test the rendered views title.
39
+ #
40
+ # Example:
41
+ # should_render_page_with_metadata :title => /index/
42
+ def should_render_page_with_metadata(options)
43
+ options.each do |key, value|
44
+ should "have metatag #{key}" do
45
+ if key.to_sym == :title
46
+ assert_select "title", value
47
+ else
48
+ assert_select "meta[name=?][content#{"*" if value.is_a?(Regexp)}=?]", key, value
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+
@@ -0,0 +1,16 @@
1
+ require 'shoulda'
2
+ require 'shoulda/active_record/helpers'
3
+ require 'shoulda/active_record/matchers'
4
+ require 'shoulda/active_record/assertions'
5
+ require 'shoulda/active_record/macros'
6
+
7
+ module Test # :nodoc: all
8
+ module Unit
9
+ class TestCase
10
+ include Shoulda::ActiveRecord::Helpers
11
+ include Shoulda::ActiveRecord::Matchers
12
+ include Shoulda::ActiveRecord::Assertions
13
+ extend Shoulda::ActiveRecord::Macros
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,69 @@
1
+ module Shoulda # :nodoc:
2
+ module ActiveRecord # :nodoc:
3
+ module Assertions
4
+ # Asserts that the given object can be saved
5
+ #
6
+ # assert_save User.new(params)
7
+ def assert_save(obj)
8
+ assert obj.save, "Errors: #{pretty_error_messages obj}"
9
+ obj.reload
10
+ end
11
+
12
+ # Asserts that the given object is valid
13
+ #
14
+ # assert_valid User.new(params)
15
+ def assert_valid(obj)
16
+ assert obj.valid?, "Errors: #{pretty_error_messages obj}"
17
+ end
18
+
19
+ # Asserts that an Active Record model validates with the passed
20
+ # <tt>value</tt> by making sure the <tt>error_message_to_avoid</tt> is not
21
+ # contained within the list of errors for that attribute.
22
+ #
23
+ # assert_good_value(User.new, :email, "user@example.com")
24
+ # assert_good_value(User.new, :ssn, "123456789", /length/)
25
+ #
26
+ # If a class is passed as the first argument, a new object will be
27
+ # instantiated before the assertion. If an instance variable exists with
28
+ # the same name as the class (underscored), that object will be used
29
+ # instead.
30
+ #
31
+ # assert_good_value(User, :email, "user@example.com")
32
+ #
33
+ # @product = Product.new(:tangible => false)
34
+ # assert_good_value(Product, :price, "0")
35
+ def assert_good_value(object_or_klass, attribute, value, error_message_to_avoid = nil)
36
+ object = get_instance_of(object_or_klass)
37
+ matcher = allow_value(value).
38
+ for(attribute).
39
+ with_message(error_message_to_avoid)
40
+ assert_accepts(matcher, object)
41
+ end
42
+
43
+ # Asserts that an Active Record model invalidates the passed
44
+ # <tt>value</tt> by making sure the <tt>error_message_to_expect</tt> is
45
+ # contained within the list of errors for that attribute.
46
+ #
47
+ # assert_bad_value(User.new, :email, "invalid")
48
+ # assert_bad_value(User.new, :ssn, "123", /length/)
49
+ #
50
+ # If a class is passed as the first argument, a new object will be
51
+ # instantiated before the assertion. If an instance variable exists with
52
+ # the same name as the class (underscored), that object will be used
53
+ # instead.
54
+ #
55
+ # assert_bad_value(User, :email, "invalid")
56
+ #
57
+ # @product = Product.new(:tangible => true)
58
+ # assert_bad_value(Product, :price, "0")
59
+ def assert_bad_value(object_or_klass, attribute, value,
60
+ error_message_to_expect = nil)
61
+ object = get_instance_of(object_or_klass)
62
+ matcher = allow_value(value).
63
+ for(attribute).
64
+ with_message(error_message_to_expect)
65
+ assert_rejects(matcher, object)
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,40 @@
1
+ module Shoulda # :nodoc:
2
+ module ActiveRecord # :nodoc:
3
+ module Helpers
4
+ def pretty_error_messages(obj) # :nodoc:
5
+ obj.errors.map do |a, m|
6
+ msg = "#{a} #{m}"
7
+ msg << " (#{obj.send(a).inspect})" unless a.to_sym == :base
8
+ end
9
+ end
10
+
11
+ def get_instance_of(object_or_klass)
12
+ if object_or_klass.is_a?(Class)
13
+ klass = object_or_klass
14
+ instance_variable_get("@#{instance_variable_name_for(klass)}") || klass.new
15
+ else
16
+ object_or_klass
17
+ end
18
+ end
19
+
20
+ def instance_variable_name_for(klass)
21
+ klass.to_s.split('::').last.underscore
22
+ end
23
+
24
+ # Helper method that determines the default error message used by Active
25
+ # Record. Works for both existing Rails 2.1 and Rails 2.2 with the newly
26
+ # introduced I18n module used for localization.
27
+ #
28
+ # default_error_message(:blank)
29
+ # default_error_message(:too_short, :count => 5)
30
+ # default_error_message(:too_long, :count => 60)
31
+ def default_error_message(key, values = {})
32
+ if Object.const_defined?(:I18n) # Rails >= 2.2
33
+ I18n.translate("activerecord.errors.messages.#{key}", values)
34
+ else # Rails <= 2.1.x
35
+ ::ActiveRecord::Errors.default_error_messages[key] % values[:count]
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,586 @@
1
+ module Shoulda # :nodoc:
2
+ module ActiveRecord # :nodoc:
3
+ # = Macro test helpers for your active record models
4
+ #
5
+ # These helpers will test most of the validations and associations for your ActiveRecord models.
6
+ #
7
+ # class UserTest < Test::Unit::TestCase
8
+ # should_validate_presence_of :name, :phone_number
9
+ # should_not_allow_values_for :phone_number, "abcd", "1234"
10
+ # should_allow_values_for :phone_number, "(123) 456-7890"
11
+ #
12
+ # should_not_allow_mass_assignment_of :password
13
+ #
14
+ # should_have_one :profile
15
+ # should_have_many :dogs
16
+ # should_have_many :messes, :through => :dogs
17
+ # should_belong_to :lover
18
+ # end
19
+ #
20
+ # For all of these helpers, the last parameter may be a hash of options.
21
+ #
22
+ module Macros
23
+ include Helpers
24
+ include Matchers
25
+
26
+ # Ensures that the model cannot be saved if one of the attributes listed is not present.
27
+ #
28
+ # If an instance variable has been created in the setup named after the
29
+ # model being tested, then this method will use that. Otherwise, it will
30
+ # create a new instance to test against.
31
+ #
32
+ # Options:
33
+ # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
34
+ # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.blank')</tt>
35
+ #
36
+ # Example:
37
+ # should_validate_presence_of :name, :phone_number
38
+ #
39
+ def should_validate_presence_of(*attributes)
40
+ message = get_options!(attributes, :message)
41
+ klass = model_class
42
+
43
+ attributes.each do |attribute|
44
+ matcher = validate_presence_of(attribute).with_message(message)
45
+ should matcher.description do
46
+ assert_accepts(matcher, get_instance_of(klass))
47
+ end
48
+ end
49
+ end
50
+
51
+ # Deprecated. See should_validate_presence_of
52
+ def should_require_attributes(*attributes)
53
+ warn "[DEPRECATION] should_require_attributes is deprecated. " <<
54
+ "Use should_validate_presence_of instead."
55
+ should_validate_presence_of(*attributes)
56
+ end
57
+
58
+ # Ensures that the model cannot be saved if one of the attributes listed is not unique.
59
+ # Requires an existing record
60
+ #
61
+ # Options:
62
+
63
+ # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
64
+ # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.taken')</tt>
65
+ # * <tt>:scoped_to</tt> - field(s) to scope the uniqueness to.
66
+ # * <tt>:case_sensitive</tt> - whether or not uniqueness is defined by an
67
+ # exact match. Ignored by non-text attributes. Default = <tt>true</tt>
68
+ #
69
+ # Examples:
70
+ # should_validate_uniqueness_of :keyword, :username
71
+ # should_validate_uniqueness_of :name, :message => "O NOES! SOMEONE STOELED YER NAME!"
72
+ # should_validate_uniqueness_of :email, :scoped_to => :name
73
+ # should_validate_uniqueness_of :address, :scoped_to => [:first_name, :last_name]
74
+ # should_validate_uniqueness_of :email, :case_sensitive => false
75
+ #
76
+ def should_validate_uniqueness_of(*attributes)
77
+ message, scope, case_sensitive = get_options!(attributes, :message, :scoped_to, :case_sensitive)
78
+ scope = [*scope].compact
79
+ case_sensitive = true if case_sensitive.nil?
80
+
81
+ klass = model_class
82
+
83
+ attributes.each do |attribute|
84
+ matcher = validate_uniqueness_of(attribute).
85
+ with_message(message).scoped_to(scope)
86
+ matcher = matcher.case_insensitive unless case_sensitive
87
+ should matcher.description do
88
+ assert_accepts(matcher, get_instance_of(klass))
89
+ end
90
+ end
91
+ end
92
+
93
+ # Deprecated. See should_validate_uniqueness_of
94
+ def should_require_unique_attributes(*attributes)
95
+ warn "[DEPRECATION] should_require_unique_attributes is deprecated. " <<
96
+ "Use should_validate_uniqueness_of instead."
97
+ should_validate_uniqueness_of(*attributes)
98
+ end
99
+
100
+ # Ensures that the attribute can be set on mass update.
101
+ #
102
+ # should_allow_mass_assignment_of :first_name, :last_name
103
+ #
104
+ def should_allow_mass_assignment_of(*attributes)
105
+ get_options!(attributes)
106
+ klass = model_class
107
+
108
+ attributes.each do |attribute|
109
+ matcher = allow_mass_assignment_of(attribute)
110
+ should matcher.description do
111
+ assert_accepts matcher, klass.new
112
+ end
113
+ end
114
+ end
115
+
116
+ # Ensures that the attribute cannot be set on mass update.
117
+ #
118
+ # should_not_allow_mass_assignment_of :password, :admin_flag
119
+ #
120
+ def should_not_allow_mass_assignment_of(*attributes)
121
+ get_options!(attributes)
122
+ klass = model_class
123
+
124
+ attributes.each do |attribute|
125
+ matcher = allow_mass_assignment_of(attribute)
126
+ should "not #{matcher.description}" do
127
+ assert_rejects matcher, klass.new
128
+ end
129
+ end
130
+ end
131
+
132
+ # Deprecated. See should_not_allow_mass_assignment_of
133
+ def should_protect_attributes(*attributes)
134
+ warn "[DEPRECATION] should_protect_attributes is deprecated. " <<
135
+ "Use should_not_allow_mass_assignment_of instead."
136
+ should_not_allow_mass_assignment_of(*attributes)
137
+ end
138
+
139
+ # Ensures that the attribute cannot be changed once the record has been created.
140
+ #
141
+ # should_have_readonly_attributes :password, :admin_flag
142
+ #
143
+ def should_have_readonly_attributes(*attributes)
144
+ get_options!(attributes)
145
+ klass = model_class
146
+
147
+ attributes.each do |attribute|
148
+ matcher = have_readonly_attribute(attribute)
149
+ should matcher.description do
150
+ assert_accepts matcher, klass.new
151
+ end
152
+ end
153
+ end
154
+
155
+ # Ensures that the attribute cannot be set to the given values
156
+ #
157
+ # If an instance variable has been created in the setup named after the
158
+ # model being tested, then this method will use that. Otherwise, it will
159
+ # create a new instance to test against.
160
+ #
161
+ # Options:
162
+ # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
163
+ # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.invalid')</tt>
164
+ #
165
+ # Example:
166
+ # should_not_allow_values_for :isbn, "bad 1", "bad 2"
167
+ #
168
+ def should_not_allow_values_for(attribute, *bad_values)
169
+ message = get_options!(bad_values, :message)
170
+ klass = model_class
171
+ bad_values.each do |value|
172
+ matcher = allow_value(value).for(attribute).with_message(message)
173
+ should "not #{matcher.description}" do
174
+ assert_rejects matcher, get_instance_of(klass)
175
+ end
176
+ end
177
+ end
178
+
179
+ # Ensures that the attribute can be set to the given values.
180
+ #
181
+ # If an instance variable has been created in the setup named after the
182
+ # model being tested, then this method will use that. Otherwise, it will
183
+ # create a new instance to test against.
184
+ #
185
+ # Example:
186
+ # should_allow_values_for :isbn, "isbn 1 2345 6789 0", "ISBN 1-2345-6789-0"
187
+ #
188
+ def should_allow_values_for(attribute, *good_values)
189
+ get_options!(good_values)
190
+ klass = model_class
191
+ klass = model_class
192
+ good_values.each do |value|
193
+ matcher = allow_value(value).for(attribute)
194
+ should matcher.description do
195
+ assert_accepts matcher, get_instance_of(klass)
196
+ end
197
+ end
198
+ end
199
+
200
+ # Ensures that the length of the attribute is in the given range
201
+ #
202
+ # If an instance variable has been created in the setup named after the
203
+ # model being tested, then this method will use that. Otherwise, it will
204
+ # create a new instance to test against.
205
+ #
206
+ # Options:
207
+ # * <tt>:short_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
208
+ # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.too_short') % range.first</tt>
209
+ # * <tt>:long_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
210
+ # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.too_long') % range.last</tt>
211
+ #
212
+ # Example:
213
+ # should_ensure_length_in_range :password, (6..20)
214
+ #
215
+ def should_ensure_length_in_range(attribute, range, opts = {})
216
+ short_message, long_message = get_options!([opts],
217
+ :short_message,
218
+ :long_message)
219
+ klass = model_class
220
+
221
+ matcher = ensure_length_of(attribute).
222
+ is_at_least(range.first).
223
+ with_short_message(short_message).
224
+ is_at_most(range.last).
225
+ with_long_message(long_message)
226
+
227
+ should matcher.description do
228
+ assert_accepts matcher, get_instance_of(klass)
229
+ end
230
+ end
231
+
232
+ # Ensures that the length of the attribute is at least a certain length
233
+ #
234
+ # If an instance variable has been created in the setup named after the
235
+ # model being tested, then this method will use that. Otherwise, it will
236
+ # create a new instance to test against.
237
+ #
238
+ # Options:
239
+ # * <tt>:short_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
240
+ # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.too_short') % min_length</tt>
241
+ #
242
+ # Example:
243
+ # should_ensure_length_at_least :name, 3
244
+ #
245
+ def should_ensure_length_at_least(attribute, min_length, opts = {})
246
+ short_message = get_options!([opts], :short_message)
247
+ klass = model_class
248
+
249
+ matcher = ensure_length_of(attribute).
250
+ is_at_least(min_length).
251
+ with_short_message(short_message)
252
+
253
+ should matcher.description do
254
+ assert_accepts matcher, get_instance_of(klass)
255
+ end
256
+ end
257
+
258
+ # Ensures that the length of the attribute is exactly a certain length
259
+ #
260
+ # If an instance variable has been created in the setup named after the
261
+ # model being tested, then this method will use that. Otherwise, it will
262
+ # create a new instance to test against.
263
+ #
264
+ # Options:
265
+ # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
266
+ # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.wrong_length') % length</tt>
267
+ #
268
+ # Example:
269
+ # should_ensure_length_is :ssn, 9
270
+ #
271
+ def should_ensure_length_is(attribute, length, opts = {})
272
+ message = get_options!([opts], :message)
273
+ klass = model_class
274
+ matcher = ensure_length_of(attribute).
275
+ is_equal_to(length).
276
+ with_message(message)
277
+
278
+ should matcher.description do
279
+ assert_accepts matcher, get_instance_of(klass)
280
+ end
281
+ end
282
+
283
+ # Ensure that the attribute is in the range specified
284
+ #
285
+ # If an instance variable has been created in the setup named after the
286
+ # model being tested, then this method will use that. Otherwise, it will
287
+ # create a new instance to test against.
288
+ #
289
+ # Options:
290
+ # * <tt>:low_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
291
+ # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.inclusion')</tt>
292
+ # * <tt>:high_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
293
+ # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.inclusion')</tt>
294
+ #
295
+ # Example:
296
+ # should_ensure_value_in_range :age, (0..100)
297
+ #
298
+ def should_ensure_value_in_range(attribute, range, opts = {})
299
+ message = get_options!([opts], :message)
300
+ message ||= default_error_message(:inclusion)
301
+
302
+ klass = model_class
303
+ matcher = ensure_inclusion_of(attribute).
304
+ in_range(range).
305
+ with_message(message)
306
+ should matcher.description do
307
+ assert_accepts matcher, get_instance_of(klass)
308
+ end
309
+ end
310
+
311
+ # Ensure that the attribute is numeric
312
+ #
313
+ # If an instance variable has been created in the setup named after the
314
+ # model being tested, then this method will use that. Otherwise, it will
315
+ # create a new instance to test against.
316
+ #
317
+ # Options:
318
+ # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
319
+ # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.not_a_number')</tt>
320
+ #
321
+ # Example:
322
+ # should_validate_numericality_of :age
323
+ #
324
+ def should_validate_numericality_of(*attributes)
325
+ message = get_options!(attributes, :message)
326
+ klass = model_class
327
+ attributes.each do |attribute|
328
+ matcher = validate_numericality_of(attribute).
329
+ with_message(message)
330
+ should matcher.description do
331
+ assert_accepts matcher, get_instance_of(klass)
332
+ end
333
+ end
334
+ end
335
+
336
+ # Deprecated. See should_validate_uniqueness_of
337
+ def should_only_allow_numeric_values_for(*attributes)
338
+ warn "[DEPRECATION] should_only_allow_numeric_values_for is " <<
339
+ "deprecated. Use should_validate_numericality_of instead."
340
+ should_validate_numericality_of(*attributes)
341
+ end
342
+
343
+ # Ensures that the has_many relationship exists. Will also test that the
344
+ # associated table has the required columns. Works with polymorphic
345
+ # associations.
346
+ #
347
+ # Options:
348
+ # * <tt>:through</tt> - association name for <tt>has_many :through</tt>
349
+ # * <tt>:dependent</tt> - tests that the association makes use of the dependent option.
350
+ #
351
+ # Example:
352
+ # should_have_many :friends
353
+ # should_have_many :enemies, :through => :friends
354
+ # should_have_many :enemies, :dependent => :destroy
355
+ #
356
+ def should_have_many(*associations)
357
+ through, dependent = get_options!(associations, :through, :dependent)
358
+ klass = model_class
359
+ associations.each do |association|
360
+ matcher = have_many(association).through(through).dependent(dependent)
361
+ should matcher.description do
362
+ assert_accepts(matcher, klass.new)
363
+ end
364
+ end
365
+ end
366
+
367
+ # Ensure that the has_one relationship exists. Will also test that the
368
+ # associated table has the required columns. Works with polymorphic
369
+ # associations.
370
+ #
371
+ # Options:
372
+ # * <tt>:dependent</tt> - tests that the association makes use of the dependent option.
373
+ #
374
+ # Example:
375
+ # should_have_one :god # unless hindu
376
+ #
377
+ def should_have_one(*associations)
378
+ dependent = get_options!(associations, :dependent)
379
+ klass = model_class
380
+ associations.each do |association|
381
+ matcher = have_one(association).dependent(dependent)
382
+ should matcher.description do
383
+ assert_accepts(matcher, klass.new)
384
+ end
385
+ end
386
+ end
387
+
388
+ # Ensures that the has_and_belongs_to_many relationship exists, and that the join
389
+ # table is in place.
390
+ #
391
+ # should_have_and_belong_to_many :posts, :cars
392
+ #
393
+ def should_have_and_belong_to_many(*associations)
394
+ get_options!(associations)
395
+ klass = model_class
396
+
397
+ associations.each do |association|
398
+ matcher = have_and_belong_to_many(association)
399
+ should matcher.description do
400
+ assert_accepts(matcher, klass.new)
401
+ end
402
+ end
403
+ end
404
+
405
+ # Ensure that the belongs_to relationship exists.
406
+ #
407
+ # should_belong_to :parent
408
+ #
409
+ def should_belong_to(*associations)
410
+ dependent = get_options!(associations, :dependent)
411
+ klass = model_class
412
+ associations.each do |association|
413
+ matcher = belong_to(association).dependent(dependent)
414
+ should matcher.description do
415
+ assert_accepts(matcher, klass.new)
416
+ end
417
+ end
418
+ end
419
+
420
+ # Ensure that the given class methods are defined on the model.
421
+ #
422
+ # should_have_class_methods :find, :destroy
423
+ #
424
+ def should_have_class_methods(*methods)
425
+ get_options!(methods)
426
+ klass = model_class
427
+ methods.each do |method|
428
+ should "respond to class method ##{method}" do
429
+ assert_respond_to klass, method, "#{klass.name} does not have class method #{method}"
430
+ end
431
+ end
432
+ end
433
+
434
+ # Ensure that the given instance methods are defined on the model.
435
+ #
436
+ # should_have_instance_methods :email, :name, :name=
437
+ #
438
+ def should_have_instance_methods(*methods)
439
+ get_options!(methods)
440
+ klass = model_class
441
+ methods.each do |method|
442
+ should "respond to instance method ##{method}" do
443
+ assert_respond_to klass.new, method, "#{klass.name} does not have instance method #{method}"
444
+ end
445
+ end
446
+ end
447
+
448
+ # Ensure that the given columns are defined on the models backing SQL table.
449
+ # Also aliased to should_have_index for readability.
450
+ # Takes the same options available in migrations:
451
+ # :type, :precision, :limit, :default, :null, and :scale
452
+ #
453
+ # Examples:
454
+ #
455
+ # should_have_db_columns :id, :email, :name, :created_at
456
+ #
457
+ # should_have_db_column :email, :type => "string", :limit => 255
458
+ # should_have_db_column :salary, :decimal, :precision => 15, :scale => 2
459
+ # should_have_db_column :admin, :default => false, :null => false
460
+ #
461
+ def should_have_db_columns(*columns)
462
+ column_type, precision, limit, default, null, scale, sql_type =
463
+ get_options!(columns, :type, :precision, :limit,
464
+ :default, :null, :scale, :sql_type)
465
+ klass = model_class
466
+ columns.each do |name|
467
+ matcher = have_db_column(name).
468
+ of_type(column_type).
469
+ with_options(:precision => precision, :limit => limit,
470
+ :default => default, :null => null,
471
+ :scale => scale, :sql_type => sql_type)
472
+ should matcher.description do
473
+ assert_accepts(matcher, klass.new)
474
+ end
475
+ end
476
+ end
477
+
478
+ alias_method :should_have_db_column, :should_have_db_columns
479
+
480
+ # Ensures that there are DB indices on the given columns or tuples of columns.
481
+ # Also aliased to should_have_index for readability
482
+ #
483
+ # Options:
484
+ # * <tt>:unique</tt> - whether or not the index has a unique
485
+ # constraint. Use <tt>true</tt> to explicitly test for a unique
486
+ # constraint. Use <tt>false</tt> to explicitly test for a non-unique
487
+ # constraint. Use <tt>nil</tt> if you don't care whether the index is
488
+ # unique or not. Default = <tt>nil</tt>
489
+ #
490
+ # Examples:
491
+ #
492
+ # should_have_indices :email, :name, [:commentable_type, :commentable_id]
493
+ # should_have_index :age
494
+ # should_have_index :ssn, :unique => true
495
+ #
496
+ def should_have_indices(*columns)
497
+ unique = get_options!(columns, :unique)
498
+ klass = model_class
499
+
500
+ columns.each do |column|
501
+ matcher = have_index(column).unique(unique)
502
+ should matcher.description do
503
+ assert_accepts(matcher, klass.new)
504
+ end
505
+ end
506
+ end
507
+
508
+ alias_method :should_have_index, :should_have_indices
509
+
510
+ # Ensures that the model cannot be saved if one of the attributes listed is not accepted.
511
+ #
512
+ # If an instance variable has been created in the setup named after the
513
+ # model being tested, then this method will use that. Otherwise, it will
514
+ # create a new instance to test against.
515
+ #
516
+ # Options:
517
+ # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
518
+ # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.accepted')</tt>
519
+ #
520
+ # Example:
521
+ # should_validate_acceptance_of :eula
522
+ #
523
+ def should_validate_acceptance_of(*attributes)
524
+ message = get_options!(attributes, :message)
525
+ klass = model_class
526
+
527
+ attributes.each do |attribute|
528
+ matcher = validate_acceptance_of(attribute).with_message(message)
529
+ should matcher.description do
530
+ assert_accepts matcher, get_instance_of(klass)
531
+ end
532
+ end
533
+ end
534
+
535
+ # Deprecated. See should_validate_uniqueness_of
536
+ def should_require_acceptance_of(*attributes)
537
+ warn "[DEPRECATION] should_require_acceptance_of is deprecated. " <<
538
+ "Use should_validate_acceptance_of instead."
539
+ should_validate_acceptance_of(*attributes)
540
+ end
541
+
542
+ # Ensures that the model has a method named scope_name that returns a NamedScope object with the
543
+ # proxy options set to the options you supply. scope_name can be either a symbol, or a method
544
+ # call which will be evaled against the model. The eval'd method call has access to all the same
545
+ # instance variables that a should statement would.
546
+ #
547
+ # Options: Any of the options that the named scope would pass on to find.
548
+ #
549
+ # Example:
550
+ #
551
+ # should_have_named_scope :visible, :conditions => {:visible => true}
552
+ #
553
+ # Passes for
554
+ #
555
+ # named_scope :visible, :conditions => {:visible => true}
556
+ #
557
+ # Or for
558
+ #
559
+ # def self.visible
560
+ # scoped(:conditions => {:visible => true})
561
+ # end
562
+ #
563
+ # You can test lambdas or methods that return ActiveRecord#scoped calls:
564
+ #
565
+ # should_have_named_scope 'recent(5)', :limit => 5
566
+ # should_have_named_scope 'recent(1)', :limit => 1
567
+ #
568
+ # Passes for
569
+ # named_scope :recent, lambda {|c| {:limit => c}}
570
+ #
571
+ # Or for
572
+ #
573
+ # def self.recent(c)
574
+ # scoped(:limit => c)
575
+ # end
576
+ #
577
+ def should_have_named_scope(scope_call, find_options = nil)
578
+ klass = model_class
579
+ matcher = have_named_scope(scope_call).finding(find_options)
580
+ should matcher.description do
581
+ assert_accepts matcher.in_context(self), klass.new
582
+ end
583
+ end
584
+ end
585
+ end
586
+ end