generator-spec 0.4.8 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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