admin_data 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. data/History.txt +221 -0
  2. data/README.textile +21 -0
  3. data/Rakefile +46 -0
  4. data/app/controllers/admin_data/base_controller.rb +114 -0
  5. data/app/controllers/admin_data/diagnostic_controller.rb +28 -0
  6. data/app/controllers/admin_data/feed_controller.rb +17 -0
  7. data/app/controllers/admin_data/main_controller.rb +132 -0
  8. data/app/controllers/admin_data/migration_controller.rb +19 -0
  9. data/app/controllers/admin_data/search_controller.rb +125 -0
  10. data/app/controllers/admin_data/validate_model_controller.rb +106 -0
  11. data/app/views/admin_data/diagnostic/index.html.erb +17 -0
  12. data/app/views/admin_data/diagnostic/missing_index.html.erb +26 -0
  13. data/app/views/admin_data/feed/index.rss.builder +24 -0
  14. data/app/views/admin_data/main/all_models.html.erb +22 -0
  15. data/app/views/admin_data/main/association/_association_info.html.erb +10 -0
  16. data/app/views/admin_data/main/association/_belongs_to_info.html.erb +7 -0
  17. data/app/views/admin_data/main/association/_has_many_info.html.erb +7 -0
  18. data/app/views/admin_data/main/association/_has_one_info.html.erb +6 -0
  19. data/app/views/admin_data/main/edit.html.erb +38 -0
  20. data/app/views/admin_data/main/misc/_form.html.erb +25 -0
  21. data/app/views/admin_data/main/misc/_modify_record.html.erb +22 -0
  22. data/app/views/admin_data/main/new.html.erb +23 -0
  23. data/app/views/admin_data/main/show.html.erb +41 -0
  24. data/app/views/admin_data/main/table_structure.html.erb +55 -0
  25. data/app/views/admin_data/migration/index.html.erb +18 -0
  26. data/app/views/admin_data/migration/jstest.html.erb +51 -0
  27. data/app/views/admin_data/search/_search_base.html.erb +34 -0
  28. data/app/views/admin_data/search/advance_search.html.erb +3 -0
  29. data/app/views/admin_data/search/quick_search.html.erb +6 -0
  30. data/app/views/admin_data/search/search/_advance_search_form.html.erb +48 -0
  31. data/app/views/admin_data/search/search/_errors.html.erb +5 -0
  32. data/app/views/admin_data/search/search/_listing.html.erb +40 -0
  33. data/app/views/admin_data/search/search/_search_form.html.erb +28 -0
  34. data/app/views/admin_data/search/search/_sortby.html.erb +18 -0
  35. data/app/views/admin_data/search/search/_title.html.erb +34 -0
  36. data/app/views/admin_data/shared/_breadcrum.html.erb +10 -0
  37. data/app/views/admin_data/shared/_drop_down_klasses.html.erb +4 -0
  38. data/app/views/admin_data/shared/_flash_message.html.erb +13 -0
  39. data/app/views/admin_data/shared/_header.html.erb +23 -0
  40. data/app/views/admin_data/shared/_powered_by.html.erb +23 -0
  41. data/app/views/admin_data/shared/_secondary_navigation.html.erb +28 -0
  42. data/app/views/admin_data/validate_model/_bad.html.erb +1 -0
  43. data/app/views/admin_data/validate_model/tid.html.erb +2 -0
  44. data/app/views/admin_data/validate_model/validate.html.erb +67 -0
  45. data/app/views/layouts/admin_data.html.erb +60 -0
  46. data/config/routes.rb +34 -0
  47. data/init.rb +1 -0
  48. data/lib/admin_data.rb +34 -0
  49. data/lib/admin_data/chelper.rb +37 -0
  50. data/lib/admin_data/compatibility.rb +7 -0
  51. data/lib/admin_data/helpers.rb +222 -0
  52. data/lib/admin_data/railtie.rb +21 -0
  53. data/lib/admin_data/search.rb +186 -0
  54. data/lib/admin_data/settings.rb +72 -0
  55. data/lib/admin_data/util.rb +237 -0
  56. data/lib/admin_data/version.rb +3 -0
  57. data/lib/admin_data_date_validation.rb +79 -0
  58. data/lib/css/app.css +224 -0
  59. data/lib/css/base.css +1071 -0
  60. data/lib/css/header.css +65 -0
  61. data/lib/css/rounded.css +18 -0
  62. data/lib/css/themes/drastic-dark/style.css +374 -0
  63. data/lib/css/umbrella.css +34 -0
  64. data/lib/css/vendor/images/ui-bg_diagonals-thick_75_f3d8d8_40x40.png +0 -0
  65. data/lib/css/vendor/images/ui-bg_dots-small_65_a6a6a6_2x2.png +0 -0
  66. data/lib/css/vendor/images/ui-bg_flat_0_333333_40x100.png +0 -0
  67. data/lib/css/vendor/images/ui-bg_flat_65_ffffff_40x100.png +0 -0
  68. data/lib/css/vendor/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  69. data/lib/css/vendor/images/ui-bg_glass_55_fbf8ee_1x400.png +0 -0
  70. data/lib/css/vendor/images/ui-bg_highlight-hard_100_eeeeee_1x100.png +0 -0
  71. data/lib/css/vendor/images/ui-bg_highlight-hard_100_f6f6f6_1x100.png +0 -0
  72. data/lib/css/vendor/images/ui-bg_highlight-soft_15_cc0000_1x100.png +0 -0
  73. data/lib/css/vendor/images/ui-icons_004276_256x240.png +0 -0
  74. data/lib/css/vendor/images/ui-icons_cc0000_256x240.png +0 -0
  75. data/lib/css/vendor/images/ui-icons_ffffff_256x240.png +0 -0
  76. data/lib/css/vendor/jquery-ui-1.7.2.custom.css +406 -0
  77. data/lib/css/vendor/qunit.css +119 -0
  78. data/lib/js/advance_search/act_on_result.js +47 -0
  79. data/lib/js/advance_search/adv_search.js +46 -0
  80. data/lib/js/advance_search/advance_search.js +60 -0
  81. data/lib/js/advance_search/advance_search_structure.js +79 -0
  82. data/lib/js/advance_search/ajaxify_advance_search.js +28 -0
  83. data/lib/js/advance_search/build_first_row.js +12 -0
  84. data/lib/js/advance_search/event_bindings.js +87 -0
  85. data/lib/js/advance_search/global_ajax_setting.js +10 -0
  86. data/lib/js/advance_search/trigger_submit_on_domready.js +6 -0
  87. data/lib/js/misc/drop_down_change.js +8 -0
  88. data/lib/js/misc/js_util.js +42 -0
  89. data/lib/js/misc/quick_search_input_focus.js +6 -0
  90. data/lib/js/test/act_on_result.js +120 -0
  91. data/lib/js/test/advance_search.js +80 -0
  92. data/lib/js/test/ajaxify_advance_search.js +29 -0
  93. data/lib/js/test/build_first_row.js +10 -0
  94. data/lib/js/test/event_bindings.js +100 -0
  95. data/lib/js/validate_model/ajaxify_form.js +66 -0
  96. data/lib/js/validate_model/select_all.js +15 -0
  97. data/lib/js/vendor/jack.js +903 -0
  98. data/lib/js/vendor/jquery-1.4.1.js +6078 -0
  99. data/lib/js/vendor/jquery-ui-1.7.2.custom.min.js +298 -0
  100. data/lib/js/vendor/jquery.ba-isjquery.js +21 -0
  101. data/lib/js/vendor/jquery.form.js +814 -0
  102. data/lib/js/vendor/jquery.lint.js +604 -0
  103. data/lib/js/vendor/log.js +9 -0
  104. data/lib/js/vendor/qunit.js +1043 -0
  105. data/lib/tasks/admin_data_tasks.rake +7 -0
  106. data/lib/tasks/validate_models_bg.rake +23 -0
  107. data/test/factories/article.rb +9 -0
  108. data/test/factories/car.rb +4 -0
  109. data/test/factories/city.rb +4 -0
  110. data/test/factories/comment.rb +6 -0
  111. data/test/factories/door.rb +4 -0
  112. data/test/factories/engine.rb +4 -0
  113. data/test/functional/base_controller_test.rb +5 -0
  114. data/test/functional/feed_controller_test.rb +34 -0
  115. data/test/functional/main_controller_test.rb +421 -0
  116. data/test/functional/migration_controller_test.rb +30 -0
  117. data/test/functional/routes_test.rb +61 -0
  118. data/test/functional/search_controller_test.rb +814 -0
  119. data/test/helper/view_helper_test.rb +177 -0
  120. data/test/misc_tests/date_validation_test.rb +32 -0
  121. data/test/misc_tests/settings_test.rb +29 -0
  122. data/test/misc_tests/util_test.rb +83 -0
  123. data/test/rails_root/Gemfile +22 -0
  124. data/test/rails_root/Gemfile.lock +101 -0
  125. data/test/rails_root/Rakefile +7 -0
  126. data/test/rails_root/app/controllers/application_controller.rb +3 -0
  127. data/test/rails_root/app/helpers/application_helper.rb +2 -0
  128. data/test/rails_root/app/models/article.rb +25 -0
  129. data/test/rails_root/app/models/city.rb +15 -0
  130. data/test/rails_root/app/models/comment.rb +13 -0
  131. data/test/rails_root/app/models/tech_magazine.rb +2 -0
  132. data/test/rails_root/app/models/vehicle/car.rb +4 -0
  133. data/test/rails_root/app/models/vehicle/door.rb +3 -0
  134. data/test/rails_root/app/models/vehicle/engine.rb +3 -0
  135. data/test/rails_root/app/views/layouts/application.html.erb +14 -0
  136. data/test/rails_root/config.ru +4 -0
  137. data/test/rails_root/config/application.rb +42 -0
  138. data/test/rails_root/config/boot.rb +13 -0
  139. data/test/rails_root/config/database.yml +22 -0
  140. data/test/rails_root/config/environment.rb +5 -0
  141. data/test/rails_root/config/environments/development.rb +22 -0
  142. data/test/rails_root/config/environments/production.rb +49 -0
  143. data/test/rails_root/config/environments/test.rb +35 -0
  144. data/test/rails_root/config/initializers/backtrace_silencers.rb +7 -0
  145. data/test/rails_root/config/initializers/inflections.rb +10 -0
  146. data/test/rails_root/config/initializers/mime_types.rb +5 -0
  147. data/test/rails_root/config/initializers/secret_token.rb +7 -0
  148. data/test/rails_root/config/initializers/session_store.rb +8 -0
  149. data/test/rails_root/config/locales/en.yml +5 -0
  150. data/test/rails_root/config/routes.rb +58 -0
  151. data/test/rails_root/db/migrate/20090809061114_create_tables.rb +70 -0
  152. data/test/rails_root/db/schema.rb +74 -0
  153. data/test/rails_root/db/seeds.rb +7 -0
  154. data/test/rails_root/script/rails +6 -0
  155. data/test/rails_root/test/performance/browsing_test.rb +0 -0
  156. data/test/rails_root/test/test_helper.rb +13 -0
  157. data/test/support/assertions.rb +20 -0
  158. data/test/test_helper.rb +74 -0
  159. metadata +321 -0
