spec_producer 0.8.0 → 0.9.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.
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