active_admin_import 2.1.2 → 3.0.0.pre
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.
- checksums.yaml +4 -4
- data/.hound.yml +4 -0
- data/.travis.yml +9 -0
- data/Gemfile +16 -0
- data/README.md +73 -173
- data/Rakefile +7 -2
- data/active_admin_import.gemspec +5 -3
- data/app/views/admin/import.html.erb +1 -1
- data/config/locales/en.yml +11 -4
- data/config/locales/es.yml +18 -0
- data/config/locales/it.yml +3 -1
- data/config/locales/zh-CN.yml +24 -0
- data/lib/active_admin_import/dsl.rb +39 -31
- data/lib/active_admin_import/import_result.rb +39 -0
- data/lib/active_admin_import/importer.rb +91 -44
- data/lib/active_admin_import/model.rb +80 -29
- data/lib/active_admin_import/options.rb +44 -0
- data/lib/active_admin_import/version.rb +1 -1
- data/lib/active_admin_import.rb +3 -0
- data/spec/fixtures/files/author.csv +2 -0
- data/spec/fixtures/files/author_broken_header.csv +2 -0
- data/spec/fixtures/files/author_invalid.csv +2 -0
- data/spec/fixtures/files/authors.csv +3 -0
- data/spec/fixtures/files/authors_bom.csv +3 -0
- data/spec/fixtures/files/authors_invalid_db.csv +3 -0
- data/spec/fixtures/files/authors_invalid_model.csv +3 -0
- data/spec/fixtures/files/authors_no_headers.csv +2 -0
- data/spec/fixtures/files/authors_win1251_win_endline.csv +3 -0
- data/spec/fixtures/files/authors_with_ids.csv +3 -0
- data/spec/fixtures/files/authors_with_semicolons.csv +3 -0
- data/spec/fixtures/files/empty.csv +0 -0
- data/spec/fixtures/files/only_headers.csv +1 -0
- data/spec/fixtures/files/posts.csv +4 -0
- data/spec/fixtures/files/posts_for_author.csv +3 -0
- data/spec/fixtures/files/posts_for_author_no_headers.csv +2 -0
- data/spec/import_result_spec.rb +32 -0
- data/spec/import_spec.rb +432 -0
- data/spec/model_spec.rb +5 -0
- data/spec/spec_helper.rb +72 -0
- data/spec/support/active_model_lint.rb +14 -0
- data/spec/support/admin.rb +20 -0
- data/spec/support/rails_template.rb +29 -0
- data/tasks/test.rake +6 -0
- metadata +80 -19
data/spec/import_spec.rb
ADDED
@@ -0,0 +1,432 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'import', type: :feature do
|
4
|
+
|
5
|
+
shared_examples 'successful inserts' do |encoding, csv_file_name|
|
6
|
+
let(:options) do
|
7
|
+
attributes = { force_encoding: encoding }
|
8
|
+
{ template_object: ActiveAdminImport::Model.new(attributes) }
|
9
|
+
end
|
10
|
+
|
11
|
+
before do
|
12
|
+
upload_file!(csv_file_name)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should import file with many records" do
|
16
|
+
expect(page).to have_content "Successfully imported 2 authors"
|
17
|
+
expect(Author.count).to eq(2)
|
18
|
+
Author.all.each do |author|
|
19
|
+
expect(author).to be_valid
|
20
|
+
expect(author.name).to be_present
|
21
|
+
expect(author.last_name).to be_present
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def with_zipped_csv(name, &block)
|
27
|
+
|
28
|
+
zip_file = File.expand_path("./spec/fixtures/files/#{name}.zip")
|
29
|
+
|
30
|
+
begin
|
31
|
+
Zip::File.open(zip_file, Zip::File::CREATE) do |z|
|
32
|
+
z.add "#{name}.csv", File.expand_path("./spec/fixtures/files/#{name}.csv")
|
33
|
+
end
|
34
|
+
instance_eval &block
|
35
|
+
ensure
|
36
|
+
File.delete zip_file rescue nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def upload_file!(name, ext='csv')
|
41
|
+
attach_file('active_admin_import_model_file', File.expand_path("./spec/fixtures/files/#{name}.#{ext}"))
|
42
|
+
find_button('Import').click
|
43
|
+
end
|
44
|
+
|
45
|
+
context "posts index" do
|
46
|
+
before do
|
47
|
+
Author.create!(name: "John", last_name: "Doe")
|
48
|
+
Author.create!(name: "Jane", last_name: "Roe")
|
49
|
+
end
|
50
|
+
|
51
|
+
context "for csv for particular author" do
|
52
|
+
let(:author) { Author.take }
|
53
|
+
|
54
|
+
shared_examples 'successful inserts for author' do
|
55
|
+
it "should use predefined author_id" do
|
56
|
+
expect(Post.where(author_id: author.id).count).to eq(Post.count)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should be imported" do
|
60
|
+
expect(Post.count).to eq(2)
|
61
|
+
expect(page).to have_content "Successfully imported 2 posts"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
context "no headers" do
|
66
|
+
before do
|
67
|
+
add_post_resource(template_object: ActiveAdminImport::Model.new(author_id: author.id,
|
68
|
+
csv_headers: [:title, :body, :author_id]),
|
69
|
+
validate: true,
|
70
|
+
before_batch_import: ->(importer) do
|
71
|
+
importer.csv_lines.map! { |row| row << importer.model.author_id }
|
72
|
+
end
|
73
|
+
)
|
74
|
+
|
75
|
+
visit "/admin/posts/import"
|
76
|
+
upload_file!(:posts_for_author_no_headers)
|
77
|
+
end
|
78
|
+
include_examples 'successful inserts for author'
|
79
|
+
end
|
80
|
+
|
81
|
+
context "with headers" do
|
82
|
+
before do
|
83
|
+
add_post_resource(template_object: ActiveAdminImport::Model.new(author_id: author.id),
|
84
|
+
validate: true,
|
85
|
+
before_batch_import: ->(importer) do
|
86
|
+
importer.csv_lines.map! { |row| row << importer.model.author_id }
|
87
|
+
importer.headers.merge!({ :'Author Id' => :author_id })
|
88
|
+
end
|
89
|
+
)
|
90
|
+
|
91
|
+
visit "/admin/posts/import"
|
92
|
+
upload_file!(:posts_for_author)
|
93
|
+
end
|
94
|
+
include_examples 'successful inserts for author'
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context "for csv with author name" do
|
99
|
+
before do
|
100
|
+
add_post_resource(
|
101
|
+
validate: true,
|
102
|
+
template_object: ActiveAdminImport::Model.new,
|
103
|
+
headers_rewrites: { :'Author Name' => :author_id },
|
104
|
+
before_batch_import: ->(importer) do
|
105
|
+
authors_names = importer.values_at(:author_id)
|
106
|
+
# replacing author name with author id
|
107
|
+
authors = Author.where(name: authors_names).pluck(:name, :id)
|
108
|
+
#{"Jane" => 2, "John" => 1}
|
109
|
+
options = Hash[*authors.flatten]
|
110
|
+
importer.batch_replace(:author_id, options)
|
111
|
+
end
|
112
|
+
)
|
113
|
+
visit "/admin/posts/import"
|
114
|
+
upload_file!(:posts)
|
115
|
+
end
|
116
|
+
|
117
|
+
it "should resolve author_id by author name" do
|
118
|
+
Post.all.each do |post|
|
119
|
+
expect(Author.where(id: post.author.id)).to be_present
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should be imported" do
|
124
|
+
expect(Post.count).to eq(2)
|
125
|
+
expect(page).to have_content "Successfully imported 2 posts"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context "authors index" do
|
131
|
+
before do
|
132
|
+
add_author_resource
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should navigate to import page" do
|
136
|
+
#todo: removing this causes undefined method `ransack' for #<ActiveRecord::Relation []>
|
137
|
+
allow_any_instance_of(Admin::AuthorsController).to receive(:find_collection).and_return(Author.all)
|
138
|
+
visit '/admin/authors'
|
139
|
+
find_link('Import Authors').click
|
140
|
+
expect(current_path).to eq("/admin/authors/import")
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
context "with custom block" do
|
145
|
+
before do
|
146
|
+
add_author_resource({}) do
|
147
|
+
flash[:notice] = 'some custom message'
|
148
|
+
end
|
149
|
+
visit '/admin/authors/import'
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should display notice from custom block" do
|
153
|
+
upload_file!(:author)
|
154
|
+
expect(page).to have_content "some custom message"
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
|
159
|
+
context "authors already exist" do
|
160
|
+
before do
|
161
|
+
Author.create!(id: 1, name: "Jane", last_name: "Roe")
|
162
|
+
Author.create!(id: 2, name: "John", last_name: "Doe")
|
163
|
+
end
|
164
|
+
|
165
|
+
context "having authors with the same Id" do
|
166
|
+
before do
|
167
|
+
add_author_resource(
|
168
|
+
before_batch_import: ->(importer) do
|
169
|
+
Author.where(id: importer.values_at("id")).delete_all
|
170
|
+
end
|
171
|
+
)
|
172
|
+
visit "/admin/authors/import"
|
173
|
+
upload_file!(:authors_with_ids)
|
174
|
+
end
|
175
|
+
|
176
|
+
it "should replace authors" do
|
177
|
+
expect(page).to have_content "Successfully imported 2 authors"
|
178
|
+
expect(Author.count).to eq(2)
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should replace authors by id" do
|
182
|
+
expect(Author.find(1).name).to eq("John")
|
183
|
+
expect(Author.find(2).name).to eq("Jane")
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
context "with valid options" do
|
189
|
+
|
190
|
+
let(:options) { {} }
|
191
|
+
|
192
|
+
before do
|
193
|
+
add_author_resource(options)
|
194
|
+
visit '/admin/authors/import'
|
195
|
+
end
|
196
|
+
|
197
|
+
it "has valid form" do
|
198
|
+
form = find('#new_active_admin_import_model')
|
199
|
+
expect(form['action']).to eq("/admin/authors/do_import")
|
200
|
+
expect(form['enctype']).to eq("multipart/form-data")
|
201
|
+
file_input = form.find("input#active_admin_import_model_file")
|
202
|
+
expect(file_input[:type]).to eq("file")
|
203
|
+
expect(file_input.value).to be_blank
|
204
|
+
submit_input = form.find("#active_admin_import_model_submit_action input")
|
205
|
+
expect(submit_input[:value]).to eq("Import")
|
206
|
+
expect(submit_input[:type]).to eq("submit")
|
207
|
+
end
|
208
|
+
|
209
|
+
context "with hint defined" do
|
210
|
+
let(:options) do
|
211
|
+
{ template_object: ActiveAdminImport::Model.new(hint: "hint") }
|
212
|
+
end
|
213
|
+
it "renders hint at upload page" do
|
214
|
+
expect(page).to have_content options[:template_object].hint
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
context "when importing file" do
|
219
|
+
|
220
|
+
[:empty, :only_headers].each do |file|
|
221
|
+
context "when #{file} file" do
|
222
|
+
it "should render warning" do
|
223
|
+
upload_file!(file)
|
224
|
+
expect(page).to have_content I18n.t('active_admin_import.file_empty_error')
|
225
|
+
expect(Author.count).to eq(0)
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
|
230
|
+
context "when no file" do
|
231
|
+
it "should render error" do
|
232
|
+
find_button('Import').click
|
233
|
+
expect(Author.count).to eq(0)
|
234
|
+
expect(page).to have_content I18n.t('active_admin_import.no_file_error')
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
context "auto detect encoding" do
|
239
|
+
include_examples 'successful inserts',
|
240
|
+
:auto,
|
241
|
+
:authors_win1251_win_endline
|
242
|
+
end
|
243
|
+
|
244
|
+
context "Win1251" do
|
245
|
+
include_examples 'successful inserts',
|
246
|
+
'windows-1251',
|
247
|
+
:authors_win1251_win_endline
|
248
|
+
end
|
249
|
+
|
250
|
+
context "BOM" do
|
251
|
+
it "should import file with many records" do
|
252
|
+
upload_file!(:authors_bom)
|
253
|
+
expect(page).to have_content "Successfully imported 2 authors"
|
254
|
+
expect(Author.count).to eq(2)
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
context "with headers" do
|
259
|
+
it "should import file with many records" do
|
260
|
+
upload_file!(:authors)
|
261
|
+
expect(page).to have_content "Successfully imported 2 authors"
|
262
|
+
expect(Author.count).to eq(2)
|
263
|
+
end
|
264
|
+
|
265
|
+
it "should import file with 1 record" do
|
266
|
+
upload_file!(:author)
|
267
|
+
expect(page).to have_content "Successfully imported 1 author"
|
268
|
+
expect(Author.count).to eq(1)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
context "without headers" do
|
273
|
+
context "with known csv headers" do
|
274
|
+
let(:options) do
|
275
|
+
attributes = { csv_headers: ['Name', 'Last name', 'Birthday'] }
|
276
|
+
{ template_object: ActiveAdminImport::Model.new(attributes) }
|
277
|
+
end
|
278
|
+
|
279
|
+
it "should import file" do
|
280
|
+
upload_file!(:authors_no_headers)
|
281
|
+
expect(page).to have_content "Successfully imported 2 authors"
|
282
|
+
expect(Author.count).to eq(2)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
context "with unknown csv headers" do
|
287
|
+
it "should render error" do
|
288
|
+
upload_file!(:authors_no_headers)
|
289
|
+
expect(page).to have_content "Error:"
|
290
|
+
expect(Author.count).to eq(0)
|
291
|
+
end
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
context "with invalid data insert on DB constraint" do
|
296
|
+
# :name field has an uniq index
|
297
|
+
it "should render error" do
|
298
|
+
upload_file!(:authors_invalid_db)
|
299
|
+
expect(page).to have_content "Error:"
|
300
|
+
expect(Author.count).to eq(0)
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
304
|
+
context "with invalid data insert on model validation" do
|
305
|
+
let(:options) { { validate: true } }
|
306
|
+
|
307
|
+
before do
|
308
|
+
Author.create!(name: "John", last_name: "Doe")
|
309
|
+
end
|
310
|
+
|
311
|
+
it "should render both successful and failed message" do
|
312
|
+
upload_file!(:authors_invalid_model)
|
313
|
+
expect(page).to have_content "Failed to import 1 author"
|
314
|
+
expect(page).to have_content "Successfully imported 1 author"
|
315
|
+
expect(Author.count).to eq(2)
|
316
|
+
end
|
317
|
+
|
318
|
+
context "use batch_transaction to make transaction work on model validation" do
|
319
|
+
let(:options) { { validate: true, batch_transaction: true } }
|
320
|
+
|
321
|
+
it "should render only the failed message" do
|
322
|
+
upload_file!(:authors_invalid_model)
|
323
|
+
expect(page).to have_content "Failed to import 1 author"
|
324
|
+
expect(page).to_not have_content "Successfully imported"
|
325
|
+
expect(Author.count).to eq(1)
|
326
|
+
end
|
327
|
+
end
|
328
|
+
end
|
329
|
+
|
330
|
+
context "with invalid records" do
|
331
|
+
context "with validation" do
|
332
|
+
it "should render error" do
|
333
|
+
upload_file!(:author_invalid)
|
334
|
+
expect(page).to have_content "Failed to import 1 author"
|
335
|
+
expect(Author.count).to eq(0)
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
context "without validation" do
|
340
|
+
let(:options) { { validate: false } }
|
341
|
+
it "should render error" do
|
342
|
+
upload_file!(:author_invalid)
|
343
|
+
expect(page).to have_content "Successfully imported 1 author"
|
344
|
+
expect(Author.count).to eq(1)
|
345
|
+
end
|
346
|
+
end
|
347
|
+
end
|
348
|
+
|
349
|
+
context "when zipped" do
|
350
|
+
context "when allowed" do
|
351
|
+
it "should import file" do
|
352
|
+
with_zipped_csv(:authors) do
|
353
|
+
upload_file!(:authors, :zip)
|
354
|
+
expect(page).to have_content "Successfully imported 2 authors"
|
355
|
+
expect(Author.count).to eq(2)
|
356
|
+
end
|
357
|
+
end
|
358
|
+
end
|
359
|
+
|
360
|
+
context "when not allowed" do
|
361
|
+
let(:options) do
|
362
|
+
attributes = { allow_archive: false }
|
363
|
+
{ template_object: ActiveAdminImport::Model.new(attributes) }
|
364
|
+
end
|
365
|
+
it "should render error" do
|
366
|
+
with_zipped_csv(:authors) do
|
367
|
+
upload_file!(:authors, :zip)
|
368
|
+
expect(page).to have_content I18n.t('active_admin_import.file_format_error')
|
369
|
+
expect(Author.count).to eq(0)
|
370
|
+
end
|
371
|
+
end
|
372
|
+
end
|
373
|
+
end
|
374
|
+
|
375
|
+
context "with different header attribute names" do
|
376
|
+
let(:options) do
|
377
|
+
{ headers_rewrites: { :'Second name' => :last_name } }
|
378
|
+
end
|
379
|
+
|
380
|
+
it "should import file" do
|
381
|
+
upload_file!(:author_broken_header)
|
382
|
+
expect(page).to have_content "Successfully imported 1 author"
|
383
|
+
expect(Author.count).to eq(1)
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
context "with semicolons separator" do
|
388
|
+
let(:options) do
|
389
|
+
attributes = { csv_options: { col_sep: ";" } }
|
390
|
+
{ template_object: ActiveAdminImport::Model.new(attributes) }
|
391
|
+
end
|
392
|
+
|
393
|
+
it "should import file" do
|
394
|
+
upload_file!(:authors_with_semicolons)
|
395
|
+
expect(page).to have_content "Successfully imported 2 authors"
|
396
|
+
expect(Author.count).to eq(2)
|
397
|
+
end
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
context "with callback procs options" do
|
402
|
+
let(:options) do
|
403
|
+
{
|
404
|
+
before_import: ->(_) { true },
|
405
|
+
after_import: ->(_) { true },
|
406
|
+
before_batch_import: ->(_) { true },
|
407
|
+
after_batch_import: ->(_) { true }
|
408
|
+
}
|
409
|
+
end
|
410
|
+
|
411
|
+
it "should call each callback" do
|
412
|
+
expect(options[:before_import]).to receive(:call).with(kind_of(ActiveAdminImport::Importer))
|
413
|
+
expect(options[:after_import]).to receive(:call).with(kind_of(ActiveAdminImport::Importer))
|
414
|
+
expect(options[:before_batch_import]).to receive(:call).with(kind_of(ActiveAdminImport::Importer))
|
415
|
+
expect(options[:after_batch_import]).to receive(:call).with(kind_of(ActiveAdminImport::Importer))
|
416
|
+
upload_file!(:authors)
|
417
|
+
expect(Author.count).to eq(2)
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
end
|
422
|
+
|
423
|
+
context "with invalid options" do
|
424
|
+
let(:options) { { invalid_option: :invalid_value } }
|
425
|
+
|
426
|
+
it "should raise TypeError" do
|
427
|
+
expect { add_author_resource(options) }.to raise_error(ArgumentError)
|
428
|
+
end
|
429
|
+
|
430
|
+
end
|
431
|
+
|
432
|
+
end
|
data/spec/model_spec.rb
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'coveralls'
|
2
|
+
Coveralls.wear!
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
5
|
+
$LOAD_PATH << File.expand_path('../support', __FILE__)
|
6
|
+
|
7
|
+
ENV['BUNDLE_GEMFILE'] = File.expand_path('../../Gemfile', __FILE__)
|
8
|
+
require "bundler"
|
9
|
+
Bundler.setup
|
10
|
+
|
11
|
+
ENV['RAILS'] = '4.1.9'
|
12
|
+
|
13
|
+
ENV['RAILS_ENV'] = 'test'
|
14
|
+
ENV['RAILS_ROOT'] = File.expand_path("../rails/rails-#{ENV['RAILS']}", __FILE__)
|
15
|
+
|
16
|
+
# Create the test app if it doesn't exists
|
17
|
+
unless File.exists?(ENV['RAILS_ROOT'])
|
18
|
+
system 'rake setup'
|
19
|
+
end
|
20
|
+
|
21
|
+
# Ensure the Active Admin load path is happy
|
22
|
+
require 'rails'
|
23
|
+
require 'active_model'
|
24
|
+
require 'active_admin'
|
25
|
+
ActiveAdmin.application.load_paths = [ENV['RAILS_ROOT'] + "/app/admin"]
|
26
|
+
|
27
|
+
require ENV['RAILS_ROOT'] + '/config/environment.rb'
|
28
|
+
|
29
|
+
# Disabling authentication in specs so that we don't have to worry about
|
30
|
+
# it allover the place
|
31
|
+
ActiveAdmin.application.authentication_method = false
|
32
|
+
ActiveAdmin.application.current_user_method = false
|
33
|
+
|
34
|
+
require 'rspec/rails'
|
35
|
+
require 'support/admin'
|
36
|
+
require 'capybara/rails'
|
37
|
+
require 'capybara/rspec'
|
38
|
+
require 'capybara/poltergeist'
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
Capybara.register_driver :poltergeist do |app|
|
44
|
+
Capybara::Poltergeist::Driver.new(app, {
|
45
|
+
js_errors: true,
|
46
|
+
timeout: 80,
|
47
|
+
debug: true,
|
48
|
+
:phantomjs_options => ['--debug=no', '--load-images=no']
|
49
|
+
|
50
|
+
})
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
Capybara.javascript_driver = :poltergeist
|
55
|
+
|
56
|
+
|
57
|
+
RSpec.configure do |config|
|
58
|
+
config.use_transactional_fixtures = false
|
59
|
+
|
60
|
+
config.before(:suite) do
|
61
|
+
DatabaseCleaner.strategy = :truncation
|
62
|
+
DatabaseCleaner.clean_with(:truncation)
|
63
|
+
end
|
64
|
+
config.before(:each) do
|
65
|
+
DatabaseCleaner.strategy = :truncation
|
66
|
+
DatabaseCleaner.start
|
67
|
+
end
|
68
|
+
config.after(:each) do
|
69
|
+
DatabaseCleaner.clean
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
shared_examples_for "ActiveModel" do
|
2
|
+
include ActiveModel::Lint::Tests
|
3
|
+
|
4
|
+
# to_s is to support ruby-1.9
|
5
|
+
ActiveModel::Lint::Tests.public_instance_methods.map{|m| m.to_s}.grep(/^test/).each do |m|
|
6
|
+
example m.gsub('_',' ') do
|
7
|
+
send m
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def model
|
12
|
+
subject
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
def add_author_resource(options = {}, &block)
|
2
|
+
|
3
|
+
ActiveAdmin.register Author do
|
4
|
+
config.filters = false
|
5
|
+
active_admin_import(options, &block)
|
6
|
+
end
|
7
|
+
Rails.application.reload_routes!
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
|
12
|
+
def add_post_resource(options = {}, &block)
|
13
|
+
|
14
|
+
ActiveAdmin.register Post do
|
15
|
+
config.filters = false
|
16
|
+
active_admin_import(options, &block)
|
17
|
+
end
|
18
|
+
Rails.application.reload_routes!
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Rails template to build the sample app for specs
|
2
|
+
|
3
|
+
generate :model, 'author name:string{10}:uniq last_name:string birthday:date'
|
4
|
+
generate :model, 'post title:string:uniq body:text author:references'
|
5
|
+
|
6
|
+
#Add validation
|
7
|
+
inject_into_file "app/models/author.rb", " validates_presence_of :name\n validates_uniqueness_of :last_name\n", after: "Base\n"
|
8
|
+
inject_into_file "app/models/post.rb", " validates_presence_of :author\n", after: ":author\n"
|
9
|
+
|
10
|
+
# Configure default_url_options in test environment
|
11
|
+
inject_into_file "config/environments/test.rb", " config.action_mailer.default_url_options = { :host => 'example.com' }\n", after: "config.cache_classes = true\n"
|
12
|
+
|
13
|
+
# Add our local Active Admin to the load path
|
14
|
+
inject_into_file "config/environment.rb", "\n$LOAD_PATH.unshift('#{File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'lib'))}')\nrequire \"active_admin\"\n", after: "require File.expand_path('../application', __FILE__)"
|
15
|
+
|
16
|
+
run "rm Gemfile"
|
17
|
+
|
18
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
19
|
+
|
20
|
+
generate :'active_admin:install --skip-users'
|
21
|
+
generate :'formtastic:install'
|
22
|
+
|
23
|
+
run "rm -r test"
|
24
|
+
run "rm -r spec"
|
25
|
+
|
26
|
+
# Setup a root path for devise
|
27
|
+
route "root :to => 'admin/dashboard#index'"
|
28
|
+
|
29
|
+
rake "db:migrate"
|
data/tasks/test.rake
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
desc "Creates a test rails app for the specs to run against"
|
2
|
+
task :setup do
|
3
|
+
require 'rails/version'
|
4
|
+
system("mkdir spec/rails") unless File.exists?("spec/rails")
|
5
|
+
system "bundle exec rails new spec/rails/rails-#{Rails::VERSION::STRING} -m spec/support/rails_template.rb --skip-spring"
|
6
|
+
end
|