formtastic 2.1.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (164) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +1 -0
  3. data/.github/workflows/test.yml +61 -0
  4. data/.gitignore +4 -2
  5. data/CHANGELOG.md +52 -0
  6. data/Gemfile +1 -1
  7. data/Gemfile.lock +105 -0
  8. data/MIT-LICENSE +1 -1
  9. data/{README.textile → README.md} +204 -219
  10. data/RELEASE_PROCESS +3 -1
  11. data/Rakefile +27 -29
  12. data/app/assets/stylesheets/formtastic.css +3 -2
  13. data/bin/appraisal +8 -0
  14. data/formtastic.gemspec +11 -14
  15. data/gemfiles/rails_5.2/Gemfile +5 -0
  16. data/gemfiles/rails_6.0/Gemfile +5 -0
  17. data/gemfiles/rails_6.1/Gemfile +5 -0
  18. data/gemfiles/rails_edge/Gemfile +13 -0
  19. data/lib/formtastic/action_class_finder.rb +18 -0
  20. data/lib/formtastic/actions/button_action.rb +55 -60
  21. data/lib/formtastic/actions/input_action.rb +59 -57
  22. data/lib/formtastic/actions/link_action.rb +68 -67
  23. data/lib/formtastic/actions.rb +6 -3
  24. data/lib/formtastic/deprecation.rb +5 -0
  25. data/lib/formtastic/engine.rb +3 -1
  26. data/lib/formtastic/form_builder.rb +35 -16
  27. data/lib/formtastic/helpers/action_helper.rb +34 -28
  28. data/lib/formtastic/helpers/enum.rb +13 -0
  29. data/lib/formtastic/helpers/errors_helper.rb +2 -2
  30. data/lib/formtastic/helpers/fieldset_wrapper.rb +16 -12
  31. data/lib/formtastic/helpers/form_helper.rb +19 -16
  32. data/lib/formtastic/helpers/input_helper.rb +69 -97
  33. data/lib/formtastic/helpers/inputs_helper.rb +35 -25
  34. data/lib/formtastic/helpers/reflection.rb +4 -4
  35. data/lib/formtastic/helpers.rb +1 -2
  36. data/lib/formtastic/html_attributes.rb +12 -1
  37. data/lib/formtastic/i18n.rb +1 -1
  38. data/lib/formtastic/input_class_finder.rb +18 -0
  39. data/lib/formtastic/inputs/base/choices.rb +2 -2
  40. data/lib/formtastic/inputs/base/collections.rb +46 -14
  41. data/lib/formtastic/inputs/base/database.rb +7 -2
  42. data/lib/formtastic/inputs/base/datetime_pickerish.rb +85 -0
  43. data/lib/formtastic/inputs/base/errors.rb +7 -7
  44. data/lib/formtastic/inputs/base/hints.rb +2 -2
  45. data/lib/formtastic/inputs/base/html.rb +10 -9
  46. data/lib/formtastic/inputs/base/labelling.rb +5 -8
  47. data/lib/formtastic/inputs/base/naming.rb +4 -4
  48. data/lib/formtastic/inputs/base/numeric.rb +1 -1
  49. data/lib/formtastic/inputs/base/options.rb +3 -4
  50. data/lib/formtastic/inputs/base/stringish.rb +10 -2
  51. data/lib/formtastic/inputs/base/timeish.rb +34 -22
  52. data/lib/formtastic/inputs/base/validations.rb +41 -13
  53. data/lib/formtastic/inputs/base/wrapping.rb +29 -26
  54. data/lib/formtastic/inputs/base.rb +22 -15
  55. data/lib/formtastic/inputs/boolean_input.rb +26 -12
  56. data/lib/formtastic/inputs/check_boxes_input.rb +39 -31
  57. data/lib/formtastic/inputs/color_input.rb +41 -0
  58. data/lib/formtastic/inputs/country_input.rb +24 -5
  59. data/lib/formtastic/inputs/datalist_input.rb +41 -0
  60. data/lib/formtastic/inputs/date_picker_input.rb +93 -0
  61. data/lib/formtastic/inputs/{date_input.rb → date_select_input.rb} +1 -1
  62. data/lib/formtastic/inputs/datetime_picker_input.rb +103 -0
  63. data/lib/formtastic/inputs/{datetime_input.rb → datetime_select_input.rb} +1 -1
  64. data/lib/formtastic/inputs/file_input.rb +2 -2
  65. data/lib/formtastic/inputs/hidden_input.rb +2 -6
  66. data/lib/formtastic/inputs/radio_input.rb +28 -22
  67. data/lib/formtastic/inputs/select_input.rb +36 -39
  68. data/lib/formtastic/inputs/time_picker_input.rb +99 -0
  69. data/lib/formtastic/inputs/{time_input.rb → time_select_input.rb} +6 -2
  70. data/lib/formtastic/inputs/time_zone_input.rb +16 -6
  71. data/lib/formtastic/inputs.rb +32 -21
  72. data/lib/formtastic/localized_string.rb +1 -1
  73. data/lib/formtastic/localizer.rb +24 -24
  74. data/lib/formtastic/namespaced_class_finder.rb +99 -0
  75. data/lib/formtastic/version.rb +1 -1
  76. data/lib/formtastic.rb +20 -10
  77. data/lib/generators/formtastic/form/form_generator.rb +10 -4
  78. data/lib/generators/formtastic/input/input_generator.rb +46 -0
  79. data/lib/generators/formtastic/install/install_generator.rb +5 -19
  80. data/lib/generators/templates/_form.html.slim +2 -2
  81. data/lib/generators/templates/formtastic.rb +46 -25
  82. data/lib/generators/templates/input.rb +19 -0
  83. data/sample/basic_inputs.html +23 -3
  84. data/script/integration-template.rb +74 -0
  85. data/script/integration.sh +19 -0
  86. data/spec/action_class_finder_spec.rb +12 -0
  87. data/spec/actions/button_action_spec.rb +8 -8
  88. data/spec/actions/generic_action_spec.rb +92 -56
  89. data/spec/actions/input_action_spec.rb +7 -7
  90. data/spec/actions/link_action_spec.rb +10 -10
  91. data/spec/builder/custom_builder_spec.rb +36 -20
  92. data/spec/builder/error_proc_spec.rb +4 -4
  93. data/spec/builder/semantic_fields_for_spec.rb +28 -29
  94. data/spec/fast_spec_helper.rb +12 -0
  95. data/spec/generators/formtastic/form/form_generator_spec.rb +45 -32
  96. data/spec/generators/formtastic/input/input_generator_spec.rb +124 -0
  97. data/spec/generators/formtastic/install/install_generator_spec.rb +9 -9
  98. data/spec/helpers/action_helper_spec.rb +75 -103
  99. data/spec/helpers/actions_helper_spec.rb +17 -17
  100. data/spec/helpers/form_helper_spec.rb +84 -33
  101. data/spec/helpers/input_helper_spec.rb +333 -285
  102. data/spec/helpers/inputs_helper_spec.rb +167 -121
  103. data/spec/helpers/reflection_helper_spec.rb +3 -3
  104. data/spec/helpers/semantic_errors_helper_spec.rb +23 -23
  105. data/spec/i18n_spec.rb +26 -26
  106. data/spec/input_class_finder_spec.rb +10 -0
  107. data/spec/inputs/base/collections_spec.rb +76 -0
  108. data/spec/inputs/base/validations_spec.rb +480 -0
  109. data/spec/inputs/boolean_input_spec.rb +100 -65
  110. data/spec/inputs/check_boxes_input_spec.rb +200 -101
  111. data/spec/inputs/color_input_spec.rb +85 -0
  112. data/spec/inputs/country_input_spec.rb +20 -20
  113. data/spec/inputs/custom_input_spec.rb +3 -4
  114. data/spec/inputs/datalist_input_spec.rb +61 -0
  115. data/spec/inputs/date_picker_input_spec.rb +449 -0
  116. data/spec/inputs/date_select_input_spec.rb +249 -0
  117. data/spec/inputs/datetime_picker_input_spec.rb +490 -0
  118. data/spec/inputs/datetime_select_input_spec.rb +209 -0
  119. data/spec/inputs/email_input_spec.rb +5 -5
  120. data/spec/inputs/file_input_spec.rb +6 -6
  121. data/spec/inputs/hidden_input_spec.rb +22 -35
  122. data/spec/inputs/include_blank_spec.rb +11 -11
  123. data/spec/inputs/label_spec.rb +62 -25
  124. data/spec/inputs/number_input_spec.rb +112 -112
  125. data/spec/inputs/password_input_spec.rb +5 -5
  126. data/spec/inputs/phone_input_spec.rb +5 -5
  127. data/spec/inputs/placeholder_spec.rb +6 -6
  128. data/spec/inputs/radio_input_spec.rb +99 -55
  129. data/spec/inputs/range_input_spec.rb +66 -66
  130. data/spec/inputs/readonly_spec.rb +50 -0
  131. data/spec/inputs/search_input_spec.rb +5 -5
  132. data/spec/inputs/select_input_spec.rb +170 -170
  133. data/spec/inputs/string_input_spec.rb +68 -16
  134. data/spec/inputs/text_input_spec.rb +16 -16
  135. data/spec/inputs/time_picker_input_spec.rb +455 -0
  136. data/spec/inputs/time_select_input_spec.rb +261 -0
  137. data/spec/inputs/time_zone_input_spec.rb +54 -28
  138. data/spec/inputs/url_input_spec.rb +5 -5
  139. data/spec/inputs/with_options_spec.rb +7 -7
  140. data/spec/localizer_spec.rb +39 -17
  141. data/spec/namespaced_class_finder_spec.rb +79 -0
  142. data/spec/schema.rb +21 -0
  143. data/spec/spec_helper.rb +254 -221
  144. data/spec/support/custom_macros.rb +128 -95
  145. data/spec/support/shared_examples.rb +12 -0
  146. data/spec/support/specialized_class_finder_shared_example.rb +27 -0
  147. data/spec/support/test_environment.rb +26 -10
  148. metadata +177 -238
  149. data/.travis.yml +0 -8
  150. data/Appraisals +0 -11
  151. data/CHANGELOG +0 -371
  152. data/gemfiles/rails-3.0.gemfile +0 -7
  153. data/gemfiles/rails-3.1.gemfile +0 -7
  154. data/gemfiles/rails-3.2.gemfile +0 -7
  155. data/lib/formtastic/helpers/buttons_helper.rb +0 -310
  156. data/lib/formtastic/inputs/base/grouped_collections.rb +0 -77
  157. data/lib/formtastic/util.rb +0 -25
  158. data/lib/tasks/verify_rcov.rb +0 -44
  159. data/spec/helpers/buttons_helper_spec.rb +0 -166
  160. data/spec/helpers/commit_button_helper_spec.rb +0 -530
  161. data/spec/inputs/date_input_spec.rb +0 -227
  162. data/spec/inputs/datetime_input_spec.rb +0 -185
  163. data/spec/inputs/time_input_spec.rb +0 -267
  164. data/spec/support/deferred_garbage_collection.rb +0 -21