@@ -0,0 +1,30 @@
1
+ pwd = File.dirname(__FILE__)
2
+ require File.join(pwd, '..', 'test_helper')
3
+ #require 'test_helper'
4
+
5
+ pwd = File.dirname(__FILE__)
6
+ f = File.join(pwd, '..', '..', 'app', 'views')
7
+ AdminData::MainController.prepend_view_path(f)
8
+ AdminData::MigrationController.prepend_view_path(f)
9
+
10
+ class AdminData::MigrationControllerTest < ActionController::TestCase
11
+
12
+ def setup
13
+ @controller = AdminData::MigrationController.new
14
+ @request = ActionController::TestRequest.new
15
+ @response = ActionController::TestResponse.new
16
+ grant_read_only_access
17
+ end
18
+
19
+ context 'GET index' do
20
+ setup do
21
+ get :index
22
+ end
23
+ should_respond_with :success
24
+ should_assign_to :data
25
+ should 'contain title' do
26
+ assert_tag(:tag => 'h2', :content => 'Migration Information from schema_migrations table')
27
+ end
28
+ end
29
+
30
+ end
@@ -0,0 +1,61 @@
1
+ pwd = File.dirname(__FILE__)
2
+
3
+ require File.join(pwd, '..', 'test_helper')
4
+
5
+ class AdminData::MainControllerTest < ActionController::TestCase
6
+
7
+ should route(:get, '/admin_data/quick_search/article').to(:controller => 'admin_data/search',
8
+ :action => :quick_search,
9
+ :klass => 'article')
10
+
11
+ should route(:get, '/admin_data/advance_search/article').to(:controller => 'admin_data/search',
12
+ :action => :advance_search,
13
+ :klass => 'article')
14
+
15
+ should route(:get, '/admin_data/migration').to(:controller => 'admin_data/migration',
16
+ :action => :index)
17
+
18
+ should route(:get, '/admin_data').to(:controller => 'admin_data/main',
19
+ :action => :all_models)
20
+
21
+ should route(:get, '/admin_data').to(:controller => 'admin_data/main',
22
+ :action => :all_models)
23
+
24
+ should route(:get, '/admin_data/klass/article/1').to(:controller => 'admin_data/main',
25
+ :action => :show,
26
+ :klass => 'article',
27
+ :id => 1)
28
+
29
+ should route(:delete, '/admin_data/klass/article/1').to(:controller => 'admin_data/main',
30
+ :action => :destroy,
31
+ :klass => 'article',
32
+ :id => 1)
33
+
34
+ should route(:delete, '/admin_data/klass/article/1/del').to(:controller => 'admin_data/main',
35
+ :action => :del,
36
+ :klass => 'article',
37
+ :id => 1)
38
+
39
+ should route(:get, '/admin_data/klass/article/1/edit').to(:controller => 'admin_data/main',
40
+ :action => :edit,
41
+ :klass => 'article',
42
+ :id => 1)
43
+
44
+ should route(:put, '/admin_data/klass/article/1').to(:controller => 'admin_data/main',
45
+ :action => :update,
46
+ :klass => 'article',
47
+ :id => 1)
48
+
49
+ should route(:get, '/admin_data/klass/article/new').to(:controller => 'admin_data/main',
50
+ :action => :new,
51
+ :klass => 'article')
52
+
53
+ should route(:post, '/admin_data/klass/article').to(:controller => 'admin_data/main',
54
+ :action => :create,
55
+ :klass => 'article')
56
+
57
+ should route(:get, '/admin_data/klass/article/table_structure').to(:controller => 'admin_data/main',
58
+ :action => :table_structure,
59
+ :klass => 'article')
60
+
61
+ end
@@ -0,0 +1,814 @@
1
+
2
+ require 'test_helper'
3
+
4
+ pwd = File.dirname(__FILE__)
5
+ f = File.join(pwd, '..', '..', 'app', 'views')
6
+ AdminData::MainController.prepend_view_path(f)
7
+ AdminData::SearchController.prepend_view_path(f)
8
+
9
+ class AdminData::SearchControllerTest < ActionController::TestCase
10
+
11
+ def setup
12
+ @controller = AdminData::SearchController.new
13
+ @request = ActionController::TestRequest.new
14
+ @response = ActionController::TestResponse.new
15
+ @article = Factory(:article)
16
+ @car = Factory(:car, :year => 2000, :brand => 'bmw')
17
+ grant_read_only_access
18
+ end
19
+
20
+ # write filters test
21
+
22
+
23
+ context 'GET quick_search' do
24
+ context 'GET quick_search with wrong children class' do
25
+ setup do
26
+ get :quick_search, { :base => 'article',
27
+ :klass => 'comment',
28
+ :model_id => @article.id,
29
+ :children => 'wrong_children_name' }
30
+ end
31
+ should_respond_with :not_found
32
+ end
33
+
34
+ context 'with no klass param' do
35
+ setup do
36
+ assert_raises ActionController::RoutingError do
37
+ get :quick_search
38
+ end
39
+ end
40
+ end
41
+
42
+ context 'with no search query' do
43
+ setup do
44
+ get :quick_search, {:klass => Article.name.underscore}
45
+ end
46
+ should_respond_with :success
47
+ should_assign_to :records
48
+ end
49
+ context 'with has_many association' do
50
+ context 'for a nested model' do
51
+ setup do
52
+ Vehicle::Door.delete_all
53
+ @door1 = Factory(:door, :color => 'black', :car => @car)
54
+ @door2 = Factory(:door, :color => 'green', :car => @car)
55
+ get :quick_search, { :klass => @door1.class.name.underscore,
56
+ :base => @car.class.name.underscore,
57
+ :model_id => @car.id,
58
+ :children => 'doors'}
59
+ end
60
+ should_respond_with :success
61
+ should_assign_to :records
62
+ should 'have 2 records' do
63
+ assert_equal 2, assigns(:records).size
64
+ end
65
+ should 'have 2 as total number of children' do
66
+ assert_equal 2, assigns(:total_num_of_children)
67
+ end
68
+ should 'contain text' do
69
+ assert_tag(:tag => 'h2', :attributes => {:class => 'title'}, :content => /has 2/m)
70
+ end
71
+ end
72
+
73
+ context 'for a standard model' do
74
+ setup do
75
+ @comment1 = Factory(:comment, :article => @article)
76
+ @comment2 = Factory(:comment, :article => @article)
77
+ get :quick_search, { :klass => Comment.name.underscore,
78
+ :base => 'article',
79
+ :model_id => @article.id.to_s,
80
+ :children => 'comments' }
81
+ end
82
+ should_respond_with :success
83
+ should_assign_to :records
84
+ should 'have 2 records' do
85
+ assert_equal 2, assigns(:records).size
86
+ end
87
+ should 'contain text' do
88
+ assert_tag(:tag => 'h2', :attributes => {:class => 'title'}, :content => /has 2 comments/ )
89
+ end
90
+ end
91
+ end
92
+ end
93
+
94
+
95
+ context 'GET quick_search' do
96
+ context 'for a standard model' do
97
+ setup do
98
+ @comment = Factory(:comment)
99
+ @comment = Factory(:comment)
100
+ get :quick_search, {:klass => @comment.class.name.underscore}
101
+ end
102
+ should_respond_with :success
103
+ should 'contain valid link at header breadcrum' do
104
+ assert_tag( :tag => 'div', :attributes => {:class => 'breadcrum rounded'},
105
+ :descendant => {:tag => 'a',
106
+ :attributes => {:href => '/admin_data/quick_search/comment'}})
107
+ end
108
+ should 'contain proper link at table listing' do
109
+ url = "/admin_data/klass/comment/#{Comment.last.id}"
110
+ assert_tag( :tag => 'td', :descendant => {:tag => 'a', :attributes => {:href => url}})
111
+ end
112
+ end
113
+
114
+ context 'for a nested model' do
115
+ setup do
116
+ get :quick_search, {:klass => @car.class.name.underscore}
117
+ end
118
+ should_respond_with :success
119
+ should 'contain proper link at header breadcum' do
120
+ s = CGI.escape('vehicle/car')
121
+ assert_tag( :tag => 'div',
122
+ :attributes => {:class => 'breadcrum rounded'},
123
+ :descendant => {:tag => 'a', :attributes => {:href => "/admin_data/quick_search/#{s}" }})
124
+ end
125
+ should 'contain proper link at table listing' do
126
+ s = CGI.escape("vehicle/car")
127
+ url = "/admin_data/klass/#{s}/#{@car.class.last.id}"
128
+ assert_tag(:tag => 'td', :descendant => {:tag => 'a', :attributes => {:href => url}})
129
+ end
130
+ should 'have proper action name for search form' do
131
+ url = admin_data_search_path(:klass=>Vehicle::Car)
132
+ assert_tag( :tag => 'form', :attributes => {:action => url})
133
+ end
134
+ end
135
+ end
136
+
137
+ context 'GET quick_search with search term' do
138
+ setup do
139
+ Article.delete_all
140
+ @python_beginner_book = Factory(:article, :title => 'python for beginners')
141
+ @python_book = Factory(:article, :title => 'python')
142
+ @java_book = Factory(:article, :title => 'java')
143
+ @clojure_book = Factory(:article, :title => 'clojure')
144
+ end
145
+ context 'with default order' do
146
+ setup do
147
+ get :quick_search, {:klass => 'Article', :query => 'python'}
148
+ end
149
+ should_respond_with :success
150
+ should_assign_to :records
151
+ should 'have only two records' do
152
+ assert_equal 2, assigns(:records).size
153
+ end
154
+ should 'have python beginner book as the first book' do
155
+ assert_equal @python_beginner_book.id, assigns(:records).last.id
156
+ end
157
+ should 'have python book as the last book' do
158
+ assert_equal @python_book.id, assigns(:records).first.id
159
+ end
160
+ end
161
+
162
+ context 'with article_id ascending order' do
163
+ setup do
164
+ get :quick_search, { :klass => 'Article', :query => 'python', :sortby => 'article_id asc'}
165
+ end
166
+ should_respond_with :success
167
+ should_assign_to :records
168
+ should 'have only two records' do
169
+ assert_equal 2, assigns(:records).size
170
+ end
171
+ should 'have python beginner book as the first book' do
172
+ assert_equal @python_beginner_book.id, assigns(:records).first.id
173
+ end
174
+ should 'have python book as the last book' do
175
+ assert_equal @python_book.id, assigns(:records).last.id
176
+ end
177
+ end
178
+ end
179
+
180
+ context 'GET advance_search' do
181
+ context 'with no klass param' do
182
+ setup do
183
+ assert_raises ActionController::RoutingError do
184
+ get :advance_search
185
+ end
186
+ end
187
+ end
188
+
189
+ context 'with klass param' do
190
+ setup do
191
+ get :advance_search, {:klass => Article.name.underscore}
192
+ end
193
+ should_respond_with :success
194
+ should_not_assign_to :records
195
+ should 'have proper action for advance search form' do
196
+ url = admin_data_advance_search_path(:klass => Article)
197
+ assert_tag( :tag => 'form', :attributes => {:action => url})
198
+ end
199
+ end
200
+ end
201
+
202
+
203
+ context 'xhr advance_search with does_not_contain first one' do
204
+ setup do
205
+ Article.delete_all
206
+ AdminData::Config.set = ({ :is_allowed_to_update => lambda {|controller| return false} })
207
+ Factory(:article, :short_desc => 'ruby')
208
+ Factory(:article, :short_desc => 'rails')
209
+ Factory(:article, :short_desc => nil)
210
+ xml_http_request :post,
211
+ :advance_search,
212
+ { :klass => Article.name.underscore,
213
+ :sortby => 'article_id desc',
214
+ :adv_search => {'1_row' => {:col1 => 'short_desc',
215
+ :col2 => 'does_not_contain',
216
+ :col3 => 'ruby'} } }
217
+ end
218
+ should_respond_with :success
219
+ should 'contain text' do
220
+ assert_tag(:tag => 'h2', :attributes => {:class => 'title'}, :content => /Search result: 2 records found/ )
221
+ end
222
+ should 'not contain delete all link' do
223
+ assert_no_tag( :tag => 'a', :attributes => {:id => 'advance_search_delete_all'})
224
+ end
225
+ should 'not contain destroy all link' do
226
+ assert_no_tag( :tag => 'a', :attributes => {:id => 'advance_search_destroy_all'})
227
+ end
228
+ end
229
+
230
+ context 'xhr advance_search with delete_all action' do
231
+ setup do
232
+ Article.delete_all
233
+ AdminData::Config.set = ({ :is_allowed_to_update => lambda {|controller| return true} })
234
+ Factory(:article, :short_desc => 'ruby')
235
+ Factory(:article, :short_desc => 'rails')
236
+ so = {'1_row' => {:col1 => 'short_desc', :col2 => 'contains', :col3 => 'ruby'} }
237
+ h = { :klass => Article.name.underscore,
238
+ :sortby => 'article_id desc',
239
+ :admin_data_advance_search_action_type => 'delete',
240
+ :adv_search => so }
241
+ xml_http_request :post, :advance_search, h
242
+ @json = JSON.parse(@response.body)
243
+ end
244
+ should_respond_with :success
245
+ should 'have only one record' do
246
+ assert_equal 1, Article.count
247
+ end
248
+ should 'have success key in the response message' do
249
+ assert @json.has_key?('success')
250
+ end
251
+ should 'have success message in the response message' do
252
+ assert_equal '1 record deleted', @json.fetch('success')
253
+ end
254
+ end
255
+
256
+ context 'xhr advance_search with destroy_all action' do
257
+ setup do
258
+ Article.delete_all
259
+ AdminData::Config.set = ({ :is_allowed_to_update => lambda {|controller| return true} })
260
+ Factory(:article, :short_desc => 'ruby')
261
+ Factory(:article, :short_desc => 'rails')
262
+ xml_http_request :post,
263
+ :advance_search,
264
+ {:klass => Article.name.underscore,
265
+ :sortby => 'article_id desc',
266
+ :admin_data_advance_search_action_type => 'destroy',
267
+ :adv_search => {'1_row' => {:col1 => 'short_desc', :col2 => 'contains', :col3 => 'ruby'} } }
268
+ @json = JSON.parse(@response.body)
269
+ end
270
+ should_respond_with :success
271
+ should 'have only one record' do
272
+ assert_equal 1, Article.count
273
+ end
274
+ should 'have success key in the response message' do
275
+ assert @json.has_key?('success')
276
+ end
277
+ should 'have success message in the response message' do
278
+ assert_equal '1 record destroyed', @json.fetch('success')
279
+ end
280
+ end
281
+
282
+ context 'xhr advance_search with does_not_contain' do
283
+ setup do
284
+ AdminData::Config.set = ({ :is_allowed_to_update => lambda {|controller| return true } })
285
+ Article.delete_all
286
+ Factory(:article, :short_desc => 'ruby')
287
+ Factory(:article, :short_desc => 'rails')
288
+ Factory(:article, :short_desc => nil)
289
+ xml_http_request :post,
290
+ :advance_search,
291
+ {:klass => Article.name.underscore,
292
+ :sortby => 'article_id desc',
293
+ :adv_search => {'1_row' => {:col1 => 'short_desc',
294
+ :col2 => 'does_not_contain',
295
+ :col3 => 'ruby'} } }
296
+ end
297
+ should_respond_with :success
298
+ should 'contain search result' do
299
+ assert_tag(:tag => 'h2', :attributes => {:class => 'title'}, :content => /Search result: 2 records found/ )
300
+ end
301
+ should 'contain delete all link' do
302
+ assert_tag( :tag => 'a', :attributes => {:id => 'advance_search_delete_all'})
303
+ end
304
+ should 'contain destroy all link' do
305
+ assert_tag( :tag => 'a', :attributes => {:id => 'advance_search_destroy_all'})
306
+ end
307
+ end
308
+
309
+ context 'xhr advance_search with contains option with 2 records' do
310
+ setup do
311
+ Article.delete_all
312
+ @python_book = Factory(:article, :title => 'python')
313
+ @python_beginner_book = Factory(:article, :title => 'python for beginners')
314
+ @java_book = Factory(:article, :title => 'java')
315
+ @clojure_book = Factory(:article, :title => 'clojure')
316
+ xml_http_request :post,
317
+ :advance_search,
318
+ {:klass => Article.name.underscore,
319
+ :sortby => 'article_id desc',
320
+ :adv_search => {'1_row' => {:col1 => 'title', :col2 => 'contains', :col3 => 'python'} } }
321
+ end
322
+ should_respond_with :success
323
+ should 'contain text' do
324
+ assert_tag(:tag => 'h2', :attributes => {:class => 'title'}, :content => /Search result: 2 records found/ )
325
+ end
326
+ end
327
+
328
+ context 'xhr advance_search with 1 result' do
329
+ setup do
330
+ Article.delete_all
331
+ @python_book = Factory(:article, :title => 'python')
332
+ @python_beginner_book = Factory(:article, :title => 'python for beginners')
333
+ @java_book = Factory(:article, :title => 'java')
334
+ @clojure_book = Factory(:article, :title => 'clojure')
335
+ xml_http_request :post,
336
+ :advance_search,
337
+ { :klass => Article.name.underscore,
338
+ :sortby => 'article_id desc',
339
+ :adv_search => {'1_row' => {:col1 => 'title', :col2 => 'contains', :col3 => 'clojure'} } }
340
+ end
341
+ should_respond_with :success
342
+ should 'contain text' do
343
+ assert_tag(:tag => 'h2', :attributes => {:class => 'title'}, :content => /Search result: 1 record found/ )
344
+ end
345
+ end
346
+
347
+ context 'xhr advance_search with empty query term with contains option' do
348
+ setup do
349
+ Article.delete_all
350
+ @python_book = Factory(:article, :title => 'python')
351
+ @python_beginner_book = Factory(:article, :title => 'python for beginners')
352
+ @java_book = Factory(:article, :title => 'java')
353
+ @clojure_book = Factory(:article, :title => 'clojure')
354
+ xml_http_request :post,
355
+ :advance_search,
356
+ { :klass => Article.name.underscore,
357
+ :sortby => 'article_id desc',
358
+ :adv_search => {'1_row' => {:col1 => 'title', :col2 => 'contains', :col3 => ''} } }
359
+ end
360
+ should_respond_with :success
361
+ should 'contain text' do
362
+ assert_tag(:tag => 'h2', :attributes => {:class => 'title'}, :content => /Search result: 4 records found/ )
363
+ end
364
+ end
365
+
366
+ context 'xhr advance_search with empty col2' do
367
+ setup do
368
+ Article.delete_all
369
+ @python_book = Factory(:article, :title => 'python')
370
+ @python_beginner_book = Factory(:article, :title => 'python for beginners')
371
+ xml_http_request :post,
372
+ :advance_search,
373
+ { :klass => Article.name.underscore,
374
+ :sortby => 'article_id desc',
375
+ :adv_search => {'1_row' => {:col1 => 'title', :col2 => nil, :col3 => nil} } }
376
+ end
377
+ should_respond_with :success
378
+ should 'contain text' do
379
+ assert_tag(:tag => 'h2', :attributes => {:class => 'title'}, :content => /Search result: 2 records found/ )
380
+ end
381
+ end
382
+
383
+ context 'xhr advance_search with two search terms' do
384
+ setup do
385
+ Article.delete_all
386
+ @python_book = Factory(:article, :title => 'python')
387
+ @python_beginner_book = Factory(:article, :title => 'python for beginners', :body => 'for beginners')
388
+ @java_book = Factory(:article, :title => 'java')
389
+ @clojure_book = Factory(:article, :title => 'clojure', :body => 'not for beginners')
390
+ adv_search = { '1_row' => { :col1 => 'title',
391
+ :col2 => 'contains',
392
+ :col3 => 'python'},
393
+ '2_row' => {:col1 => 'body',
394
+ :col2 => 'contains',
395
+ :col3 => 'beginners'} }
396
+ xml_http_request :post,
397
+ :advance_search,
398
+ { :klass => Article.name.underscore, :sortby => 'article_id desc', :adv_search => adv_search }
399
+ end
400
+ should_respond_with :success
401
+ should 'contain text' do
402
+ assert_tag(:tag => 'h2', :attributes => {:class => 'title'}, :content => /Search result: 1 record found/ )
403
+ end
404
+ end
405
+
406
+ context 'advance search conditions' do
407
+ setup do
408
+ @klass = Object.const_get('Article')
409
+ @proc = Proc.new do
410
+ @controller.send(:build_advance_search_conditions, @klass, { '429440_row' => @hash })
411
+ end
412
+ end
413
+
414
+ context 'with col2 as null' do
415
+ should 'have sql as body is not null' do
416
+ @hash = { :col1 => 'body', :col2 => 'is_not_null'}
417
+ output = @proc.call
418
+ expected = %Q{ SELECT "articles".* FROM "articles" WHERE (articles.body IS NOT NULL) }
419
+ assert_equal_sql expected, @proc.call[:cond].to_sql
420
+ end
421
+ end
422
+
423
+ context 'with col2 contains' do
424
+ should 'have sql with like' do
425
+ @hash = { :col1 => 'body', :col2 => 'contains', :col3 => 'python'}
426
+ expected = %{ SELECT "articles".* FROM "articles" WHERE (articles.body LIKE '%python%') }
427
+ assert_equal_sql expected, @proc.call[:cond].to_sql
428
+ end
429
+ end
430
+
431
+ context 'with col2 as exactly' do
432
+ should 'have sql as body equals' do
433
+ @hash = { :col1 => 'body', :col2 => 'is_exactly', :col3 => 'python'}
434
+ expected = %{ SELECT "articles".* FROM "articles" WHERE (articles.body = 'python') }
435
+ assert_equal_sql expected , @proc.call[:cond].to_sql
436
+ end
437
+ end
438
+
439
+ context 'with does not contain' do
440
+ should 'have sql as body is null or not like' do
441
+ @hash = { :col1 => 'body', :col2 => 'does_not_contain', :col3 => 'python'}
442
+ expected = %Q{SELECT "articles".* FROM "articles" WHERE (articles.body IS NULL OR articles.body NOT LIKE '%python%')}
443
+ assert_equal_sql expected, @proc.call[:cond].to_sql
444
+ end
445
+ end
446
+
447
+ context 'with col2 as false' do
448
+ should 'have sql with body as false' do
449
+ @hash = { :col1 => 'body', :col2 => 'is_false', :col3 => 'python'}
450
+ expected = %{ SELECT "articles".* FROM "articles" WHERE (articles.body = 'f') }
451
+ assert_equal_sql expected, @proc.call[:cond].to_sql
452
+ end
453
+ end
454
+ end
455
+
456
+
457
+ context 'XHR advance_search' do
458
+ setup do
459
+ Article.delete_all
460
+ @proc = Proc.new do
461
+ @hash_big = { :klass => Article.name.underscore, :adv_search => {'2_row' => @hash } }
462
+ end
463
+ end
464
+ context 'with col2 contains' do
465
+ setup do
466
+ Factory(:article, :title => 'python')
467
+ @hash = {:col1 => 'title', :col2 => 'contains', :col3 => 'python'}
468
+ xml_http_request :post, :advance_search, @proc.call
469
+ end
470
+ should_respond_with :success
471
+ should 'contain content' do
472
+ assert_tag( :tag => 'h2', :attributes => { :class => 'title'}, :content => /Search result: 1 record found/ )
473
+ end
474
+ end
475
+
476
+ context 'with col2 contains with no search result' do
477
+ setup do
478
+ Factory(:article, :title => 'ruby')
479
+ @hash = { :col1 => 'title', :col2 => 'contains', :col3 => 'python'}
480
+ xml_http_request :post, :advance_search, @proc.call
481
+ end
482
+ should 'contain text' do
483
+ assert_tag( :tag => 'h2', :attributes => { :class => 'title' }, :content => /Search result: 0 records found/ )
484
+ end
485
+ end
486
+
487
+ context 'with col2 is_exactly' do
488
+ setup do
489
+ Factory(:article, :title => 'python')
490
+ @hash = { :col1 => 'title', :col2 => 'is_exactly', :col3 => 'python'}
491
+ xml_http_request :post, :advance_search, @proc.call
492
+ end
493
+ should 'contain text' do
494
+ assert_tag( :tag => 'h2', :attributes => { :class => 'title'}, :content => /Search result: 1 record found/ )
495
+ end
496
+ end
497
+
498
+ context 'with col2 is_exactly negative case' do
499
+ setup do
500
+ Factory(:article, :title => 'ruby')
501
+ @hash = {:col1 => 'title', :col2 => 'is_exactly', :col3 => 'python'}
502
+ xml_http_request :post, :advance_search, @proc.call
503
+ end
504
+ should 'contain text' do
505
+ assert_tag( :tag => 'h2', :attributes => { :id => 'search_result_title'}, :content => /Search result: 0 records found/ )
506
+ end
507
+ end
508
+
509
+ context 'with col2 does_not_contain' do
510
+ setup do
511
+ Factory(:article, :title => 'python')
512
+ @hash = {:col1 => 'title', :col2 => 'does_not_contain', :col3 => 'ruby'}
513
+ xml_http_request :post, :advance_search, @proc.call
514
+ end
515
+ should 'contain text' do
516
+ assert_tag( :tag => 'h2', :attributes => { :class => 'title'}, :content => /Search result: 1 record found/ )
517
+ end
518
+ end
519
+
520
+ context 'with col2 does_not_conatin negative case' do
521
+ setup do
522
+ Factory(:article, :title => 'ruby')
523
+ @hash = {:col1 => 'title', :col2 => 'does_not_contain', :col3 => 'ruby'}
524
+ xml_http_request :post, :advance_search, @proc.call
525
+ end
526
+ should 'contain text' do
527
+ assert_tag( :tag => 'h2', :attributes =>{ :class => 'title'}, :content => /Search result: 0 records found/ )
528
+ end
529
+ end
530
+
531
+ context 'with col2 is_false' do
532
+ setup do
533
+ Factory(:article, :approved => false)
534
+ @hash = {:col1 => 'approved', :col2 => 'is_false'}
535
+ xml_http_request :post, :advance_search, @proc.call
536
+ end
537
+ should 'contain text' do
538
+ assert_tag( :tag => 'h2', :attributes => {:class => 'title'}, :content => /Search result: 1 record found/ )
539
+ end
540
+ end
541
+
542
+ context 'with col2 is_false negative case' do
543
+ setup do
544
+ Factory(:article, :approved => true)
545
+ @hash = {:col1 => 'approved', :col2 => 'is_false'}
546
+ xml_http_request :post, :advance_search, @proc.call
547
+ end
548
+ should 'contain text' do
549
+ assert_tag(:tag => 'h2', :attributes => {:class => 'title'}, :content => /Search result: 0 records found/ )
550
+ end
551
+ end
552
+
553
+ context 'with col2 is_true' do
554
+ setup do
555
+ Factory(:article, :approved => true)
556
+ @hash = {:col1 => 'approved', :col2 => 'is_true'}
557
+ xml_http_request :post, :advance_search, @proc.call
558
+ end
559
+ should 'contain text' do
560
+ assert_tag( :tag => 'h2', :attributes => { :class => 'title'}, :content => /Search result: 1 record found/ )
561
+ end
562
+ end
563
+
564
+ context 'with col2 is_true negative case' do
565
+ setup do
566
+ Factory(:article, :approved => false)
567
+ @hash = {:col1 => 'approved', :col2 => 'is_true'}
568
+ xml_http_request :post, :advance_search, @proc.call
569
+ end
570
+ should 'contain text' do
571
+ assert_tag(:tag => 'h2', :attributes => {:class => 'title'}, :content => /Search result: 0 records found/ )
572
+ end
573
+ end
574
+
575
+ context 'with col2 is_null' do
576
+ setup do
577
+ Factory(:article, :status => nil)
578
+ @hash = {:col1 => 'status', :col2 => 'is_null'}
579
+ xml_http_request :post, :advance_search, @proc.call
580
+ end
581
+ should 'contain text' do
582
+ assert_tag( :tag => 'h2', :attributes => { :class => 'title' }, :content => /Search result: 1 record found/ )
583
+ end
584
+ end
585
+
586
+ context 'with col2 is_null negative case' do
587
+ setup do
588
+ Factory(:article, :status => 'something')
589
+ @hash = {:col1 => 'status', :col2 => 'is_null'}
590
+ xml_http_request :post, :advance_search, @proc.call
591
+ end
592
+ should 'contain text' do
593
+ assert_tag(:tag => 'h2', :attributes => {:class => 'title'}, :content => /Search result: 0 records found/ )
594
+ end
595
+ end
596
+
597
+ context 'with col2 is_not_null' do
598
+ setup do
599
+ Factory(:article, :status => 'something')
600
+ @hash = {:col1 => 'status', :col2 => 'is_not_null'}
601
+ xml_http_request :post, :advance_search, @proc.call
602
+ end
603
+ should 'contain text' do
604
+ assert_tag( :tag => 'h2', :attributes => { :class => 'title'}, :content => /Search result: 1 record found/ )
605
+ end
606
+ end
607
+
608
+ context 'with col2 is_not_null negative case' do
609
+ setup do
610
+ Factory(:article, :status => nil)
611
+ @hash = {:col1 => 'status', :col2 => 'is_not_null'}
612
+ xml_http_request :post, :advance_search, @proc.call
613
+ end
614
+ should 'contain text' do
615
+ assert_tag( :tag => 'h2', :attributes => { :class => 'title'}, :content => /Search result: 0 records found/ )
616
+ end
617
+ end
618
+
619
+ context 'with col2 is_equal_to' do
620
+ setup do
621
+ Factory(:article, :hits_count => 100)
622
+ @hash = {:col1 => 'hits_count', :col2 => 'is_equal_to', :col3 => 100.to_s}
623
+ xml_http_request :post, :advance_search, @proc.call
624
+ end
625
+ should 'contain text' do
626
+ assert_tag( :tag => 'h2', :attributes => { :class => 'title' }, :content => /Search result: 1 record found/ )
627
+ end
628
+ end
629
+
630
+ context 'with col2 is_equal_to negative case' do
631
+ setup do
632
+ Factory(:article, :hits_count => 100)
633
+ @hash = {:col1 => 'hits_count', :col2 => 'is_equal_to', :col3 => 101.to_s}
634
+ xml_http_request :post, :advance_search, @proc.call
635
+ end
636
+ should 'contain text' do
637
+ assert_tag( :tag => 'h2', :attributes => { :class => 'title' }, :content => /Search result: 0 records found/ )
638
+ end
639
+ end
640
+
641
+ context 'with col2 greater_than' do
642
+ setup do
643
+ Factory(:article, :hits_count => 100)
644
+ @hash = {:col1 => 'hits_count', :col2 => 'greater_than', :col3 => 99.to_s}
645
+ xml_http_request :post, :advance_search, @proc.call
646
+ end
647
+ should 'contain text' do
648
+ assert_tag( :tag => 'h2', :attributes => { :class => 'title'}, :content => /Search result: 1 record found/ )
649
+ end
650
+ end
651
+
652
+ context 'with col2 greater_than negative case' do
653
+ setup do
654
+ Factory(:article, :hits_count => 100)
655
+ @hash = {:col1 => 'hits_count', :col2 => 'greater_than', :col3 => 101.to_s}
656
+ xml_http_request :post, :advance_search, @proc.call
657
+ end
658
+ should 'contain text' do
659
+ assert_tag( :tag => 'h2', :attributes => { :class => 'title'}, :content => /Search result: 0 records found/ )
660
+ end
661
+ end
662
+
663
+ context 'with col2 less_than' do
664
+ setup do
665
+ Factory(:article, :hits_count => 100)
666
+ @hash = {:col1 => 'hits_count', :col2 => 'less_than', :col3 => 101.to_s}
667
+ xml_http_request :post, :advance_search, @proc.call
668
+ end
669
+ should 'contain text' do
670
+ assert_tag( :tag => 'h2', :attributes => { :class => 'title' }, :content => /Search result: 1 record found/ )
671
+ end
672
+ end
673
+
674
+ context 'with col2 less_than negative case' do
675
+ setup do
676
+ Factory(:article, :hits_count => 100)
677
+ @hash = {:col1 => 'hits_count', :col2 => 'less_than', :col3 => 99.to_s}
678
+ xml_http_request :post, :advance_search, @proc.call
679
+ end
680
+ should 'contain text' do
681
+ assert_tag( :tag => 'h2', :attributes => { :class => 'title' }, :content => /Search result: 0 records found/ )
682
+ end
683
+ end
684
+
685
+ context 'with col2 is_on' do
686
+ setup do
687
+ Factory(:article, :published_at => Time.now)
688
+ d = Time.now.strftime('%d-%B-%Y')
689
+ @hash = {:col1 => 'published_at', :col2 => 'is_on', :col3 => d}
690
+ xml_http_request :post, :advance_search, @proc.call
691
+ end
692
+ should 'contain text' do
693
+ assert_tag( :tag => 'h2', :attributes =>{ :class => 'title'}, :content => /Search result: 1 record found/ )
694
+ end
695
+ end
696
+
697
+ context 'with col2 is_on negative case' do
698
+ setup do
699
+ Factory(:article, :published_at => Time.now)
700
+ d = 1.year.ago.strftime('%d-%B-%Y')
701
+ @hash = {:col1 => 'published_at', :col2 => 'is_on', :col3 => d}
702
+ xml_http_request :post, :advance_search, @proc.call
703
+ end
704
+ should 'contain text' do
705
+ assert_tag( :tag => 'h2', :attributes => { :class => 'title'}, :content => /Search result: 0 records found/ )
706
+ end
707
+ end
708
+
709
+ context 'with col2 is_on_or_after_date' do
710
+ setup do
711
+ Factory(:article, :published_at => Time.now)
712
+ @hash = {:col1 => 'published_at', :col2 => 'is_on_or_after_date', :col3 => 1.month.ago.strftime('%d-%B-%Y') }
713
+ xml_http_request :post, :advance_search, @proc.call
714
+ end
715
+ should 'contain text' do
716
+ assert_tag( :tag => 'h2', :attributes => { :class => 'title'}, :descendant => /Search result: 1 record found/ )
717
+ end
718
+ end
719
+
720
+ context 'with col2 is_on_or_after_date negative case' do
721
+ setup do
722
+ Factory(:article, :published_at => Time.now)
723
+ @hash = {:col1 => 'published_at', :col2 => 'is_on_or_after_date', :col3 => 1.month.from_now.strftime('%d-%B-%Y') }
724
+ xml_http_request :post, :advance_search, @proc.call
725
+ end
726
+ should 'contain text' do
727
+ assert_tag( :tag => 'h2', :attributes => { :class => 'title' }, :content => /Search result: 0 records found/ )
728
+ end
729
+ end
730
+
731
+ context 'with col2 is_on_or_before_date' do
732
+ setup do
733
+ Factory(:article, :published_at => Time.now)
734
+ @hash = {:col1 => 'published_at', :col2 => 'is_on_or_before_date', :col3 => 1.month.from_now.strftime('%d-%B-%Y') }
735
+ xml_http_request :post, :advance_search, @proc.call
736
+ end
737
+ should 'contain text' do
738
+ assert_tag( :tag => 'h2', :attributes => { :class => 'title'}, :content => /Search result: 1 record found/ )
739
+ end
740
+ end
741
+
742
+ context 'with col2 is_on_or_before_date negative case' do
743
+ setup do
744
+ @hash = {:col1 => 'published_at', :col2 => 'is_on_or_before_date', :col3 => 1.year.ago.strftime('%d-%B-%Y') }
745
+ xml_http_request :post, :advance_search, @proc.call
746
+ end
747
+ should 'does contain text' do
748
+ assert_tag(:tag => 'h2', :attributes => {:class => 'title'}, :content => /Search result: 0 records found/ )
749
+ end
750
+ end
751
+
752
+ context 'with col2 is_on_or_before_date with invalid_date input' do
753
+ setup do
754
+ @hash = {:col1 => 'published_at', :col2 => 'is_on_or_before_date', :col3 => 'invalid_date'}
755
+ xml_http_request :post, :advance_search, @proc.call
756
+ end
757
+ should 'contain text' do
758
+ assert_tag(:tag => 'p', :attributes => {:class => 'error'}, :content => /is not a valid date/ )
759
+ end
760
+ end
761
+
762
+ context 'with col2 is_on_or_after_date with invalid_date input' do
763
+ setup do
764
+ @hash = {:col1 => 'published_at', :col2 => 'is_on_or_after_date', :col3 => 'invalid_date'}
765
+ xml_http_request :post, :advance_search, @proc.call
766
+ end
767
+ should 'contain text' do
768
+ assert_tag(:tag => 'p', :attributes => {:class => 'error'}, :content => /is not a valid date/ )
769
+ end
770
+ end
771
+
772
+ context 'is_on invalid date' do
773
+ setup do
774
+ @hash = {:col1 => 'published_at', :col2 => 'is_on', :col3 => 'invalid_date'}
775
+ xml_http_request :post, :advance_search, @proc.call
776
+ end
777
+ should 'contain text' do
778
+ assert_tag(:tag => 'p', :attributes => {:class => 'error'}, :content => /is not a valid date/ )
779
+ end
780
+ end
781
+
782
+ context 'with col2 is_equal_to with invalid input' do
783
+ setup do
784
+ @hash = {:col1 => 'hits_count', :col2 => 'is_equal_to', :col3 => 'invalid_integer'}
785
+ xml_http_request :post, :advance_search, @proc.call
786
+ end
787
+ should 'contain text' do
788
+ assert_tag(:tag => 'p', :attributes => {:class => 'error'}, :content => /is not a valid integer/ )
789
+ end
790
+ end
791
+
792
+ context 'with col2 less_than invalid_integer' do
793
+ setup do
794
+ @hash = {:col1 => 'hits_count', :col2 => 'less_than', :col3 => 'invalid_integer'}
795
+ xml_http_request :post, :advance_search, @proc.call
796
+ end
797
+ should 'contain text' do
798
+ assert_tag(:tag => 'p', :attributes => {:class => 'error'}, :content => /is not a valid integer/ )
799
+ end
800
+ end
801
+
802
+ context 'with col2 greater_than invalid integer' do
803
+ setup do
804
+ @hash = {:col1 => 'hits_count', :col2 => 'greater_than', :col3 => 'invalid_integer'}
805
+ xml_http_request :post, :advance_search, @proc.call
806
+ end
807
+ should 'contain text' do
808
+ assert_tag(:tag => 'p', :attributes => {:class => 'error'}, :content => /is not a valid integer/ )
809
+ end
810
+ end
811
+
812
+ end
813
+
814
+ end