generator-spec 0.4.8 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. data/README.markdown +6 -0
  2. data/VERSION +1 -1
  3. data/generator-spec.gemspec +4 -2
  4. data/lib/generator_spec/extensions/core_ext.rb +30 -0
  5. data/lib/generator_spec/helpers/migration_helper.rb +15 -10
  6. data/lib/generator_spec/main.rb +5 -3
  7. data/lib/generator_spec/matchers/content/content_matcher.rb +8 -4
  8. data/lib/generator_spec/matchers/content/have_call.rb +4 -4
  9. data/lib/generator_spec/matchers/content/have_comment.rb +42 -0
  10. data/lib/generator_spec/matchers/file/generate_file.rb +2 -4
  11. data/lib/generator_spec/matchers/file/have_file.rb +2 -2
  12. data/lib/generator_spec/matchers/migration/have_up_down.rb +2 -0
  13. data/lib/generator_spec/rails_helpers/base_helper.rb +171 -0
  14. data/lib/generator_spec/rails_helpers/rails_app.rb +9 -2
  15. data/lib/generator_spec/rails_helpers/rails_controller.rb +33 -25
  16. data/lib/generator_spec/rails_helpers/rails_helper.rb +27 -25
  17. data/lib/generator_spec/rails_helpers/rails_mailer.rb +29 -21
  18. data/lib/generator_spec/rails_helpers/rails_migration.rb +41 -26
  19. data/lib/generator_spec/rails_helpers/rails_model.rb +29 -19
  20. data/lib/generator_spec/rails_helpers/rails_observer.rb +27 -23
  21. data/lib/generator_spec/rails_helpers/rails_orm.rb +33 -18
  22. data/lib/generator_spec/rails_helpers/rails_view.rb +42 -28
  23. data/spec/generator_spec/matchers/content/have_call_spec.rb +16 -0
  24. data/spec/generator_spec/matchers/rails/controller_matcher_spec.rb +3 -2
  25. data/spec/generator_spec/matchers/rails/helper_matcher_spec.rb +1 -1
  26. data/spec/generator_spec/matchers/rails/mailer_matcher_spec.rb +1 -1
  27. data/spec/generator_spec/matchers/rails/model_matcher_spec.rb +4 -4
  28. data/spec/generator_spec/matchers/rails/observer_matcher_spec.rb +1 -1
  29. data/spec/generator_spec/matchers/rails/view_matcher_spec.rb +1 -1
  30. data/spec/generator_spec/rails_helpers/rails_controller_spec.rb +33 -0
  31. data/spec/generator_spec/rails_helpers/rails_helper_spec.rb +33 -0
  32. data/spec/generator_spec/rails_helpers/rails_mailer_spec.rb +33 -0
  33. data/spec/generator_spec/rails_helpers/rails_model_spec.rb +31 -0
  34. data/spec/generator_spec/rails_helpers/rails_observer_spec.rb +33 -0
  35. data/spec/generator_spec/rails_helpers/rails_view_spec.rb +31 -0
  36. data/spec/spec_helper.rb +1 -1
  37. metadata +6 -4
data/README.markdown CHANGED
@@ -22,6 +22,12 @@ To install the gem from the code, simply use the jeweler rake task:
22
22
 
23
23
  <code>rake install</code>
24
24
 
25
+ ## TODO
26
+
27
+ Check out ways to improve the DSL, fx using Macros:
28
+
29
+ http://gist.github.com/511087
30
+
25
31
  ## Usage
26
32
 
27
33
  The following demonstrates usage of this library. There are many more options and DSL convenience methods (see wiki, code or specs).
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.8
1
+ 0.5.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{generator-spec}
8
- s.version = "0.4.8"
8
+ s.version = "0.5.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Kristian Mandrup"]
12
- s.date = %q{2010-08-11}
12
+ s.date = %q{2010-08-14}
13
13
  s.description = %q{RSpec 2 library to assist in writing generator specs}