data/spec/schema.rb ADDED
@@ -0,0 +1,21 @@
1
+ ActiveRecord::Schema.define(version: 20170208011723) do
2
+
3
+ create_table "posts", force: :cascade do |t|
4
+ t.integer "author_id", limit: 4, null: false
5
+ end
6
+
7
+ create_table "authors", force: :cascade do |t|
8
+ t.integer "age", limit: 4, null: false
9
+ t.string "name", limit: 255, null: false
10
+ t.string "surname", limit: 255, null: false
11
+ t.string "login", limit: 255
12
+ t.datetime "created_at"
13
+ t.datetime "updated_at"
14
+ end
15
+
16
+ #non-rails foreign id convention
17
+ create_table "legacy_posts", force: :cascade do |t|
18
+ t.integer "post_author", limit: 4, null: false
19
+ end
20
+
21
+ end
data/spec/spec_helper.rb CHANGED
@@ -6,8 +6,11 @@ require 'action_pack'
6
6
  require 'action_view'
7
7
  require 'action_controller'
8
8
  require 'action_dispatch'
9
+ require 'active_record'
10
+
11
+ ActiveRecord::Base.establish_connection('url' => 'sqlite3::memory:', 'pool' => 1)
12
+ load 'spec/schema.rb'
9
13
 
