spec_producer 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 67ec73a4f7348ffe92ebccbe9ed6e9136eacb71e
4
- data.tar.gz: c8dfd381a28742ffb40bfbcd67ec867e16b64ec2
3
+ metadata.gz: cbf3344329308865bd461e0d7b32bb9bb9ffc2c0
4
+ data.tar.gz: 3e31ede5c27b8ccd8699f5f9be4bad78a65eac2c
5
5
  SHA512:
6
- metadata.gz: 0bc5bf84efebb26ff6b62cd8df2946be78fec77f44d4cd37f9d186d929084f404e9647249fcbe92176174e0d3981b7d4b0c6873dd0cfb141416c3eec351ce009
7
- data.tar.gz: 125063256cb3d7c825b866a9111f1e237c7a25ffcf1711c5751872730873c09743e6604f6e0eb06169c452a0f067a5cc8660d7d5177f49b19494c1839f069838
6
+ metadata.gz: 3273677838cbed20613bac5ce81122145b7da955e3900b9eb4af832cc1e7e1b6d55bda632f6f05423763a37c79f08453c0253896b8560d0c9d96fc73544b201b
7
+ data.tar.gz: a38b7b70e7d472d7e05f0ccae9ea698db92f7c5ef3fc9594fe9b6c54f6eda1fa0f963fe48a1258ae144e3efbcafc9e40439f36622f515532576df9057cd6ec4f
data/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ ## 0.9.0 (2016-10-06)
2
+
3
+ * Ignore optional parameters when producing routing specs
4
+ * Read helper that might be used already in the existing specs
5
+ * Adds new set_up_necessities method that checks whether necessary gems exist in the gemfile and if not updates it.
6
+ * aDDS new method for producing factories for each model
7
+ * Adds more info in the view specs produced
8
+ * Print missing specs files for mailers and jobs
9
+ * Produce specs for mailers and jobs
10
+
11
+
1
12
  ## 0.8.0 (2016-08-30)
2
13
 
3
14
  Fixes:
@@ -0,0 +1,79 @@
1
+ module MissingFilesModule
2
+ def self.print_missing_model_specs
3
+ files_list = Dir["app/models/**/*.rb"]
4
+
5
+ puts "\n" << "## Searching for missing model specs..."
6
+ files_list.each do |file|
7
+ unless FileTest.exists?(file.gsub('app/', 'spec/').gsub('.rb', '_spec.rb'))
8
+ puts "Missing model spec file for: #{file}"
9
+ end
10
+ end
11
+
12
+ nil
13
+ end
14
+
15
+ def self.print_missing_controller_specs
16
+ files_list = Dir["app/controllers/**/*.rb"]
17
+
18
+ puts "\n" << "## Searching for missing controller specs..."
19
+ files_list.each do |file|
20
+ unless FileTest.exists?(file.gsub('app/', 'spec/').gsub('.rb', '_spec.rb'))
21
+ puts "Missing controller spec file for: #{file}"
22
+ end
23
+ end
24
+
25
+ nil
26
+ end
27
+
28
+ def self.print_missing_job_specs
29
+ files_list = Dir["app/jobs/**/*.rb"]
30
+
31
+ puts "\n" << "## Searching for missing jobs specs..."
32
+ files_list.each do |file|
33
+ unless FileTest.exists?(file.gsub('app/', 'spec/').gsub('.rb', '_spec.rb'))
34
+ puts "Missing job spec file for: #{file}"
35
+ end
36
+ end
37
+
38
+ nil
39
+ end
40
+
41
+ def self.print_missing_mailer_specs
42
+ files_list = Dir["app/mailers/**/*.rb"]
43
+
44
+ puts "\n" << "## Searching for missing mailers specs..."
45
+ files_list.each do |file|
46
+ unless FileTest.exists?(file.gsub('app/', 'spec/').gsub('.rb', '_spec.rb'))
47
+ puts "Missing mailer spec file for: #{file}"
48
+ end
49
+ end
50
+
51
+ nil
52
+ end
53
+
54
+ def self.print_missing_helper_specs
55
+ files_list = Dir["app/helpers/**/*.rb"]
56
+
57
+ puts "\n" << "## Searching for missing helper specs..."
58
+ files_list.each do |file|
59
+ unless FileTest.exists?(file.gsub('app/', 'spec/').gsub('.rb', '_spec.rb'))
60
+ puts "Missing helper spec file for: #{file}"
61
+ end
62
+ end
63
+
64
+ nil
65
+ end
66
+
67
+ def self.print_missing_view_specs
68
+ files_list = Dir["app/views/**/*.erb"]
69
+
70
+ puts "\n" << "## Searching for missing view specs..."
71
+ files_list.each do |file|
72
+ unless FileTest.exists?("#{file.gsub('app/', 'spec/')}_spec.rb")
73
+ puts "Missing spec file for: #{file}"
74
+ end
75
+ end
76
+
77
+ nil
78
+ end
79
+ end
@@ -0,0 +1,487 @@
1
+ module SpecProductionModule
2
+ def self.produce_specs_for_models
3
+ Dir.glob(Rails.root.join('app/models/*.rb')).each do |x|
4
+ require x
5
+ end
6
+
7
+ not_valid_descendants = [ ActiveRecord::SchemaMigration, Delayed::Backend::ActiveRecord::Job ]
8
+
9
+ ActiveRecord::Base.descendants.reject { |descendant| not_valid_descendants.include? descendant }.each do |descendant|
10
+ final_text = "require '#{require_helper_string}'\n\n"
11
+ final_text << "describe #{descendant.name}, :type => :model do\n"
12
+
13
+ descendant.attribute_names.each do |attribute|
14
+ final_text << " it { should respond_to :#{attribute}, :#{attribute}= }\n"
15
+ end
16
+
17
+ descendant.readonly_attributes.each do |attribute|
18
+ final_text << " it { should have_readonly_attribute :#{attribute} }\n"
19
+ end
20
+
21
+ if descendant.validators.reject { |validator| validator.kind == :associated }.present?
22
+ final_text << "\n # Validators\n"
23
+ end
24
+
25
+ descendant.validators.each do |validator|
26
+ if validator.kind == :presence
27
+ validator.attributes.each do |attribute|
28
+ final_text << " it { should validate_presence_of :#{attribute} }\n"
29
+ end
30
+ elsif validator.kind == :uniqueness
31
+ validator.attributes.each do |attribute|
32
+ final_text << " it { should validate_uniqueness_of :#{attribute} }\n"
33
+ end
34
+ elsif validator.kind == :numericality
35
+ validator.attributes.each do |attribute|
36
+ final_text << " it { should validate_numericality_of :#{attribute} }\n"
37
+ end
38
+ elsif validator.kind == :acceptance
39
+ validator.attributes.each do |attribute|
40
+ final_text << " it { should validate_acceptance_of :#{attribute} }\n"
41
+ end
42
+ elsif validator.kind == :confirmation
43
+ validator.attributes.each do |attribute|
44
+ final_text << " it { should validate_confirmation_of :#{attribute} }\n"
45
+ end
46
+ elsif validator.kind == :length
47
+ validator.attributes.each do |attribute|
48
+ final_text << " it { should validate_length_of :#{attribute} }\n"
49
+ end
50
+ elsif validator.kind == :absence
51
+ validator.attributes.each do |attribute|
52
+ final_text << " it { should validate_absence_of :#{attribute} }\n"
53
+ end
54
+ end
55
+ end
56
+
57
+ if descendant.column_names.present?
58
+ final_text << "\n # Columns\n"
59
+ end
60
+
61
+ descendant.column_names.each do |column_name|
62
+ final_text << " it { should have_db_column :#{column_name} }\n"
63
+ end
64
+
65
+ if descendant.reflections.keys.present?
66
+ final_text << "\n # Associations\n"
67
+ end
68
+
69
+ descendant.reflections.each_pair do |key, reflection|
70
+ final_text << case reflection.macro
71
+ when :belongs_to then " it { should belong_to(:#{key})#{produce_association_options(reflection)} }\n"
72
+ when :has_one then " it { should have_one(:#{key})#{produce_association_options(reflection)} }\n"
73
+ when :has_many then " it { should have_many(:#{key})#{produce_association_options(reflection)} }\n"
74
+ when :has_and_belongs_to_many then " it { should have_and_belong_to_many(:#{key})#{produce_association_options(reflection)} }\n"
75
+ end
76
+ end
77
+
78
+ final_text << "end"
79
+
80
+ if File.exists?(Rails.root.join("spec/models/#{descendant.name.underscore}_spec.rb"))
81
+ puts '#'*100
82
+ puts "Please, check whether the following lines are included in: " + descendant.name.underscore + "_spec.rb\n"
83
+ puts '#'*100
84
+ puts "\n"
85
+ puts final_text
86
+ else
87
+ check_if_spec_file_exists
88
+
89
+ unless Dir.exists? Rails.root.join("spec/models")
90
+ puts "Generating spec/models directory"
91
+ Dir.mkdir(Rails.root.join("spec/models"))
92
+ end
93
+
94
+ path = "spec/models/#{descendant.name.underscore}_spec.rb"
95
+ puts "Producing model spec file for: #{path}"
96
+ f = File.open("#{Rails.root.join(path)}", 'wb+')
97
+ f.write(final_text)
98
+ f.close
99
+ end
100
+ end
101
+
102
+ nil
103
+ rescue NameError
104
+ puts "ActiveRecord is not set for this project. Skipping model specs production."
105
+ rescue Exception => e
106
+ puts "Exception '#{e}' was raised. Skipping model specs production."
107
+ end
108
+
109
+ def self.produce_specs_for_routes
110
+ routes = Rails.application.routes.routes.map do |route|
111
+ path = route.path.spec.to_s.gsub(/\(\.:format\)/, "")
112
+ verb = %W{ GET POST PUT PATCH DELETE }.grep(route.verb).first.downcase.to_sym
113
+ controller = route.defaults[:controller]
114
+ action = route.defaults[:action]
115
+
116
+ if controller.present? && !/^rails/.match(controller)
117
+ { :path => path, :verb => verb, :controller => controller, :action => action }
118
+ end
119
+ end.compact
120
+
121
+ routes.group_by { |route| route[:controller] }.each do |route_group|
122
+ final_text = "require '#{require_helper_string}'\n\n"
123
+ final_text << "describe '#{route_group[0]} routes', :type => :routing do\n"
124
+
125
+ route_group[1].each_with_index do |route, index|
126
+ final_text << "\n" unless index == 0
127
+ final_text << " it \"#{route[:verb].upcase} #{route[:path].gsub(/\(.*?\)/, '')} should route to '#{route[:controller]}##{route[:action]}'\" do\n"
128
+
129
+ final_text << " expect(:#{route[:verb]} => '#{route[:path].gsub(/\(.*?\)/, '').gsub(/:[a-zA-Z_]+/){ |param| param.gsub(':','').upcase }}').\n"
130
+ final_text << " to route_to(:controller => '#{route[:controller]}',\n"
131
+ final_text << " :action => '#{route[:action]}'"
132
+
133
+ route[:path].gsub(/\(.*?\)/, '').scan(/:[a-zA-Z_]+/).flatten.each do |parameter|
134
+ final_text << ",\n #{parameter} => '#{parameter.gsub(':','').upcase}'"
135
+ end
136
+
137
+ final_text << ")\n end\n"
138
+ end
139
+
140
+ final_text << "end\n"
141
+
142
+ if File.exists?(Rails.root.join("spec/routing/#{route_group[0]}_routing_spec.rb"))
143
+ if File.open(Rails.root.join("spec/routing/#{route_group[0]}_routing_spec.rb")).read == final_text
144
+ # nothing to do here, pre-existing content is the same :)
145
+ else
146
+ puts '#'*100
147
+ puts "Please, check whether the following lines are included in: spec/routing/#{route_group[0]}_routing_spec.rb\n"
148
+ puts '#'*100
149
+ puts "\n"
150
+ puts final_text
151
+ end
152
+ else
153
+ check_if_spec_file_exists
154
+
155
+ unless Dir.exists? Rails.root.join("spec/routing")
156
+ puts "Generating spec/routing directory"
157
+ Dir.mkdir(Rails.root.join("spec/routing"))
158
+ end
159
+
160
+ # Check whether the route is not in top level namespace but deeper
161
+ full_path = 'spec/routing'
162
+ paths = route_group[0].split('/')
163
+
164
+ # And if it is deeper in the tree make sure to check if the related namespaces exist or create them
165
+ if paths.size > 1
166
+ paths.each do |path|
167
+ unless path == paths.last
168
+ full_path << "/#{path}"
169
+
170
+ unless Dir.exists? full_path
171
+ Dir.mkdir(Rails.root.join(full_path))
172
+ end
173
+ end
174
+ end
175
+ end
176
+
177
+ path = "spec/routing/#{route_group[0]}_routing_spec.rb"
178
+ puts "Producing routing spec file for: #{route_group[0]}"
179
+ f = File.open("#{Rails.root.join(path)}", 'wb+')
180
+ f.write(final_text)
181
+ f.close
182
+ end
183
+ end
184
+
185
+ nil
186
+ rescue Exception => e
187
+ puts "Exception '#{e}' was raised. Skipping route specs production."
188
+ end
189
+
190
+ def self.produce_specs_for_views
191
+ files_list = Dir["app/views/**/*.erb"]
192
+
193
+ files_list.each do |file|
194
+ full_path = 'spec'
195
+ File.dirname(file.gsub('app/', 'spec/')).split('/').reject { |path| path == 'spec' }.each do |path|
196
+ unless /.*\.erb/.match path
197
+ full_path << "/#{path}"
198
+
199
+ unless Dir.exists? full_path
200
+ Dir.mkdir(Rails.root.join(full_path))
201
+ end
202
+ end
203
+ end
204
+
205
+ file_content = File.read(file)
206
+ fields_in_file = file_content.scan(/(check_box_tag|text_field_tag|text_area_tag|select_tag|email_field_tag|color_field_tag|date_field_tag|datetime_field_tag|datetime_local_field_tag|hidden_field_tag|password_field_tag|phone_field_tag|radio_button_tag) \:(?<field>[a-zA-Z_]*)/).flatten.uniq
207
+ objects_in_file = file_content.scan(/@(?<field>[a-zA-Z_]*)/).flatten.uniq
208
+ templates_in_file = file_content.scan(/render ('|")(?<template>\S*)('|")/).flatten.uniq
209
+ partials_in_file = file_content.scan(/render :partial => ('|")(?<partial>\S*)('|")/).flatten.uniq
210
+
211
+ file_name = "#{file.gsub('app/', 'spec/')}_spec.rb"
212
+ final_text = "require '#{require_helper_string}'\n\n"
213
+ final_text << "describe '#{file.gsub('app/views/', '')}', :type => :view do\n"
214
+ final_text << " let(:page) { Capybara::Node::Simple.new(rendered) }\n\n"
215
+
216
+ objects_in_file.each do |object|
217
+ final_text << " let(:#{object}) { '#{object}' }\n"
218
+ end
219
+
220
+ final_text << " subject { page }\n\n"
221
+ final_text << " before do\n"
222
+
223
+ objects_in_file.each do |object|
224
+ final_text << " assign(:#{object}, #{object})\n"
225
+ end
226
+
227
+ final_text << " render\n"
228
+ final_text << " end\n\n"
229
+
230
+ if fields_in_file.size > 0 || templates_in_file.size > 0 || partials_in_file.size > 0
231
+ final_text << " describe 'content' do\n"
232
+
233
+ fields_in_file.each do |field_name|
234
+ final_text << " it { should have_field '#{field_name }' }\n"
235
+ end
236
+
237
+ templates_in_file.each do |template_name|
238
+ final_text << " it { should render_template '#{template_name }' }\n"
239
+ end
240
+
241
+ partials_in_file.each do |partial_name|
242
+ final_text << " it { should render_template(:partial => '#{partial_name }') }\n"
243
+ end
244
+
245
+ final_text << " pending 'view content test'\n"
246
+ final_text << " end\n"
247
+ else
248
+ final_text << " pending 'view content test'\n"
249
+ end
250
+
251
+ final_text << "end\n"
252
+
253
+ check_if_spec_file_exists
254
+
255
+ unless FileTest.exists?(file_name)
256
+ puts "Producing view spec file for: #{file_name}"
257
+ f = File.open(file_name, 'wb+')
258
+ f.write(final_text)
259
+ f.close
260
+ end
261
+ end
262
+
263
+ nil
264
+ rescue Exception => e
265
+ puts "Exception '#{e}' was raised. Skipping view specs production."
266
+ end
267
+
268
+ def self.produce_specs_for_helpers
269
+ files_list = Dir["app/helpers/**/*.rb"]
270
+
271
+ files_list.each do |file|
272
+ full_path = 'spec'
273
+ File.dirname(file.gsub('app/', 'spec/')).split('/').reject { |path| path == 'spec' }.each do |path|
274
+ unless /.*\.rb/.match path
275
+ full_path << "/#{path}"
276
+
277
+ unless Dir.exists? full_path
278
+ Dir.mkdir(Rails.root.join(full_path))
279
+ end
280
+ end
281
+ end
282
+
283
+ file_name = "#{file.gsub('app/', 'spec/').gsub('.rb', '')}_spec.rb"
284
+ final_text = "require '#{require_helper_string}'\n\n"
285
+ final_text << "describe #{file.gsub('app/helpers/', '').gsub('.rb', '').split('/').map { |x| x.camelcase }.join('::')}, :type => :helper do\n"
286
+ final_text << " pending 'view helper tests'\n"
287
+ final_text << "end"
288
+
289
+ check_if_spec_file_exists
290
+
291
+ unless FileTest.exists?(file_name)
292
+ puts "Producing helper spec file for: #{file_name}"
293
+ f = File.open(file_name, 'wb+')
294
+ f.write(final_text)
295
+ f.close
296
+ end
297
+ end
298
+
299
+ nil
300
+ rescue Exception => e
301
+ puts "Exception '#{e}' was raised. Skipping helper specs production."
302
+ end
303
+
304
+ def self.produce_specs_for_mailers
305
+ files_list = Dir["app/mailers/**/*.rb"]
306
+
307
+ files_list.each do |file|
308
+ full_path = 'spec'
309
+ File.dirname(file.gsub('app/', 'spec/')).split('/').reject { |path| path == 'spec' }.each do |path|
310
+ unless /.*\.rb/.match path
311
+ full_path << "/#{path}"
312
+
313
+ unless Dir.exists? full_path
314
+ Dir.mkdir(Rails.root.join(full_path))
315
+ end
316
+ end
317
+ end
318
+
319
+ file_name = "#{file.gsub('app/', 'spec/').gsub('.rb', '')}_spec.rb"
320
+ final_text = "require '#{require_helper_string}'\n\n"
321
+ final_text << "describe #{File.basename(file, ".rb").camelcase}, :type => :mailer do\n"
322
+ final_text << " pending 'mailer tests'\n"
323
+ final_text << "end"
324
+
325
+ check_if_spec_file_exists
326
+
327
+ unless FileTest.exists?(file_name)
328
+ puts "Producing helper spec file for: #{file_name}"
329
+ f = File.open(file_name, 'wb+')
330
+ f.write(final_text)
331
+ f.close
332
+ end
333
+ end
334
+
335
+ nil
336
+ rescue Exception => e
337
+ puts "Exception '#{e}' was raised. Skipping mailer specs production."
338
+ end
339
+
340
+ def self.produce_specs_for_jobs
341
+ files_list = Dir["app/jobs/**/*.rb"]
342
+
343
+ files_list.each do |file|
344
+ full_path = 'spec'
345
+ File.dirname(file.gsub('app/', 'spec/')).split('/').reject { |path| path == 'spec' }.each do |path|
346
+ unless /.*\.rb/.match path
347
+ full_path << "/#{path}"
348
+
349
+ unless Dir.exists? full_path
350
+ Dir.mkdir(Rails.root.join(full_path))
351
+ end
352
+ end
353
+ end
354
+
355
+ file_name = "#{file.gsub('app/', 'spec/').gsub('.rb', '')}_spec.rb"
356
+ final_text = "require '#{require_helper_string}'\n\n"
357
+ final_text << "describe #{File.basename(file, ".rb").camelcase}, :type => :job do\n"
358
+ final_text << " pending 'job tests'\n"
359
+ final_text << "end"
360
+
361
+ check_if_spec_file_exists
362
+
363
+ unless FileTest.exists?(file_name)
364
+ puts "Producing helper spec file for: #{file_name}"
365
+ f = File.open(file_name, 'wb+')
366
+ f.write(final_text)
367
+ f.close
368
+ end
369
+ end
370
+
371
+ nil
372
+ rescue Exception => e
373
+ puts "Exception '#{e}' was raised. Skipping job specs production."
374
+ end
375
+
376
+
377
+ def self.produce_specs_for_controllers
378
+ Dir.glob(Rails.root.join('app/controllers/**/*.rb')).each do |x|
379
+ require x
380
+ end
381
+
382
+ controllers = ApplicationController.descendants
383
+ controllers << ApplicationController
384
+
385
+ controllers.each do |descendant|
386
+ path_name = 'app/controllers/' + descendant.name.split('::').map { |name| name.underscore }.join('/')
387
+
388
+ full_path = 'spec'
389
+ File.dirname(path_name.gsub('app/', 'spec/')).split('/').reject { |path| path == 'spec' }.each do |path|
390
+ unless /.*\.rb/.match path
391
+ full_path << "/#{path}"
392
+
393
+ unless Dir.exists? full_path
394
+ Dir.mkdir(Rails.root.join(full_path))
395
+ end
396
+ end
397
+ end
398
+
399
+ file_name = "#{path_name.gsub('app/', 'spec/')}_spec.rb"
400
+ final_text = "require '#{require_helper_string}'\n\n"
401
+ final_text << "describe #{descendant.name}, :type => :controller do\n"
402
+
403
+ descendant.action_methods.each do |method|
404
+ final_text << " pending '##{method}'\n"
405
+ end
406
+
407
+ unless descendant.action_methods.size > 0
408
+ final_text << " pending 'tests'\n"
409
+ end
410
+
411
+ final_text << "end\n"
412
+
413
+ check_if_spec_file_exists
414
+
415
+ unless FileTest.exists?(file_name)
416
+ puts "Producing controller spec file for: #{file_name}"
417
+ f = File.open(file_name, 'wb+')
418
+ f.write(final_text)
419
+ f.close
420
+ end
421
+ end
422
+
423
+ nil
424
+ rescue Exception => e
425
+ puts "Exception '#{e}' was raised. Skipping controller specs production."
426
+ end
427
+
428
+ #######
429
+ private
430
+ #######
431
+
432
+ def self.produce_association_options(reflection)
433
+ return if reflection.options.empty?
434
+
435
+ final_text = []
436
+
437
+ reflection.options.each_pair do |key, value|
438
+ final_text << case key
439
+ when :inverse_of then "inverse_of(:#{value})"
440
+ when :autosave then "autosave(#{value})"
441
+ when :through then "through(:#{value})"
442
+ when :class_name then "class_name('#{value}')"
443
+ when :foreign_key then "with_foreign_key('#{value}')"
444
+ when :primary_key then "with_primary_key('#{value}')"
445
+ when :source then "source(:#{value})"
446
+ when :dependent then "dependent(:#{value})"
447
+ end
448
+ end
449
+ final_text.reject(&:nil?).join('.').prepend('.')
450
+ end
451
+
452
+ def self.require_helper_string
453
+ @require_helper_string ||= collect_helper_strings
454
+ end
455
+
456
+ def self.collect_helper_strings
457
+ spec_files = Dir.glob(Rails.root.join('spec/**/*_spec.rb'))
458
+ helper_strings_used = []
459
+
460
+ spec_files.each do |file|
461
+ helper = /require \'(?<helpers>\S*)\'/.match File.read(file)
462
+
463
+ helper_strings_used << helper[1] if helper.present?
464
+ end
465
+
466
+ helper_strings_used.compact!
467
+
468
+ if helper_strings_used.uniq.length == 1
469
+ helper_strings_used.first
470
+ else
471
+ puts "More than one helpers are in place in your specs! Proceeding with 'rails_helpers'."
472
+ 'rails_helper'
473
+ end
474
+ end
475
+
476
+ def self.check_if_spec_file_exists
477
+ unless Dir.exists? Rails.root.join("spec")
478
+ puts "Generating spec directory"
479
+ Dir.mkdir(Rails.root.join("spec"))
480
+ end
481
+ end
482
+
483
+ private_class_method :produce_association_options
484
+ private_class_method :require_helper_string
485
+ private_class_method :collect_helper_strings
486
+ private_class_method :check_if_spec_file_exists
487
+ end
@@ -1,3 +1,3 @@
1
1
  module SpecProducer
2
- VERSION = "0.8.0"
2
+ VERSION = "0.9.0"
3
3
  end
data/lib/spec_producer.rb CHANGED
@@ -1,20 +1,86 @@
1
1
  require "spec_producer/version"
2
+ require "spec_producer/missing_files_module"
3
+ require "spec_producer/spec_production_module"
2
4
 
3
5
  module SpecProducer
4
6
  def self.produce_specs_for_all_types
5
- produce_specs_for_models
6
- produce_specs_for_routes
7
- produce_specs_for_views
8
- produce_specs_for_controllers
9
- produce_specs_for_helpers
7
+ set_up_necessities
8
+ SpecProductionModule.produce_specs_for_models
9
+ SpecProductionModule.produce_specs_for_routes
10
+ SpecProductionModule.produce_specs_for_views
11
+ SpecProductionModule.produce_specs_for_controllers
12
+ SpecProductionModule.produce_specs_for_helpers
13
+ SpecProductionModule.produce_specs_for_mailers
14
+ SpecProductionModule.produce_specs_for_jobs
15
+ end
16
+
17
+ def self.produce_specs_for_models
18
+ SpecProductionModule.produce_specs_for_models
19
+ end
20
+
21
+ def self.produce_specs_for_routes
22
+ SpecProductionModule.produce_specs_for_routes
23
+ end
24
+
25
+ def self.produce_specs_for_views
26
+ SpecProductionModule.produce_specs_for_views
27
+ end
28
+
29
+ def self.produce_specs_for_controllers
30
+ SpecProductionModule.produce_specs_for_controllers
31
+ end
32
+
33
+ def self.produce_specs_for_helpers
34
+ SpecProductionModule.produce_specs_for_helpers
35
+ end
36
+
37
+ def self.produce_specs_for_mailers
38
+ SpecProductionModule.produce_specs_for_mailers
39
+ end
40
+
41
+ def self.produce_specs_for_jobs
42
+ SpecProductionModule.produce_specs_for_jobs
43
+ end
44
+
45
+ def self.set_up_necessities
46
+ gemfiles = Dir.glob(Rails.root.join('Gemfile'))
47
+
48
+ if gemfiles.size > 0
49
+ contents = File.read(gemfiles.first)
50
+ gems = contents.scan(/gem \'(?<gem>\S*)\'/).flatten.uniq
51
+ missing_gems = []
52
+
53
+ missing_gems << 'rspec-rails' unless (gems.include? 'rspec-rails')
54
+ missing_gems << 'factory_girl_rails' unless (gems.include? 'factory_girl_rails')
55
+ missing_gems << 'shoulda-matchers' unless (gems.include? 'shoulda-matchers')
56
+ missing_gems << 'capybara' unless (gems.include? 'capybara')
57
+
58
+ if missing_gems.size > 0
59
+ contents << "\ngroup :test do\n"
60
+
61
+ missing_gems.each do |gem|
62
+ contents << " gem '#{gem}'\n"
63
+ end
64
+
65
+ contents << "end"
66
+ end
67
+
68
+ f = File.open(gemfiles.first, 'wb+')
69
+ f.write(contents)
70
+ f.close
71
+ else
72
+ puts "We couldn't find a Gemfile and setting up halted!"
73
+ end
10
74
  end
11
75
 
12
76
  def self.produce_factories
13
77
  Dir.glob(Rails.root.join('app/models/*.rb')).each do |x|
14
78
  require x
15
79
  end
80
+
81
+ not_valid_descendants = [ ActiveRecord::SchemaMigration, Delayed::Backend::ActiveRecord::Job ]
16
82
 
17
- ActiveRecord::Base.descendants.each do |descendant|
83
+ ActiveRecord::Base.descendants.reject { |descendant| not_valid_descendants.include? descendant }.each do |descendant|
18
84
  final_text = "FactoryGirl.define do\n"
19
85
  final_text << " factory :#{descendant.name.underscore}, :class => #{descendant.name} do\n"
20
86
 
@@ -66,400 +132,40 @@ module SpecProducer
66
132
  nil
67
133
  rescue NameError
68
134
  puts "ActiveRecord is not set for this project. Can't produce factories for this project."
69
- end
70
-
71
- def self.produce_specs_for_models
72
- Dir.glob(Rails.root.join('app/models/*.rb')).each do |x|
73
- require x
74
- end
75
-
76
- ActiveRecord::Base.descendants.each do |descendant|
77
- final_text = "require 'rails_helper'\n\n"
78
- final_text << "describe #{descendant.name}, :type => :model do\n"
79
-
80
- descendant.attribute_names.each do |attribute|
81
- final_text << " it { should respond_to :#{attribute}, :#{attribute}= }\n"
82
- end
83
-
84
- descendant.readonly_attributes.each do |attribute|
85
- final_text << " it { should have_readonly_attribute :#{attribute} }\n"
86
- end
87
-
88
- if descendant.validators.reject { |validator| validator.kind == :associated }.present?
89
- final_text << "\n # Validators\n"
90
- end
91
-
92
- descendant.validators.each do |validator|
93
- if validator.kind == :presence
94
- validator.attributes.each do |attribute|
95
- final_text << " it { should validate_presence_of :#{attribute} }\n"
96
- end
97
- elsif validator.kind == :uniqueness
98
- validator.attributes.each do |attribute|
99
- final_text << " it { should validate_uniqueness_of :#{attribute} }\n"
100
- end
101
- elsif validator.kind == :numericality
102
- validator.attributes.each do |attribute|
103
- final_text << " it { should validate_numericality_of :#{attribute} }\n"
104
- end
105
- elsif validator.kind == :acceptance
106
- validator.attributes.each do |attribute|
107
- final_text << " it { should validate_acceptance_of :#{attribute} }\n"
108
- end
109
- elsif validator.kind == :confirmation
110
- validator.attributes.each do |attribute|
111
- final_text << " it { should validate_confirmation_of :#{attribute} }\n"
112
- end
113
- elsif validator.kind == :length
114
- validator.attributes.each do |attribute|
115
- final_text << " it { should validate_length_of :#{attribute} }\n"
116
- end
117
- elsif validator.kind == :absence
118
- validator.attributes.each do |attribute|
119
- final_text << " it { should validate_absence_of :#{attribute} }\n"
120
- end
121
- end
122
- end
123
-
124
- if descendant.column_names.present?
125
- final_text << "\n # Columns\n"
126
- end
127
-
128
- descendant.column_names.each do |column_name|
129
- final_text << " it { should have_db_column :#{column_name} }\n"
130
- end
131
-
132
- if descendant.reflections.keys.present?
133
- final_text << "\n # Associations\n"
134
- end
135
-
136
- descendant.reflections.each_pair do |key, reflection|
137
- final_text << case reflection.macro
138
- when :belongs_to then " it { should belong_to(:#{key})#{produce_association_options(reflection)} }\n"
139
- when :has_one then " it { should have_one(:#{key})#{produce_association_options(reflection)} }\n"
140
- when :has_many then " it { should have_many(:#{key})#{produce_association_options(reflection)} }\n"
141
- when :has_and_belongs_to_many then " it { should have_and_belong_to_many(:#{key})#{produce_association_options(reflection)} }\n"
142
- end
143
- end
144
-
145
- final_text << "end"
146
-
147
- if File.exists?(Rails.root.join("spec/models/#{descendant.name.underscore}_spec.rb"))
148
- puts '#'*100
149
- puts "Please, check whether the following lines are included in: " + descendant.name.underscore + "_spec.rb\n"
150
- puts '#'*100
151
- puts "\n"
152
- puts final_text
153
- else
154
- unless Dir.exists? Rails.root.join("spec")
155
- puts "Generating spec directory"
156
- Dir.mkdir(Rails.root.join("spec"))
157
- end
158
-
159
- unless Dir.exists? Rails.root.join("spec/models")
160
- puts "Generating spec/models directory"
161
- Dir.mkdir(Rails.root.join("spec/models"))
162
- end
163
-
164
- path = "spec/models/#{descendant.name.underscore}_spec.rb"
165
- puts "Producing model spec file for: #{path}"
166
- f = File.open("#{Rails.root.join(path)}", 'wb+')
167
- f.write(final_text)
168
- f.close
169
- end
170
- end
171
-
172
- nil
173
- rescue NameError
174
- puts "ActiveRecord is not set for this project. Skipping model specs production."
175
- end
176
-
177
- def self.produce_specs_for_routes
178
- routes = Rails.application.routes.routes.map do |route|
179
- path = route.path.spec.to_s.gsub(/\(\.:format\)/, "")
180
- verb = %W{ GET POST PUT PATCH DELETE }.grep(route.verb).first.downcase.to_sym
181
- controller = route.defaults[:controller]
182
- action = route.defaults[:action]
183
-
184
- if controller.present? && !/^rails/.match(controller)
185
- { :path => path, :verb => verb, :controller => controller, :action => action }
186
- end
187
- end.compact
188
-
189
- routes.group_by { |route| route[:controller] }.each do |route_group|
190
- final_text = "require 'rails_helper'\n\n"
191
- final_text << "describe '#{route_group[0]} routes', :type => :routing do\n"
192
-
193
- route_group[1].each do |route|
194
- final_text << " it \"#{route[:verb].upcase} #{route[:path]} should route to '#{route[:controller]}##{route[:action]}'\" do\n"
195
-
196
- final_text << " expect(:#{route[:verb]} => '#{route[:path].gsub(/:[a-zA-Z_]+/){ |param| param.gsub(':','').upcase }}').\n"
197
- final_text << " to route_to(:controller => '#{route[:controller]}',\n"
198
- final_text << " :action => '#{route[:action]}'"
199
-
200
- route[:path].scan(/:[a-zA-Z_]+/).flatten.each do |parameter|
201
- final_text << ",\n #{parameter} => '#{parameter.gsub(':','').upcase}'"
202
- end
203
-
204
- final_text << ")\n end\n\n"
205
- end
206
-
207
- final_text << 'end'
208
-
209
- if File.exists?(Rails.root.join("spec/routing/#{route_group[0]}_routing_spec.rb"))
210
- puts '#'*100
211
- puts "Please, check whether the following lines are included in: spec/routing/#{route_group[0]}_routing_spec.rb\n"
212
- puts '#'*100
213
- puts "\n"
214
- puts final_text
215
- else
216
- unless Dir.exists? Rails.root.join("spec")
217
- puts "Generating spec directory"
218
- Dir.mkdir(Rails.root.join("spec"))
219
- end
220
-
221
- unless Dir.exists? Rails.root.join("spec/routing")
222
- puts "Generating spec/routing directory"
223
- Dir.mkdir(Rails.root.join("spec/routing"))
224
- end
225
-
226
- # Check whether the route is not in top level namespace but deeper
227
- full_path = 'spec/routing'
228
- paths = route_group[0].split('/')
229
-
230
- # And if it is deeper in the tree make sure to check if the related namespaces exist or create them
231
- if paths.size > 1
232
- paths.each do |path|
233
- unless path == paths.last
234
- full_path << "/#{path}"
235
-
236
- unless Dir.exists? full_path
237
- Dir.mkdir(Rails.root.join(full_path))
238
- end
239
- end
240
- end
241
- end
242
-
243
- path = "spec/routing/#{route_group[0]}_routing_spec.rb"
244
- puts "Producing routing spec file for: #{route_group[0]}"
245
- f = File.open("#{Rails.root.join(path)}", 'wb+')
246
- f.write(final_text)
247
- f.close
248
- end
249
- end
250
-
251
- nil
252
- end
253
-
254
- def self.produce_specs_for_views
255
- files_list = Dir["app/views/**/*.erb"]
256
-
257
- files_list.each do |file|
258
- full_path = 'spec'
259
- File.dirname(file.gsub('app/', 'spec/')).split('/').reject { |path| path == 'spec' }.each do |path|
260
- unless /.*\.erb/.match path
261
- full_path << "/#{path}"
262
-
263
- unless Dir.exists? full_path
264
- Dir.mkdir(Rails.root.join(full_path))
265
- end
266
- end
267
- end
268
-
269
- file_name = "#{file.gsub('app/', 'spec/')}_spec.rb"
270
- final_text = "require 'rails_helper'\n\n"
271
- final_text << "describe '#{file.gsub('app/views/', '')}', :type => :view do\n"
272
- final_text << " before do\n"
273
- final_text << " render\n"
274
- final_text << " end\n\n"
275
- final_text << " pending 'view content test'\n"
276
- final_text << "end\n"
277
-
278
- unless Dir.exists? Rails.root.join("spec")
279
- puts "Generating spec directory"
280
- Dir.mkdir(Rails.root.join("spec"))
281
- end
282
-
283
- unless FileTest.exists?(file_name)
284
- puts "Producing view spec file for: #{file_name}"
285
- f = File.open(file_name, 'wb+')
286
- f.write(final_text)
287
- f.close
288
- end
289
- end
290
-
291
- nil
292
- end
293
-
294
- def self.produce_specs_for_helpers
295
- files_list = Dir["app/helpers/**/*.rb"]
296
-
297
- files_list.each do |file|
298
- full_path = 'spec'
299
- File.dirname(file.gsub('app/', 'spec/')).split('/').reject { |path| path == 'spec' }.each do |path|
300
- unless /.*\.rb/.match path
301
- full_path << "/#{path}"
302
-
303
- unless Dir.exists? full_path
304
- Dir.mkdir(Rails.root.join(full_path))
305
- end
306
- end
307
- end
308
-
309
- file_name = "#{file.gsub('app/', 'spec/').gsub('.rb', '')}_spec.rb"
310
- final_text = "require 'rails_helper'\n\n"
311
- final_text << "describe #{File.basename(file, ".rb").camelcase}, :type => :helper do\n"
312
- final_text << " pending 'view helper tests'\n"
313
- final_text << "end"
314
-
315
- unless Dir.exists? Rails.root.join("spec")
316
- puts "Generating spec directory"
317
- Dir.mkdir(Rails.root.join("spec"))
318
- end
319
-
320
- unless FileTest.exists?(file_name)
321
- puts "Producing helper spec file for: #{file_name}"
322
- f = File.open(file_name, 'wb+')
323
- f.write(final_text)
324
- f.close
325
- end
326
- end
327
-
328
- nil
329
- end
330
-
331
- def self.produce_specs_for_controllers
332
- Dir.glob(Rails.root.join('app/controllers/**/*.rb')).each do |x|
333
- require x
334
- end
335
-
336
- controllers = ApplicationController.descendants
337
- controllers << ApplicationController
338
-
339
- controllers.each do |descendant|
340
- path_name = 'app/controllers/' + descendant.name.split('::').map { |name| name.underscore }.join('/')
341
-
342
- full_path = 'spec'
343
- File.dirname(path_name.gsub('app/', 'spec/')).split('/').reject { |path| path == 'spec' }.each do |path|
344
- unless /.*\.rb/.match path
345
- full_path << "/#{path}"
346
-
347
- unless Dir.exists? full_path
348
- Dir.mkdir(Rails.root.join(full_path))
349
- end
350
- end
351
- end
352
-
353
- file_name = "#{path_name.gsub('app/', 'spec/')}_spec.rb"
354
- final_text = "require 'rails_helper'\n\n"
355
- final_text << "describe #{descendant.name}, :type => :controller do\n"
356
-
357
- descendant.action_methods.each do |method|
358
- final_text << " pending '##{method}'\n"
359
- end
360
-
361
- unless descendant.action_methods.size > 0
362
- final_text << " pending 'tests'\n"
363
- end
364
-
365
- final_text << "end\n"
366
-
367
- unless Dir.exists? Rails.root.join("spec")
368
- puts "Generating spec directory"
369
- Dir.mkdir(Rails.root.join("spec"))
370
- end
371
-
372
- unless FileTest.exists?(file_name)
373
- puts "Producing controller spec file for: #{file_name}"
374
- f = File.open(file_name, 'wb+')
375
- f.write(final_text)
376
- f.close
377
- end
378
- end
379
-
380
- nil
135
+ rescue Exception => e
136
+ puts "Exception '#{e}' was raised. Skipping factories production."
381
137
  end
382
138
 
383
139
  def self.print_all_missing_spec_files
384
- print_missing_model_specs
385
- print_missing_controller_specs
386
- print_missing_helper_specs
387
- print_missing_view_specs
140
+ MissingFiles.print_missing_model_specs
141
+ MissingFiles.print_missing_controller_specs
142
+ MissingFiles.print_missing_helper_specs
143
+ MissingFiles.print_missing_view_specs
144
+ MissingFiles.print_missing_mailer_specs
145
+ MissingFiles.print_missing_job_specs
388
146
  end
389
147
 
390
148
  def self.print_missing_model_specs
391
- files_list = Dir["app/models/**/*.rb"]
392
-
393
- puts "\n" << "## Searching for missing model specs..."
394
- files_list.each do |file|
395
- unless FileTest.exists?(file.gsub('app/', 'spec/').gsub('.rb', '_spec.rb'))
396
- puts "Missing model spec file for: #{file}"
397
- end
398
- end
399
-
400
- nil
149
+ MissingFiles.print_missing_model_specs
401
150
  end
402
151
 
403
152
  def self.print_missing_controller_specs
404
- files_list = Dir["app/controllers/**/*.rb"]
405
-
406
- puts "\n" << "## Searching for missing controller specs..."
407
- files_list.each do |file|
408
- unless FileTest.exists?(file.gsub('app/', 'spec/').gsub('.rb', '_spec.rb'))
409
- puts "Missing controller spec file for: #{file}"
410
- end
411
- end
412
-
413
- nil
153
+ MissingFiles.print_missing_controller_specs
414
154
  end
415
155
 
416
156
  def self.print_missing_helper_specs
417
- files_list = Dir["app/helpers/**/*.rb"]
418
-
419
- puts "\n" << "## Searching for missing helper specs..."
420
- files_list.each do |file|
421
- unless FileTest.exists?(file.gsub('app/', 'spec/').gsub('.rb', '_spec.rb'))
422
- puts "Missing helper spec file for: #{file}"
423
- end
424
- end
425
-
426
- nil
157
+ MissingFiles.print_missing_helper_specs
427
158
  end
428
159
 
429
160
  def self.print_missing_view_specs
430
- files_list = Dir["app/views/**/*.erb"]
431
-
432
- puts "\n" << "## Searching for missing view specs..."
433
- files_list.each do |file|
434
- unless FileTest.exists?("#{file.gsub('app/', 'spec/')}_spec.rb")
435
- puts "Missing spec file for: #{file}"
436
- end
437
- end
438
-
439
- nil
161
+ MissingFiles.print_missing_view_specs
440
162
  end
441
163
 
442
- #######
443
- private
444
- #######
445
-
446
- def self.produce_association_options(reflection)
447
- return if reflection.options.empty?
448
-
449
- final_text = []
164
+ def self.print_missing_mailer_specs
165
+ MissingFiles.print_missing_mailer_specs
166
+ end
450
167
 
451
- reflection.options.each_pair do |key, value|
452
- final_text << case key
453
- when :inverse_of then "inverse_of(:#{value})"
454
- when :autosave then "autosave(#{value})"
455
- when :through then "through(:#{value})"
456
- when :class_name then "class_name('#{value}')"
457
- when :foreign_key then "with_foreign_key('#{value}')"
458
- when :primary_key then "with_primary_key('#{value}')"
459
- when :source then "source(:#{value})"
460
- when :dependent then "dependent(:#{value})"
461
- end
462
- end
463
- final_text.reject(&:nil?).join('.').prepend('.')
168
+ def self.print_missing_job_specs
169
+ MissingFiles.print_missing_job_specs
464
170
  end
465
- end
171
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spec_producer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vasilis Kalligas
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-08-29 00:00:00.000000000 Z
11
+ date: 2016-10-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -72,6 +72,8 @@ files:
72
72
  - bin/console
73
73
  - bin/setup
74
74
  - lib/spec_producer.rb
75
+ - lib/spec_producer/missing_files_module.rb
76
+ - lib/spec_producer/spec_production_module.rb
75
77
  - lib/spec_producer/version.rb
76
78
  - spec_producer.gemspec
77
79
  homepage: https://rubygems.org/gems/spec_producer