14
14
  s.email = %q{kmandrup@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -36,6 +36,7 @@ Gem::Specification.new do |s|
36
36
  "lib/generator_spec/matchers/content/have_call.rb",
37
37
  "lib/generator_spec/matchers/content/have_calls.rb",
38
38
  "lib/generator_spec/matchers/content/have_class_self.rb",
39
+ "lib/generator_spec/matchers/content/have_comment.rb",
39
40
  "lib/generator_spec/matchers/content/have_method.rb",
40
41
  "lib/generator_spec/matchers/content/have_module.rb",
41
42
  "lib/generator_spec/matchers/content/have_region.rb",
@@ -54,6 +55,7 @@ Gem::Specification.new do |s|
54
55
  "lib/generator_spec/matchers/migration/have_table.rb",
55
56
  "lib/generator_spec/matchers/migration/have_tbl_column.rb",
56
57
  "lib/generator_spec/matchers/migration/have_up_down.rb",
58
+ "lib/generator_spec/rails_helpers/base_helper.rb",
57
59
  "lib/generator_spec/rails_helpers/rails_app.rb",
58
60
  "lib/generator_spec/rails_helpers/rails_controller.rb",
59
61
  "lib/generator_spec/rails_helpers/rails_helper.rb",
@@ -15,3 +15,33 @@ class String
15
15
  (self =~ /\w+\s+\w+/) ? self.split : self
16
16
  end
17
17
  end
18
+
19
+ class Module
20
+ def multi_alias name, options={}
21
+ config_options = options[:options]
22
+ options.each_pair do |original, aliases|
23
+ next if original == :options
24
+ alias_methods name, original, [aliases].flatten, config_options
25
+ end
26
+ end
27
+
28
+ protected
29
+
30
+ def alias_methods name, original, aliases, config_options
31
+ aliases.each do |alias_name|
32
+ new_alias = make_name(name, alias_name.to_s, config_options)
33
+ original_name = make_name(name, original.to_s, config_options)
34
+ alias_method new_alias, original_name if respond_to? original_name
35
+ end
36
+ end
37
+
38
+ def make_name name, alias_name, config_options
39
+ return alias_name.gsub(/X/, name.to_s) if alias_name =~ /X/
40
+ case config_options
41
+ when :after
42
+ "#{alias_name}_#{name}"
43
+ when :before
44
+ "#{name}_#{alias_name}"
45
+ end
46
+ end
47
+ end
@@ -17,7 +17,6 @@ module Rails::Generators
17
17
  migration_lookup_at(dirname).grep(/\d+_#{file_name}.rb$/).sort.last
18
18
  end
19
19
 
20
-
21
20
  def current_migration_number(dirname) #:nodoc:
22
21
  migration_lookup_at(dirname).collect do |file|
23
22
  File.basename(file).split("_").first.to_i
@@ -37,20 +36,26 @@ module Rails::Generators
37
36
  base.extend ClassMethods
38
37
  end
39
38
 
39
+ def reverse_migration_name name
40
+ name.gsub(/^add_/, 'remove_').gsub(/^create_/, 'drop_')
41
+ end
42
+
40
43
  def reverse_migration! migration_path
41
- reverse_migration_path = migration_path.gsub /^add_/, 'remove_'
42
- reverse_migration_path = migration_path.gsub /^create_/, 'drop_'
43
- FileUtils.mv(migration_path, reverse_migration_path) if migration_path != reverse_migration_path
44
+ reverse_class_names! migration_path
45
+ reverse_up_down_methods! migration_path
46
+ end
44
47
 
45
- file = File.new(reverse_migration_path)
48
+ def reverse_class_names! migration_path
46
49
  # Change class name
47
- gsub_file reverse_migration_path, /class Add/, 'class Remove'
48
- gsub_file reverse_migration_path, /class Create/, 'class Drop'
50
+ gsub_file migration_path, /class Add/, 'class Remove'
51
+ gsub_file migration_path, /class Create/, 'class Drop'
52
+ end
49
53
 
54
+ def reverse_up_down_methods! migration_path
50
55
  # swap up and down methods
51
- gsub_file reverse_migration_path, /up/, 'dwn'
52
- gsub_file reverse_migration_path, /down/, 'up'
53
- gsub_file reverse_migration_path, /dwn/, 'down'
56
+ gsub_file migration_path, /up/, 'dwn'
57
+ gsub_file migration_path, /down/, 'up'
58
+ gsub_file migration_path, /dwn/, 'down'
54
59
  end
55
60
 
56
61
  def latest_migration_file dir, name
@@ -25,8 +25,8 @@ module RSpec
25
25
  end
26
26
 
27
27
  require_all File.dirname(__FILE__) + '/extensions'
28
- require_all File.dirname(__FILE__) + '/rails_helpers'
29
28
  require_all File.dirname(__FILE__) + '/helpers'
29
+ require_all File.dirname(__FILE__) + '/rails_helpers'
30
30
  require_all File.dirname(__FILE__) + '/rspec_generator'
31
31
 
32
32
 
@@ -52,8 +52,10 @@ class Class
52
52
 
53
53
  def helpers *types
54
54
  types.each{|type| include_helper type}
55
- end
56
-
55
+ end
56
+ alias_method :load_helper, :helpers
57
+ alias_method :load_helpers, :helpers
58
+
57
59
  protected
58
60
 
59
61
  def include_helper type
@@ -15,10 +15,10 @@ module RSpec
15
15
  end
16
16
 
17
17
  def debug?
18
- false
18
+ RSpec::Generator.debug?
19
19
  end
20
20
 
21
- def matches? content, &block
21
+ def matches? content, &block
22
22
  @content = content
23
23
  match = is_match? content
24
24
  content_to_yield = if indexes
@@ -31,7 +31,7 @@ module RSpec
31
31
 
32
32
  def is_match? content
33
33
  expr = get_expr(content)
34
- puts "match expression: #{expr}" if debug?
34
+ debug "match expression: #{expr}"
35
35
  match = (content =~ expr)
36
36
  @content_matches = [$1, $2, $3]
37
37
  match
@@ -100,7 +100,11 @@ module RSpec
100
100
  end
101
101
 
102
102
  def debug_content
103
- puts "Content: #{content}" if RSpec::Generator.debug?
103
+ debug "Content: #{content}"
104
104
  end
105
+
106
+ def debug msg
107
+ puts msg if debug?
108
+ end
105
109
  end
106
110
  end
@@ -9,9 +9,9 @@ module RSpec::RubyContentMatchers
9
9
  class HaveCall < RSpec::RubyContentMatcher
10
10
  attr_reader :method, :args, :dot
11
11
 
12
- def initialize(method, args = nil, options = {})
12
+ def initialize(method, options = {})
13
13
  @method = method.to_s
14
- @args = args
14
+ @args = options[:args] || options
15
15
  @dot = options[:dot]
16
16
  end
17
17
 
@@ -49,8 +49,8 @@ module RSpec::RubyContentMatchers
49
49
 
50
50
  end
51
51
 
52
- def have_call(method, args = nil)
53
- HaveCall.new(method, args)
52
+ def have_call(method, options = {})
53
+ HaveCall.new(method, options)
54
54
  end
55
55
 
56
56
  def have_dot_call(method, options = {})
@@ -0,0 +1,42 @@
1
+ # This method tries to see if a specific method is contained in the generated file.
2
+ # It can operate (should) on either a file name or the raw content
3
+ #
4
+ # generated_file_name.should have_method "hello" # 'my/path/say_hello.rb'.should have_method "hello"
5
+ #
6
+ # say_hello_file_content.should have_method "hello"
7
+ #
8
+ module RSpec::RubyContentMatchers
9
+ class HaveComment < RSpec::RubyContentMatcher
10
+ attr_accessor :comment
11
+
12
+ def initialize comment
13
+ @comment = comment
14
+ end
15
+
16
+ def matches?(content)
17
+ @content = content
18
+ (content =~ /#{main_expr}/)
19
+ end
20
+
21
+ def failure_message
22
+ super
23
+ "Expected there to be the comment '# #{comment}'"
24
+ end
25
+
26
+ def negative_failure_message
27
+ super
28
+ "Did not expect there to be the comment '# #{comment}'"
29
+ end
30
+
31
+ protected
32
+
33
+ def main_expr
34
+ '\s*#\s*' + "#{comment}"
35
+ end
36
+ end
37
+
38
+ def have_comment comment
39
+ HaveComment.new comment
40
+ end
41
+
42
+ end
@@ -13,18 +13,16 @@ module RSpec::FileMatchers
13
13
  end
14
14
 
15
15
  def matches?(generator, &block)
16
- puts "relative_path"
17
16
  file = File.expand_path(relative_path, generator.class.destination_root)
18
17
  file_exists = File.exists?(file)
19
18
  if block && file_exists
20
19
  read = File.read(file)
21
- puts "file content: #{read}, #{file}"
22
20
  ruby_content = read.extend(RSpec::RubyContent::Helpers)
23
21
  yield ruby_content
24
22
  else
25
23
  file_exists
26
- end
27
- end
24
+ end
25
+ end
28
26
 
29
27
  def failure_message
30
28
  "Expected file #{relative_path} to have been generated, but it was not"
@@ -48,7 +48,7 @@ module RSpec::FileMatchers
48
48
 
49
49
 
50
50
  def postfix type
51
- "_#{type}" if [:helper, :controller, :observer].include?(type)
51
+ "_#{type}" if ![:model].include?(type)
52
52
  end
53
53
 
54
54
  def folder type
@@ -96,7 +96,7 @@ module RSpec::FileMatchers
96
96
  end
97
97
  alias_method :contain_helper, :have_helper
98
98
 
99
- def have_view(relative, action, ext='html.erb')
99
+ def have_view(relative, action='show', ext='html.erb')
100
100
  HaveFile.new("#{relative}/#{action}.#{ext}", :view)
101
101
  end
102
102
  alias_method :contain_view, :have_view
@@ -2,10 +2,12 @@ module RSpec::RubyContentMatchers
2
2
  def have_up &block
3
3
  HaveMethod.new 'up', :class, &block
4
4
  end
5
+ alias_method :have_up_method, :have_up
5
6
 
6
7
  def have_down &block
7
8
  HaveMethod.new 'down', :class, &block
8
9
  end
10
+ alias_method :have_down_method, :have_down
9
11
  end
10
12
 
11
13
 
@@ -0,0 +1,171 @@
1
+ module RSpec::Rails
2
+ module BaseHelper
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ base.class_eval do
6
+ include RSpec::Rails::App
7
+ include Thor::Actions
8
+ end
9
+ end
10
+
11
+ module ClassMethods
12
+ def aliases_for name
13
+ multi_alias name,
14
+ :create => :new, :insert_into => [:inject_into, :update], :read => :X_content, :remove => :delete,
15
+ :options => :after
16
+ end
17
+ end
18
+
19
+ def type_postfix type
20
+ "_#{type}" if ![:model].include?(type)
21
+ end
22
+
23
+ def artifact_path name, type, dir=nil
24
+ dir ||= send :"#{type}_dir"
25
+ File.join(dir, "#{name}#{type_postfix type}.rb")
26
+ end
27
+
28
+ # CREATE
29
+ def create_artifact name, options={}, &block
30
+ type = get_type options
31
+
32
+ file = file_name name, type
33
+ return if File.exist?(file)
34
+
35
+ debug "create #{type}: #{name}"
36
+ debug "file: #{file}"
37
+
38
+ # make dir
39
+ dir = File.dirname(file)
40
+ FileUtils.mkdir_p dir if !File.directory?(dir)
41
+
42
+ content = options[:content]
43
+ content ||= yield if block
44
+
45
+ content_method = :"new_#{type}_content"
46
+ debug "inner content: #{content}, to inject using ##{content_method}"
47
+
48
+ raise "Content method #{content_method} not found #{orm_notify}" if !respond_to?(content_method)
49
+ insert_content = send content_method, name, content
50
+
51
+ debug "content to insert: #{insert_content}"
52
+
53
+ return if insert_content.blank?
54
+
55
+ File.open(file, 'w') do |f|
56
+ f.puts insert_content
57
+ end
58
+ debug "file created and content inserted"
59
+ end
60
+
61
+ # READ
62
+ def read_artifact(name, options, &block)
63
+ type = get_type options
64
+ file_name = existing_file_name(name, type)
65
+ debug "reading from: #{file_name}"
66
+ content = File.new(file_name).try :read
67
+ debug "read content: #{content}"
68
+ yield content if block
69
+ content
70
+ end
71
+
72
+ # UPDATE
73
+ def insert_content(name, options={}, &block)
74
+ type = get_type options
75
+ file = existing_file_name(name, type)
76
+ file_insertion file, marker(name, type, options), options, &block
77
+ end
78
+
79
+ # DELETE
80
+ def remove_artifact name, type
81
+ debug "remove artifact: #{name}"
82
+ file = file_name name, type
83
+ debug "removed" if File.exist?(file) && FileUtils.rm_f(file)
84
+ end
85
+
86
+ def remove_artifacts type,*names
87
+ names.flatten.each{|name| send :"remove_#{type}", name }
88
+ end
89
+
90
+ def new_artifact_content name, type, content=nil, &block
91
+ content ||= yield if block
92
+ %Q{class #{marker(name, type)}
93
+ #{content}
94
+ end}
95
+ end
96
+
97
+ protected
98
+
99
+ def get_type options = {}
100
+ raise ArgumentError, "No artifact type specified" if !options[:type]
101
+ options[:type]
102
+ end
103
+
104
+ def debug?
105
+ RSpec::Generator.debug?
106
+ end
107
+
108
+ def debug msg
109
+ puts msg if debug?
110
+ end
111
+
112
+ def set options, type
113
+ options.merge!(:type => type)
114
+ options
115
+ end
116
+
117
+ def orm_notify
118
+ ''
119
+ end
120
+
121
+ def marker name, type, options={}
122
+ send :"#{type}_marker", name, options
123
+ end
124
+
125
+ def file_name name, type, options={}
126
+ send :"#{type}_file_name", name, options
127
+ end
128
+
129
+ def existing_file_name name, type
130
+ # first try finder method
131
+ finder_method = :"find_#{type}"
132
+ found = send finder_method, name if respond_to? finder_method
133
+ # default
134
+ file_name(name, type) if !found
135
+ end
136
+
137
+ def file_insertion(file_name, marker, options={}, &block)
138
+ debug "file insertion: marker = #{marker}"
139
+ return if !marker
140
+
141
+ file = File.new(file_name)
142
+ return if !File.exist?(file)
143
+
144
+ insert_content = options[:content] || (yield if block)
145
+
146
+ # already inserted?
147
+ return if insert_content.blank? || (file.read =~ /#{insert_content}/)
148
+
149
+ place = options[:before] ? :before : :after
150
+
151
+ debug "inserted #{place}: '#{marker}'"
152
+ debug "content: #{insert_content}"
153
+
154
+ mutate_file file.path, marker, place do
155
+ insert_content
156
+ end
157
+ end
158
+
159
+ def mutate_file file, marker, place, &block
160
+ raise ArgumentError, "You must define a replacement marker for a :before or :after key" if !marker
161
+ replace_in_file file, /(#{Regexp.escape(marker)})/mi do |match|
162
+ place == :after ? "#{match}#{yield}" : "#{yield}#{match}"
163
+ end
164
+ end
165
+
166
+ def replace_in_file(path, regexp, *args, &block)
167
+ content = File.read(path).gsub(regexp, *args, &block)
168
+ File.open(path, 'wb') { |file| file.write(content) }
169
+ end
170
+ end
171
+ end