10
- require File.expand_path(File.join(File.dirname(__FILE__), '../lib/formtastic/util'))
11
14
  require File.expand_path(File.join(File.dirname(__FILE__), '../lib/formtastic'))
12
15
 
13
16
  require 'ammeter/init'
@@ -16,13 +19,15 @@ require 'ammeter/init'
16
19
  # in ./support/ and its subdirectories in alphabetic order.
17
20
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].sort.each {|f| require f}
18
21
 
22
+ I18n.enforce_available_locales = false if I18n.respond_to?(:enforce_available_locales)
23
+
19
24
  module FakeHelpersModule
20
25
  end
21
26
 
22
27
  module FormtasticSpecHelper
23
28
  include ActionPack
24
29
  include ActionView::Context if defined?(ActionView::Context)
25
- include ActionController::RecordIdentifier
30
+ include ActionController::RecordIdentifier if defined?(ActionController::RecordIdentifier)
26
31
  include ActionView::Helpers::FormHelper
27
32
  include ActionView::Helpers::FormTagHelper
28
33
  include ActionView::Helpers::FormOptionsHelper
@@ -36,12 +41,15 @@ module FormtasticSpecHelper
36
41
  include ActionView::Helpers::AssetTagHelper
37
42
  include ActiveSupport
38
43
  include ActionController::PolymorphicRoutes if defined?(ActionController::PolymorphicRoutes)
39
-
44
+ include ActionDispatch::Routing::PolymorphicRoutes
45
+ include AbstractController::UrlFor if defined?(AbstractController::UrlFor)
46
+ include ActionView::RecordIdentifier if defined?(ActionView::RecordIdentifier)
47
+
40
48
  include Formtastic::Helpers::FormHelper
41
49
 
42
50
  def default_input_type(column_type, column_name = :generic_column_name)
43
- @new_post.stub!(column_name)
44
- @new_post.stub!(:column_for_attribute).and_return(mock('column', :type => column_type)) unless column_type.nil?
51
+ allow(@new_post).to receive(column_name)
52
+ allow(@new_post).to receive(:column_for_attribute).and_return(double('column', :type => column_type)) unless column_type.nil?
45
53
 
46
54
  semantic_form_for(@new_post) do |builder|
47
55
  @default_type = builder.send(:default_input_type, column_name)
@@ -51,8 +59,8 @@ module FormtasticSpecHelper
51
59
  end
52
60
 
53
61
  def active_model_validator(kind, attributes, options = {})
54
- validator = mock("ActiveModel::Validations::#{kind.to_s.titlecase}Validator", :attributes => attributes, :options => options)
55
- validator.stub!(:kind).and_return(kind)
62
+ validator = double("ActiveModel::Validations::#{kind.to_s.titlecase}Validator", :attributes => attributes, :options => options)
63
+ allow(validator).to receive(:kind).and_return(kind)
56
64
  validator
57
65
  end
58
66
 
@@ -95,26 +103,17 @@ module FormtasticSpecHelper
95
103
  end
96
104
 
97
105
  module ::Namespaced
98
- class Post
99
- extend ActiveModel::Naming if defined?(ActiveModel::Naming)
100
- include ActiveModel::Conversion if defined?(ActiveModel::Conversion)
101
-
102
- def id
103
- end
104
-
105
- def persisted?
106
- end
106
+ class Post < ActiveRecord::Base
107
107
  end
108
108
  end
109
109
 
110
- class ::Author
111
- extend ActiveModel::Naming if defined?(ActiveModel::Naming)
112
- include ActiveModel::Conversion if defined?(ActiveModel::Conversion)
113
-
114
- def to_label
110
+ class ::Author < ActiveRecord::Base
111
+ def new_record?
112
+ !id
115
113
  end
116
114
 
117
- def persisted?
115
+ def to_label
116
+ [name, surname].compact.join(' ')
118
117
  end
119
118
  end
120
119
 
@@ -127,6 +126,10 @@ module FormtasticSpecHelper
127
126
  end
128
127
  end
129
128
 
129
+ class ::LegacyPost < ActiveRecord::Base
130
+ belongs_to :author, foreign_key: :post_author
131
+ end
132
+
130
133
  class ::Continent
131
134
  extend ActiveModel::Naming if defined?(ActiveModel::Naming)
132
135
  include ActiveModel::Conversion if defined?(ActiveModel::Conversion)
@@ -139,7 +142,7 @@ module FormtasticSpecHelper
139
142
 
140
143
  ##
141
144
  # We can't mock :respond_to?, so we need a concrete class override
142
- class ::MongoidReflectionMock < RSpec::Mocks::Mock
145
+ class ::MongoidReflectionMock < RSpec::Mocks::Double
143
146
  def initialize(name=nil, stubs_and_options={})
144
147
  super name, stubs_and_options
145
148
  end
@@ -148,24 +151,72 @@ module FormtasticSpecHelper
148
151
  sym == :options ? false : super
149
152
  end
150
153
  end
154
+
155
+ # Model.all returns an association proxy, which quacks a lot like an array.
156
+ # We use this in stubs or mocks where we need to return the later.
157
+ #
158
+ # TODO try delegate?
159
+ # delegate :map, :size, :length, :first, :to_ary, :each, :include?, :to => :array
160
+ class MockScope
161
+ attr_reader :array
162
+
163
+ def initialize(the_array)
164
+ @array = the_array
165
+ end
166
+
167
+ def map(&block)
168
+ array.map(&block)
169
+ end
170
+
171
+ def where(*args)
172
+ # array
173
+ self
174
+ end
175
+
176
+ def includes(*args)
177
+ self
178
+ end
179
+
180
+ def size
181
+ array.size
182
+ end
183
+ alias_method :length, :size
184
+
185
+ def first
186
+ array.first
187
+ end
188
+
189
+ def to_ary
190
+ array
191
+ end
192
+
193
+ def each(&block)
194
+ array.each(&block)
195
+ end
196
+
197
+ def include?(*args)
198
+ array.include?(*args)
199
+ end
200
+ end
151
201
 
152
202
  def _routes
153
- url_helpers = mock('url_helpers')
154
- url_helpers.stub!(:hash_for_posts_path).and_return({})
155
- url_helpers.stub!(:hash_for_post_path).and_return({})
156
- url_helpers.stub!(:hash_for_post_models_path).and_return({})
157
- url_helpers.stub!(:hash_for_authors_path).and_return({})
203
+ url_helpers = double('url_helpers')
204
+ allow(url_helpers).to receive(:hash_for_posts_path).and_return({})
205
+ allow(url_helpers).to receive(:hash_for_post_path).and_return({})
206
+ allow(url_helpers).to receive(:hash_for_post_models_path).and_return({})
207
+ allow(url_helpers).to receive(:hash_for_authors_path).and_return({})
158
208
 
159
- mock('_routes',
209
+ double('_routes',
160
210
  :url_helpers => url_helpers,
161
- :url_for => "/mock/path"
211
+ :url_for => "/mock/path",
212
+ :polymorphic_mappings => {}
162
213
  )
163
214
  end
164
215
 
165
216
  def controller
166
- env = mock('env', :[] => nil)
167
- request = mock('request', :env => env)
168
- mock('controller', :controller_path= => '', :params => {}, :request => request)
217
+ env = double('env', :[] => nil)
218
+ request = double('request', :env => env)
219
+ double('controller', :controller_path= => '', :params => {}, :request => request)
169
220
  end
170
221
 
171
222
  def default_url_options
@@ -185,209 +236,185 @@ module FormtasticSpecHelper
185
236
  def author_path(*args); "/authors/1"; end
186
237
  def authors_path(*args); "/authors"; end
187
238
  def new_author_path(*args); "/authors/new"; end
239
+
240
+ def author_array_or_scope(the_array = [@fred, @bob])
241
+ MockScope.new(the_array)
242
+ end
188
243
 
189
- @fred = ::Author.new
190
- @fred.stub!(:class).and_return(::Author)
191
- @fred.stub!(:to_label).and_return('Fred Smith')
192
- @fred.stub!(:login).and_return('fred_smith')
193
- @fred.stub!(:age).and_return(27)
194
- @fred.stub!(:id).and_return(37)
195
- @fred.stub!(:new_record?).and_return(false)
196
- @fred.stub!(:errors).and_return(mock('errors', :[] => nil))
197
- @fred.stub!(:to_key).and_return(nil)
198
- @fred.stub!(:persisted?).and_return(nil)
199
- @fred.stub!(:name).and_return('Fred')
200
-
201
- @bob = ::Author.new
202
- @bob.stub!(:to_label).and_return('Bob Rock')
203
- @bob.stub!(:login).and_return('bob')
204
- @bob.stub!(:age).and_return(43)
205
- @bob.stub!(:created_at)
206
- @bob.stub!(:id).and_return(42)
207
- @bob.stub!(:posts).and_return([])
208
- @bob.stub!(:post_ids).and_return([])
209
- @bob.stub!(:new_record?).and_return(false)
210
- @bob.stub!(:errors).and_return(mock('errors', :[] => nil))
211
- @bob.stub!(:to_key).and_return(nil)
212
- @bob.stub!(:persisted?).and_return(nil)
213
- @bob.stub!(:name).and_return('Bob')
214
-
215
- @james = ::Author.new
216
- @james.stub!(:to_label).and_return('James Shock')
217
- @james.stub!(:login).and_return('james')
218
- @james.stub!(:age).and_return(38)
219
- @james.stub!(:id).and_return(75)
220
- @james.stub!(:posts).and_return([])
221
- @james.stub!(:post_ids).and_return([])
222
- @james.stub!(:new_record?).and_return(false)
223
- @james.stub!(:errors).and_return(mock('errors', :[] => nil))
224
- @james.stub!(:to_key).and_return(nil)
225
- @james.stub!(:persisted?).and_return(nil)
226
- @james.stub!(:name).and_return('James')
227
-
228
-
229
- ::Author.stub!(:scoped).and_return(::Author)
230
- ::Author.stub!(:find).and_return([@fred, @bob])
231
- ::Author.stub!(:all).and_return([@fred, @bob])
232
- ::Author.stub!(:where).and_return([@fred, @bob])
233
- ::Author.stub!(:human_attribute_name).and_return { |column_name| column_name.humanize }
234
- ::Author.stub!(:human_name).and_return('::Author')
235
- ::Author.stub!(:reflect_on_association).and_return { |column_name| mock('reflection', :options => {}, :klass => Post, :macro => :has_many) if column_name == :posts }
236
- ::Author.stub!(:content_columns).and_return([mock('column', :name => 'login'), mock('column', :name => 'created_at')])
237
- ::Author.stub!(:to_key).and_return(nil)
238
- ::Author.stub!(:persisted?).and_return(nil)
244
+ @fred = ::Author.new(login: 'fred_smith', age: 27, name: 'Fred', id: 37)
245
+ @bob = ::Author.new(login: 'bob', age: 43, name: 'Bob', id: 42)
246
+ @james = ::Author.new(age: 38, id: 75)
247
+
248
+ allow(::Author).to receive(:scoped).and_return(::Author)
249
+ allow(::Author).to receive(:find).and_return(author_array_or_scope)
250
+ allow(::Author).to receive(:all).and_return(author_array_or_scope)
251
+ allow(::Author).to receive(:where).and_return(author_array_or_scope)
252
+ allow(::Author).to receive(:human_attribute_name) { |column_name| column_name.humanize }
253
+ allow(::Author).to receive(:human_name).and_return('::Author')
254
+ allow(::Author).to receive(:reflect_on_association) { |column_name| double('reflection', :options => {}, :klass => Post, :macro => :has_many) if column_name == :posts }
255
+ allow(::Author).to receive(:content_columns).and_return([double('column', :name => 'login'), double('column', :name => 'created_at')])
256
+ allow(::Author).to receive(:to_key).and_return(nil)
257
+ allow(::Author).to receive(:persisted?).and_return(nil)
239
258
 
240
259
  @hash_backed_author = HashBackedAuthor.new
241
260
 
242
261
  # Sometimes we need a mock @post object and some Authors for belongs_to
243
- @new_post = mock('post')
244
- @new_post.stub!(:class).and_return(::Post)
245
- @new_post.stub!(:id).and_return(nil)
246
- @new_post.stub!(:new_record?).and_return(true)
247
- @new_post.stub!(:errors).and_return(mock('errors', :[] => nil))
248
- @new_post.stub!(:author).and_return(nil)
249
- @new_post.stub!(:author_attributes=).and_return(nil)
250
- @new_post.stub!(:authors).and_return([@fred])
251
- @new_post.stub!(:authors_attributes=)
252
- @new_post.stub!(:reviewer).and_return(nil)
253
- @new_post.stub!(:main_post).and_return(nil)
254
- @new_post.stub!(:sub_posts).and_return([]) #TODO should be a mock with methods for adding sub posts
255
- @new_post.stub!(:to_key).and_return(nil)
256
- @new_post.stub!(:to_model).and_return(@new_post)
257
- @new_post.stub!(:persisted?).and_return(nil)
258
-
259
- @freds_post = mock('post')
260
- @freds_post.stub!(:to_ary)
261
- @freds_post.stub!(:class).and_return(::Post)
262
- @freds_post.stub!(:to_label).and_return('Fred Smith')
263
- @freds_post.stub!(:id).and_return(19)
264
- @freds_post.stub!(:title).and_return("Hello World")
265
- @freds_post.stub!(:author).and_return(@fred)
266
- @freds_post.stub!(:author_id).and_return(@fred.id)
267
- @freds_post.stub!(:authors).and_return([@fred])
268
- @freds_post.stub!(:author_ids).and_return([@fred.id])
269
- @freds_post.stub!(:new_record?).and_return(false)
270
- @freds_post.stub!(:errors).and_return(mock('errors', :[] => nil))
271
- @freds_post.stub!(:to_key).and_return(nil)
272
- @freds_post.stub!(:persisted?).and_return(nil)
273
- @fred.stub!(:posts).and_return([@freds_post])
274
- @fred.stub!(:post_ids).and_return([@freds_post.id])
275
-
276
- ::Post.stub!(:scoped).and_return(::Post)
277
- ::Post.stub!(:human_attribute_name).and_return { |column_name| column_name.humanize }
278
- ::Post.stub!(:human_name).and_return('Post')
279
- ::Post.stub!(:reflect_on_all_validations).and_return([])
280
- ::Post.stub!(:reflect_on_validations_for).and_return([])
281
- ::Post.stub!(:reflections).and_return({})
282
- ::Post.stub!(:reflect_on_association).and_return do |column_name|
262
+ @new_post = double('post')
263
+ allow(@new_post).to receive(:class).and_return(::Post)
264
+ allow(@new_post).to receive(:id).and_return(nil)
265
+ allow(@new_post).to receive(:new_record?).and_return(true)
266
+ allow(@new_post).to receive(:errors).and_return(double('errors', :[] => nil))
267
+ allow(@new_post).to receive(:author).and_return(nil)
268
+ allow(@new_post).to receive(:author_attributes=).and_return(nil)
269
+ allow(@new_post).to receive(:authors).and_return(author_array_or_scope([@fred]))
270
+ allow(@new_post).to receive(:authors_attributes=)
271
+ allow(@new_post).to receive(:reviewer).and_return(nil)
272
+ allow(@new_post).to receive(:main_post).and_return(nil)
273
+ allow(@new_post).to receive(:sub_posts).and_return([]) #TODO should be a mock with methods for adding sub posts
274
+ allow(@new_post).to receive(:to_key).and_return(nil)
275
+ allow(@new_post).to receive(:to_model).and_return(@new_post)
276
+ allow(@new_post).to receive(:persisted?).and_return(nil)
277
+ allow(@new_post).to receive(:model_name){ @new_post.class.model_name}
278
+
279
+ @freds_post = double('post')
280
+ allow(@freds_post).to receive(:to_ary)
281
+ allow(@freds_post).to receive(:class).and_return(::Post)
282
+ allow(@freds_post).to receive(:to_label).and_return('Fred Smith')
283
+ allow(@freds_post).to receive(:id).and_return(19)
284
+ allow(@freds_post).to receive(:title).and_return("Hello World")
285
+ allow(@freds_post).to receive(:author).and_return(@fred)
286
+ allow(@freds_post).to receive(:author_id).and_return(@fred.id)
287
+ allow(@freds_post).to receive(:authors).and_return([@fred])
288
+ allow(@freds_post).to receive(:author_ids).and_return([@fred.id])
289
+ allow(@freds_post).to receive(:new_record?).and_return(false)
290
+ allow(@freds_post).to receive(:errors).and_return(double('errors', :[] => nil))
291
+ allow(@freds_post).to receive(:to_key).and_return(nil)
292
+ allow(@freds_post).to receive(:persisted?).and_return(nil)
293
+ allow(@freds_post).to receive(:model_name){ @freds_post.class.model_name}
294
+ allow(@freds_post).to receive(:to_model).and_return(@freds_post)
295
+ allow(@fred).to receive(:posts).and_return(author_array_or_scope([@freds_post]))
296
+ allow(@fred).to receive(:post_ids).and_return([@freds_post.id])
297
+
298
+ allow(::Post).to receive(:scoped).and_return(::Post)
299
+ allow(::Post).to receive(:human_attribute_name) { |column_name| column_name.humanize }
300
+ allow(::Post).to receive(:human_name).and_return('Post')
301
+ allow(::Post).to receive(:reflect_on_all_validations).and_return([])
302
+ allow(::Post).to receive(:reflect_on_validations_for).and_return([])
303
+ allow(::Post).to receive(:reflections).and_return({})
304
+ allow(::Post).to receive(:reflect_on_association) { |column_name|
283
305
  case column_name
284
306
  when :author, :author_status
285
- mock = mock('reflection', :options => {}, :klass => ::Author, :macro => :belongs_to)
286
- mock.stub!(:[]).with(:class_name).and_return("Author")
307
+ mock = double('reflection', :options => {}, :klass => ::Author, :macro => :belongs_to)
308
+ allow(mock).to receive(:[]).with(:class_name).and_return("Author")
287
309
  mock
288
310
  when :reviewer
289
- mock = mock('reflection', :options => {:class_name => 'Author'}, :klass => ::Author, :macro => :belongs_to)
290
- mock.stub!(:[]).with(:class_name).and_return("Author")
311
+ mock = double('reflection', :options => {:class_name => 'Author'}, :klass => ::Author, :macro => :belongs_to)
312
+ allow(mock).to receive(:[]).with(:class_name).and_return("Author")
291
313
  mock
292
314
  when :authors
293
- mock('reflection', :options => {}, :klass => ::Author, :macro => :has_and_belongs_to_many)
315
+ double('reflection', :options => {}, :klass => ::Author, :macro => :has_and_belongs_to_many)
294
316
  when :sub_posts
295
- mock('reflection', :options => {}, :klass => ::Post, :macro => :has_many)
317
+ double('reflection', :options => {}, :klass => ::Post, :macro => :has_many)
296
318
  when :main_post
297
- mock('reflection', :options => {}, :klass => ::Post, :macro => :belongs_to)
319
+ double('reflection', :options => {}, :klass => ::Post, :macro => :belongs_to)
298
320
  when :mongoid_reviewer
299
321
  ::MongoidReflectionMock.new('reflection',
300
322
  :options => Proc.new { raise NoMethodError, "Mongoid has no reflection.options" },
301
323
  :klass => ::Author, :macro => :referenced_in, :foreign_key => "reviewer_id") # custom id
302
324
  end
303
- end
304
- ::Post.stub!(:find).and_return([@freds_post])
305
- ::Post.stub!(:all).and_return([@freds_post])
306
- ::Post.stub!(:where).and_return([@freds_post])
307
- ::Post.stub!(:content_columns).and_return([mock('column', :name => 'title'), mock('column', :name => 'body'), mock('column', :name => 'created_at')])
308
- ::Post.stub!(:to_key).and_return(nil)
309
- ::Post.stub!(:persisted?).and_return(nil)
310
- ::Post.stub!(:to_ary)
311
-
312
- ::MongoPost.stub!(:human_attribute_name).and_return { |column_name| column_name.humanize }
313
- ::MongoPost.stub!(:human_name).and_return('MongoPost')
314
- ::MongoPost.stub!(:associations).and_return({
315
- :sub_posts => mock('reflection', :options => {:polymorphic => true}, :klass => ::MongoPost, :macro => :has_many),
325
+ }
326
+ allow(::Post).to receive(:find).and_return(author_array_or_scope([@freds_post]))
327
+ allow(::Post).to receive(:all).and_return(author_array_or_scope([@freds_post]))
328
+ allow(::Post).to receive(:where).and_return(author_array_or_scope([@freds_post]))
329
+ allow(::Post).to receive(:content_columns).and_return([double('column', :name => 'title'), double('column', :name => 'body'), double('column', :name => 'created_at')])
330
+ allow(::Post).to receive(:to_key).and_return(nil)
331
+ allow(::Post).to receive(:persisted?).and_return(nil)
332
+ allow(::Post).to receive(:to_ary)
333
+
334
+ allow(::MongoPost).to receive(:human_attribute_name) { |column_name| column_name.humanize }
335
+ allow(::MongoPost).to receive(:human_name).and_return('MongoPost')
336
+ allow(::MongoPost).to receive(:associations).and_return({
337
+ :sub_posts => double('reflection', :options => {:polymorphic => true}, :klass => ::MongoPost, :macro => :has_many),
316
338
  :options => []
317
339
  })
318
- ::MongoPost.stub!(:find).and_return([@freds_post])
319
- ::MongoPost.stub!(:all).and_return([@freds_post])
320
- ::MongoPost.stub!(:where).and_return([@freds_post])
321
- ::MongoPost.stub!(:to_key).and_return(nil)
322
- ::MongoPost.stub!(:persisted?).and_return(nil)
323
- ::MongoPost.stub!(:to_ary)
324
- ::MongoPost.stub!(:model_name).and_return( mock(:model_name_mock, :singular => "post", :plural => "posts", :param_key => "post", :route_key => "posts") )
325
-
326
- @new_mm_post = mock('mm_post')
327
- @new_mm_post.stub!(:class).and_return(::MongoPost)
328
- @new_mm_post.stub!(:id).and_return(nil)
329
- @new_mm_post.stub!(:new_record?).and_return(true)
330
- @new_mm_post.stub!(:errors).and_return(mock('errors', :[] => nil))
331
- @new_mm_post.stub!(:title).and_return("Hello World")
332
- @new_mm_post.stub!(:sub_posts).and_return([]) #TODO should be a mock with methods for adding sub posts
333
- @new_mm_post.stub!(:to_key).and_return(nil)
334
- @new_mm_post.stub!(:to_model).and_return(@new_mm_post)
335
- @new_mm_post.stub!(:persisted?).and_return(nil)
336
-
337
- @mock_file = mock('file')
340
+ allow(::MongoPost).to receive(:find).and_return(author_array_or_scope([@freds_post]))
341
+ allow(::MongoPost).to receive(:all).and_return(author_array_or_scope([@freds_post]))
342
+ allow(::MongoPost).to receive(:where).and_return(author_array_or_scope([@freds_post]))
343
+ allow(::MongoPost).to receive(:to_key).and_return(nil)
344
+ allow(::MongoPost).to receive(:persisted?).and_return(nil)
345
+ allow(::MongoPost).to receive(:to_ary)
346
+ allow(::MongoPost).to receive(:model_name).and_return( double(:model_name_mock, :singular => "post", :plural => "posts", :param_key => "post", :route_key => "posts", :name => "post") )
347
+
348
+ @new_mm_post = double('mm_post')
349
+ allow(@new_mm_post).to receive(:class).and_return(::MongoPost)
350
+ allow(@new_mm_post).to receive(:id).and_return(nil)
351
+ allow(@new_mm_post).to receive(:new_record?).and_return(true)
352
+ allow(@new_mm_post).to receive(:errors).and_return(double('errors', :[] => nil))
353
+ allow(@new_mm_post).to receive(:title).and_return("Hello World")
354
+ allow(@new_mm_post).to receive(:sub_posts).and_return([]) #TODO should be a mock with methods for adding sub posts
355
+ allow(@new_mm_post).to receive(:to_key).and_return(nil)
356
+ allow(@new_mm_post).to receive(:to_model).and_return(@new_mm_post)
357
+ allow(@new_mm_post).to receive(:persisted?).and_return(nil)
358
+ allow(@new_mm_post).to receive(:model_name).and_return(::MongoPost.model_name)
359
+
360
+ @mock_file = double('file')
338
361
  Formtastic::FormBuilder.file_methods.each do |method|
339
- @mock_file.stub!(method).and_return(true)
362
+ allow(@mock_file).to receive(method).and_return(true)
340
363
  end
341
364
 
342
- @new_post.stub!(:title)
343
- @new_post.stub!(:email)
344
- @new_post.stub!(:url)
345
- @new_post.stub!(:phone)
346
- @new_post.stub!(:search)
347
- @new_post.stub!(:to_ary)
348
- @new_post.stub!(:body)
349
- @new_post.stub!(:published)
350
- @new_post.stub!(:publish_at)
351
- @new_post.stub!(:created_at)
352
- @new_post.stub!(:secret).and_return(1)
353
- @new_post.stub!(:url)
354
- @new_post.stub!(:email)
355
- @new_post.stub!(:search)
356
- @new_post.stub!(:phone)
357
- @new_post.stub!(:time_zone)
358
- @new_post.stub!(:category_name)
359
- @new_post.stub!(:allow_comments).and_return(true)
360
- @new_post.stub!(:answer_comments)
361
- @new_post.stub!(:country)
362
- @new_post.stub!(:country_subdivision)
363
- @new_post.stub!(:country_code)
364
- @new_post.stub!(:document).and_return(@mock_file)
365
- @new_post.stub!(:column_for_attribute).with(:meta_description).and_return(mock('column', :type => :string, :limit => 255))
366
- @new_post.stub!(:column_for_attribute).with(:title).and_return(mock('column', :type => :string, :limit => 50))
367
- @new_post.stub!(:column_for_attribute).with(:body).and_return(mock('column', :type => :text))
368
- @new_post.stub!(:column_for_attribute).with(:published).and_return(mock('column', :type => :boolean))
369
- @new_post.stub!(:column_for_attribute).with(:publish_at).and_return(mock('column', :type => :date))
370
- @new_post.stub!(:column_for_attribute).with(:time_zone).and_return(mock('column', :type => :string))
371
- @new_post.stub!(:column_for_attribute).with(:allow_comments).and_return(mock('column', :type => :boolean))
372
- @new_post.stub!(:column_for_attribute).with(:author).and_return(mock('column', :type => :integer))
373
- @new_post.stub!(:column_for_attribute).with(:country).and_return(mock('column', :type => :string, :limit => 255))
374
- @new_post.stub!(:column_for_attribute).with(:country_subdivision).and_return(mock('column', :type => :string, :limit => 255))
375
- @new_post.stub!(:column_for_attribute).with(:country_code).and_return(mock('column', :type => :string, :limit => 255))
376
- @new_post.stub!(:column_for_attribute).with(:email).and_return(mock('column', :type => :string, :limit => 255))
377
- @new_post.stub!(:column_for_attribute).with(:url).and_return(mock('column', :type => :string, :limit => 255))
378
- @new_post.stub!(:column_for_attribute).with(:phone).and_return(mock('column', :type => :string, :limit => 255))
379
- @new_post.stub!(:column_for_attribute).with(:search).and_return(mock('column', :type => :string, :limit => 255))
380
- @new_post.stub!(:column_for_attribute).with(:document).and_return(nil)
381
-
382
- @new_post.stub!(:author).and_return(@bob)
383
- @new_post.stub!(:author_id).and_return(@bob.id)
384
-
385
- @new_post.stub!(:reviewer).and_return(@fred)
386
- @new_post.stub!(:reviewer_id).and_return(@fred.id)
387
-
388
- @new_post.should_receive(:publish_at=).any_number_of_times
389
- @new_post.should_receive(:title=).any_number_of_times
390
- @new_post.stub!(:main_post_id).and_return(nil)
365
+ allow(@new_post).to receive(:title)
366
+ allow(@new_post).to receive(:email)
367
+ allow(@new_post).to receive(:url)
368
+ allow(@new_post).to receive(:phone)
369
+ allow(@new_post).to receive(:search)
370
+ allow(@new_post).to receive(:to_ary)
371
+ allow(@new_post).to receive(:body)
372
+ allow(@new_post).to receive(:published)
373
+ allow(@new_post).to receive(:publish_at)
374
+ allow(@new_post).to receive(:created_at)
375
+ allow(@new_post).to receive(:secret).and_return(1)
376
+ allow(@new_post).to receive(:url)
377
+ allow(@new_post).to receive(:email)
378
+ allow(@new_post).to receive(:color)
379
+ allow(@new_post).to receive(:search)
380
+ allow(@new_post).to receive(:phone)
381
+ allow(@new_post).to receive(:time_zone)
382
+ allow(@new_post).to receive(:category_name)
383
+ allow(@new_post).to receive(:allow_comments).and_return(true)
384
+ allow(@new_post).to receive(:answer_comments)
385
+ allow(@new_post).to receive(:country)
386
+ allow(@new_post).to receive(:country_subdivision)
387
+ allow(@new_post).to receive(:country_code)
388
+ allow(@new_post).to receive(:document).and_return(@mock_file)
389
+ allow(@new_post).to receive(:column_for_attribute).with(:meta_description).and_return(double('column', :type => :string, :limit => 255))
390
+ allow(@new_post).to receive(:column_for_attribute).with(:title).and_return(double('column', :type => :string, :limit => 50))
391
+ allow(@new_post).to receive(:column_for_attribute).with(:body).and_return(double('column', :type => :text))
392
+ allow(@new_post).to receive(:column_for_attribute).with(:published).and_return(double('column', :type => :boolean))
393
+ allow(@new_post).to receive(:column_for_attribute).with(:publish_at).and_return(double('column', :type => :date))
394
+ allow(@new_post).to receive(:column_for_attribute).with(:time_zone).and_return(double('column', :type => :string))
395
+ allow(@new_post).to receive(:column_for_attribute).with(:allow_comments).and_return(double('column', :type => :boolean))
396
+ allow(@new_post).to receive(:column_for_attribute).with(:author).and_return(double('column', :type => :integer))
397
+ allow(@new_post).to receive(:column_for_attribute).with(:country).and_return(double('column', :type => :string, :limit => 255))
398
+ allow(@new_post).to receive(:column_for_attribute).with(:country_subdivision).and_return(double('column', :type => :string, :limit => 255))
399
+ allow(@new_post).to receive(:column_for_attribute).with(:country_code).and_return(double('column', :type => :string, :limit => 255))
400
+ allow(@new_post).to receive(:column_for_attribute).with(:email).and_return(double('column', :type => :string, :limit => 255))
401
+ allow(@new_post).to receive(:column_for_attribute).with(:color).and_return(double('column', :type => :string, :limit => 255))
402
+ allow(@new_post).to receive(:column_for_attribute).with(:url).and_return(double('column', :type => :string, :limit => 255))
403
+ allow(@new_post).to receive(:column_for_attribute).with(:phone).and_return(double('column', :type => :string, :limit => 255))
404
+ allow(@new_post).to receive(:column_for_attribute).with(:search).and_return(double('column', :type => :string, :limit => 255))
405
+ allow(@new_post).to receive(:column_for_attribute).with(:document).and_return(nil)
406
+
407
+ allow(@new_post).to receive(:author).and_return(@bob)
408
+ allow(@new_post).to receive(:author_id).and_return(@bob.id)
409
+
410
+ allow(@new_post).to receive(:reviewer).and_return(@fred)
411
+ allow(@new_post).to receive(:reviewer_id).and_return(@fred.id)
412
+
413
+ # @new_post.should_receive(:publish_at=).at_least(:once)
414
+ allow(@new_post).to receive(:publish_at=)
415
+ # @new_post.should_receive(:title=).at_least(:once)
416
+ allow(@new_post).to receive(:title=)
417
+ allow(@new_post).to receive(:main_post_id).and_return(nil)
391
418
 
392
419
  end
393
420
 
@@ -413,20 +440,26 @@ module FormtasticSpecHelper
413
440
  yield
414
441
  Formtastic::FormBuilder.send(:"#{config_method_name}=", old_value)
415
442
  end
443
+
444
+ RSpec::Matchers.define :errors_matcher do |expected|
445
+ match { |actual| actual.to_s == expected.to_s }
446
+ end
447
+ end
416
448
 
449
+ class ::ActionView::Base
450
+ include Formtastic::Helpers::FormHelper
417
451
  end
418
452
 
419
453
  ::ActiveSupport::Deprecation.silenced = false
420
454
 
421
455
  RSpec.configure do |config|
422
- config.before(:each) do
456
+ config.infer_spec_type_from_file_location!
457
+
458
+ config.filter_run focus: true
459
+ config.filter_run_excluding skip: true
460
+ config.run_all_when_everything_filtered = true
461
+
462
+ config.before(:example) do
423
463
  Formtastic::Localizer.cache.clear!
424
464
  end
425
-
426
- config.before(:all) do
427
- DeferredGarbageCollection.start unless ENV["DEFER_GC"] == "false"
428
- end
429
- config.after(:all) do
430
- DeferredGarbageCollection.reconsider unless ENV["DEFER_GC"] == "false"
431
- end
432
465
  end