cukedep 0.1.10 → 0.1.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +8 -8
  2. data/CHANGELOG.md +4 -0
  3. data/Rakefile +4 -6
  4. data/lib/cukedep/application.rb +89 -91
  5. data/lib/cukedep/cli/cmd-line.rb +0 -7
  6. data/lib/cukedep/config.rb +70 -74
  7. data/lib/cukedep/constants.rb +1 -1
  8. data/lib/cukedep/cuke-runner.rb +0 -5
  9. data/lib/cukedep/customization.rb +0 -5
  10. data/lib/cukedep/feature-model.rb +1 -7
  11. data/lib/cukedep/feature-rep.rb +0 -4
  12. data/lib/cukedep/file-action.rb +209 -221
  13. data/lib/cukedep/gherkin-facade.rb +7 -10
  14. data/lib/cukedep/gherkin-listener.rb +82 -89
  15. data/lib/cukedep/hook-dsl.rb +0 -4
  16. data/lib/cukedep/sandbox.rb +0 -5
  17. data/sample/features/step_definitions/steps.rb +30 -26
  18. data/sample/features/support/env.rb +1 -1
  19. data/sample/model/model.rb +198 -205
  20. data/sample/result.html +1 -1
  21. data/spec/cukedep/application_spec.rb +15 -16
  22. data/spec/cukedep/cli/cmd-line_spec.rb +13 -16
  23. data/spec/cukedep/cuke-runner_spec.rb +55 -61
  24. data/spec/cukedep/customization_spec.rb +21 -26
  25. data/spec/cukedep/debug-file-action.rb +12 -10
  26. data/spec/cukedep/feature-model_spec.rb +13 -16
  27. data/spec/cukedep/feature-rep_spec.rb +4 -7
  28. data/spec/cukedep/file-action_spec.rb +18 -34
  29. data/spec/cukedep/file-parsing.rb +9 -11
  30. data/spec/cukedep/gherkin-facade_spec.rb +3 -8
  31. data/spec/cukedep/gherkin-listener_spec.rb +10 -12
  32. data/spec/cukedep/hook-dsl_spec.rb +6 -9
  33. data/spec/cukedep/sample_features/cukedep.rake +44 -37
  34. data/spec/cukedep/sample_features/cukedep_hooks.rb +2 -2
  35. data/spec/cukedep/sample_features/dependencies.dot +1 -1
  36. data/templates/rake.erb +36 -29
  37. metadata +2 -2
@@ -32,7 +32,6 @@ end
32
32
 
33
33
 
34
34
  module Cukedep # This module is used as a namespace
35
-
36
35
  # Purpose: to launch Cucumber in the appropriate directory
37
36
  # and pass it command-line arguments.
38
37
  # Responsibilities:
@@ -194,10 +193,6 @@ class CukeRunner
194
193
  safe_args = args.map { |one_arg| one_arg.dup.freeze }
195
194
  kode.call(*safe_args)
196
195
  end
197
-
198
-
199
196
  end # class
200
-
201
197
  end # module
202
-
203
198
  # End of file
@@ -4,10 +4,7 @@ require_relative 'constants'
4
4
  require_relative 'hook-dsl'
5
5
 
6
6
  module Cukedep # This module is used as a namespace
7
-
8
-
9
7
  class Customization
10
-
11
8
  # Retrieve before/after handlers from file
12
9
  # Handlers are put in a Hash with keys :before_hooks, :after_hooks.
13
10
  def build_handlers(directory)
@@ -27,9 +24,7 @@ module Cukedep # This module is used as a namespace
27
24
 
28
25
  return handlers
29
26
  end
30
-
31
27
  end # class
32
-
33
28
  end # module
34
29
 
35
30
  # End of file
@@ -6,14 +6,11 @@ require 'erb'
6
6
  require 'pathname'
7
7
 
8
8
  module Cukedep # This module is used as a namespace
9
-
10
-
11
9
  # The internal representation of a set of feature files.
12
10
  # Dependencies: use topological sort
13
11
  # TSort module http://ruby-doc.org/stdlib-1.9.3/libdoc/tsort/rdoc/TSort.html
14
12
  # See also: Is this topological sort in Ruby flawed?
15
13
  class FeatureModel
16
-
17
14
  FeatureDependencies = Struct.new(:dependee, :dependents)
18
15
 
19
16
  # Helper class used internally by FeatureModel class.
@@ -47,7 +44,6 @@ class FeatureModel
47
44
  children = dependents.map { |feature| lookup[feature] }
48
45
  children.each(&aBlock)
49
46
  end
50
-
51
47
  end # class
52
48
 
53
49
 
@@ -231,7 +227,7 @@ EOS
231
227
 
232
228
  source_dir = File.absolute_path(Dir.getwd)
233
229
  proj_dir = File.absolute_path(theProjDir)
234
- anonymous = anonymous_features.map { |ff| ff.basename }
230
+ anonymous = anonymous_features.map(&:basename)
235
231
  feature_ids = feature_files.map { |ff| ff.feature.identifier }
236
232
  feature_ids.compact!
237
233
  deps = dependencies.reject { |dep| dep.dependee.feature.anonymous? }
@@ -290,9 +286,7 @@ EOS
290
286
 
291
287
  return @dependencies
292
288
  end
293
-
294
289
  end # class
295
-
296
290
  end # module
297
291
 
298
292
  # end of file
@@ -1,8 +1,6 @@
1
1
  # File: feature-rep.rb
2
2
 
3
3
  module Cukedep # This module is used as a namespace
4
-
5
-
6
4
  # A FeatureRep is the internal representation of a Gherkin feature.
7
5
  class FeatureRep
8
6
  # Constant that specifies how feature identifier tags should begin
@@ -42,9 +40,7 @@ class FeatureRep
42
40
  def anonymous?()
43
41
  return identifier.nil?
44
42
  end
45
-
46
43
  end # class
47
-
48
44
  end # module
49
45
 
50
46
  # End of file
@@ -1,221 +1,209 @@
1
- # File: file-action.rb
2
-
3
- require 'pathname'
4
- require 'fileutils'
5
-
6
- module Cukedep # This module is used as a namespace
7
-
8
-
9
- class FileAction
10
- attr(:patterns, true)
11
- attr_reader(:delta)
12
-
13
- # Constructor.
14
- # [thePatterns] An array of file patterns.
15
- def initialize(thePatterns, aDelta = nil)
16
- @patterns = validate_file_patterns(thePatterns)
17
- @delta = validate_delta(aDelta)
18
- end
19
-
20
-
21
- # Datavalue semantic: FileActions don't have identity
22
- def ==(other)
23
- return true if object_id == other.object_id
24
- return false if self.class != other.class
25
-
26
- attrs = [:patterns, :delta]
27
- equality = true
28
-
29
- attrs.each do |accessor|
30
- equality = send(accessor) == other.send(accessor)
31
- break unless equality
32
- end
33
-
34
- return equality
35
- end
36
-
37
-
38
- protected
39
-
40
- def validate_file_patterns(filePatterns)
41
- err_msg = 'Expecting a list of file patterns'
42
- fail StandardError, err_msg unless filePatterns.is_a?(Array)
43
- filePatterns.each do |filePatt|
44
- err_msg = "Invalid value in list of file patterns: #{filePatt}"
45
- fail StandardError, err_msg unless filePatt.is_a?(String)
46
- end
47
-
48
- return filePatterns
49
- end
50
-
51
- def validate_delta(aDelta)
52
- case aDelta
53
- when NilClass then validated = nil
54
- when String
55
- validated = aDelta.empty? ? nil : aDelta
56
- else
57
- fail StandardError, 'Invalid relative path #{aDelta}'
58
- end
59
-
60
- return validated
61
- end
62
-
63
- # Determine the complete target path
64
- # complete target path = target dir + delta
65
- def full_path(targetDir)
66
- if delta.nil?
67
- result = Pathname.new(targetDir)
68
- else
69
- result = (Pathname.new(targetDir) + delta)
70
- end
71
-
72
- path = result.relative? ? result.expand_path : result
73
-
74
- return path.to_s
75
- end
76
-
77
- end # class
78
-
79
-
80
-
81
- # A delete action object has for purpose to
82
- # delete files matching one of its file patterns.
83
- # These file are deleted from (a subdir of) a given 'target' directory.
84
- class DeleteAction < FileAction
85
-
86
- # Constructor.
87
- # [thePatterns] An array of file patterns.
88
- def initialize(thePatterns, aDelta = nil)
89
- super(thePatterns, aDelta)
90
- end
91
-
92
- def run!(targetDir)
93
- return if patterns.empty?
94
- orig_dir = Dir.getwd # Store current work directory
95
- # pp orig_dir
96
-
97
- begin
98
- Dir.chdir(full_path(targetDir))
99
-
100
- patterns.each do |pattern|
101
- Dir.glob(pattern) { |fname| single_action(fname) }
102
- end
103
- ensure
104
- Dir.chdir(orig_dir) # Restore original work directory
105
- end
106
- end
107
-
108
- private
109
-
110
- def single_action(aFilename)
111
- FileUtils.remove_file(aFilename)
112
- end
113
-
114
- end # class
115
-
116
-
117
-
118
- # A copy action object has for purpose to
119
- # copy files matching one of its file patterns.
120
- # These file are copied from a given 'source' directory
121
- # and are placed in a target directory or a specific subdirectory
122
- # of the target directory.
123
- class CopyAction < FileAction
124
-
125
- def run!(sourceDir, targetDir)
126
- return if patterns.empty?
127
- orig_dir = Dir.getwd # Store current work directory
128
-
129
- begin
130
- Dir.chdir(sourceDir)
131
-
132
- destination = full_path(targetDir)
133
-
134
- patterns.each do |pattern|
135
- Dir.glob(pattern) { |fname| single_action(fname, destination) }
136
- end
137
- ensure
138
- Dir.chdir(orig_dir) # Restore original work directory
139
- end
140
- end
141
-
142
- private
143
-
144
- def single_action(aFilename, aDirectory)
145
- FileUtils.cp(aFilename, aDirectory)
146
- end
147
-
148
- end # class
149
-
150
-
151
- # An (file) action triplet combines three FileActions
152
- # that are executed in sequence.
153
- class ActionTriplet
154
-
155
- attr_reader(:save_action)
156
- attr_reader(:delete_action)
157
- attr_reader(:copy_action)
158
-
159
- # [theActionSettings] An object that responds to the [] operator.
160
- # The argument of the operator must be:
161
- # :save_patterns, :save_subdir, :delete_patterns, :delete_subdir,
162
- # :copy_patterns, :copy_subdir
163
- def initialize(theActionSettings)
164
- @save_action = CopyAction.new(theActionSettings[:save_patterns],
165
- theActionSettings[:save_subdir])
166
- @delete_action = DeleteAction.new(theActionSettings[:delete_patterns],
167
- theActionSettings[:delete_subdir])
168
- @copy_action = CopyAction.new(theActionSettings[:copy_patterns],
169
- theActionSettings[:copy_subdir])
170
- end
171
-
172
-
173
- def ==(other)
174
- return true if object_id == other.object_id
175
-
176
- return (save_action == other.save_action) &&
177
- (delete_action == other.delete_action) &&
178
- (copy_action == other.copy_action)
179
- end
180
-
181
-
182
- # Launch the file actions in sequence.
183
- def run!(currentDir, projectDir)
184
- save_action.run!(projectDir, currentDir)
185
- delete_action.run!(projectDir)
186
- copy_action.run!(currentDir, projectDir)
187
- end
188
-
189
-
190
- # Retrieve the 'built-in' action triplet associated with the given event.
191
- # Return nil if no triplet was found for the event.
192
- def self.builtin(anEvent)
193
- @@builtin_actions ||= {
194
- before_each: ActionTriplet.new(
195
- save_patterns: [],
196
- save_subdir: '',
197
- delete_patterns: ['*.feature'],
198
- delete_subdir: './features',
199
- copy_patterns: [],
200
- copy_subdir: './features'
201
- ),
202
- after_each: ActionTriplet.new(
203
- save_patterns: [],
204
- save_subdir: '',
205
- delete_patterns: ['*.feature'], # Remove feature files after the run
206
- delete_subdir: './features',
207
- copy_patterns: [],
208
- copy_subdir: ''
209
- )
210
- }
211
-
212
- return @@builtin_actions.fetch(anEvent, nil)
213
- end
214
-
215
- end # class
216
-
217
-
218
-
219
- end # module
220
-
221
- # End of file
1
+ # File: file-action.rb
2
+
3
+ require 'pathname'
4
+ require 'fileutils'
5
+
6
+ module Cukedep # This module is used as a namespace
7
+ class FileAction
8
+ attr(:patterns, true)
9
+ attr_reader(:delta)
10
+
11
+ # Constructor.
12
+ # [thePatterns] An array of file patterns.
13
+ def initialize(thePatterns, aDelta = nil)
14
+ @patterns = validate_file_patterns(thePatterns)
15
+ @delta = validate_delta(aDelta)
16
+ end
17
+
18
+
19
+ # Datavalue semantic: FileActions don't have identity
20
+ def ==(other)
21
+ return true if object_id == other.object_id
22
+ return false if self.class != other.class
23
+
24
+ attrs = [:patterns, :delta]
25
+ equality = true
26
+
27
+ attrs.each do |accessor|
28
+ equality = send(accessor) == other.send(accessor)
29
+ break unless equality
30
+ end
31
+
32
+ return equality
33
+ end
34
+
35
+
36
+ protected
37
+
38
+ def validate_file_patterns(filePatterns)
39
+ err_msg = 'Expecting a list of file patterns'
40
+ fail StandardError, err_msg unless filePatterns.is_a?(Array)
41
+ filePatterns.each do |filePatt|
42
+ err_msg = "Invalid value in list of file patterns: #{filePatt}"
43
+ fail StandardError, err_msg unless filePatt.is_a?(String)
44
+ end
45
+
46
+ return filePatterns
47
+ end
48
+
49
+ def validate_delta(aDelta)
50
+ case aDelta
51
+ when NilClass then validated = nil
52
+ when String
53
+ validated = aDelta.empty? ? nil : aDelta
54
+ else
55
+ fail StandardError, 'Invalid relative path #{aDelta}'
56
+ end
57
+
58
+ return validated
59
+ end
60
+
61
+ # Determine the complete target path
62
+ # complete target path = target dir + delta
63
+ def full_path(targetDir)
64
+ if delta.nil?
65
+ result = Pathname.new(targetDir)
66
+ else
67
+ result = (Pathname.new(targetDir) + delta)
68
+ end
69
+
70
+ path = result.relative? ? result.expand_path : result
71
+
72
+ return path.to_s
73
+ end
74
+ end # class
75
+
76
+
77
+
78
+ # A delete action object has for purpose to
79
+ # delete files matching one of its file patterns.
80
+ # These file are deleted from (a subdir of) a given 'target' directory.
81
+ class DeleteAction < FileAction
82
+ # Constructor.
83
+ # [thePatterns] An array of file patterns.
84
+ def initialize(thePatterns, aDelta = nil)
85
+ super(thePatterns, aDelta)
86
+ end
87
+
88
+ def run!(targetDir)
89
+ return if patterns.empty?
90
+ orig_dir = Dir.getwd # Store current work directory
91
+ # pp orig_dir
92
+
93
+ begin
94
+ Dir.chdir(full_path(targetDir))
95
+
96
+ patterns.each do |pattern|
97
+ Dir.glob(pattern) { |fname| single_action(fname) }
98
+ end
99
+ ensure
100
+ Dir.chdir(orig_dir) # Restore original work directory
101
+ end
102
+ end
103
+
104
+ private
105
+
106
+ def single_action(aFilename)
107
+ FileUtils.remove_file(aFilename)
108
+ end
109
+ end # class
110
+
111
+
112
+
113
+ # A copy action object has for purpose to
114
+ # copy files matching one of its file patterns.
115
+ # These file are copied from a given 'source' directory
116
+ # and are placed in a target directory or a specific subdirectory
117
+ # of the target directory.
118
+ class CopyAction < FileAction
119
+ def run!(sourceDir, targetDir)
120
+ return if patterns.empty?
121
+ orig_dir = Dir.getwd # Store current work directory
122
+
123
+ begin
124
+ Dir.chdir(sourceDir)
125
+
126
+ destination = full_path(targetDir)
127
+
128
+ patterns.each do |pattern|
129
+ Dir.glob(pattern) { |fname| single_action(fname, destination) }
130
+ end
131
+ ensure
132
+ Dir.chdir(orig_dir) # Restore original work directory
133
+ end
134
+ end
135
+
136
+ private
137
+
138
+ def single_action(aFilename, aDirectory)
139
+ FileUtils.cp(aFilename, aDirectory)
140
+ end
141
+ end # class
142
+
143
+
144
+ # An (file) action triplet combines three FileActions
145
+ # that are executed in sequence.
146
+ class ActionTriplet
147
+ attr_reader(:save_action)
148
+ attr_reader(:delete_action)
149
+ attr_reader(:copy_action)
150
+
151
+ # [theActionSettings] An object that responds to the [] operator.
152
+ # The argument of the operator must be:
153
+ # :save_patterns, :save_subdir, :delete_patterns, :delete_subdir,
154
+ # :copy_patterns, :copy_subdir
155
+ def initialize(theActionSettings)
156
+ @save_action = CopyAction.new(theActionSettings[:save_patterns],
157
+ theActionSettings[:save_subdir])
158
+ @delete_action = DeleteAction.new(theActionSettings[:delete_patterns],
159
+ theActionSettings[:delete_subdir])
160
+ @copy_action = CopyAction.new(theActionSettings[:copy_patterns],
161
+ theActionSettings[:copy_subdir])
162
+ end
163
+
164
+
165
+ def ==(other)
166
+ return true if object_id == other.object_id
167
+
168
+ return (save_action == other.save_action) &&
169
+ (delete_action == other.delete_action) &&
170
+ (copy_action == other.copy_action)
171
+ end
172
+
173
+
174
+ # Launch the file actions in sequence.
175
+ def run!(currentDir, projectDir)
176
+ save_action.run!(projectDir, currentDir)
177
+ delete_action.run!(projectDir)
178
+ copy_action.run!(currentDir, projectDir)
179
+ end
180
+
181
+
182
+ # Retrieve the 'built-in' action triplet associated with the given event.
183
+ # Return nil if no triplet was found for the event.
184
+ def self.builtin(anEvent)
185
+ @@builtin_actions ||= {
186
+ before_each: ActionTriplet.new(
187
+ save_patterns: [],
188
+ save_subdir: '',
189
+ delete_patterns: ['*.feature'],
190
+ delete_subdir: './features',
191
+ copy_patterns: [],
192
+ copy_subdir: './features'
193
+ ),
194
+ after_each: ActionTriplet.new(
195
+ save_patterns: [],
196
+ save_subdir: '',
197
+ delete_patterns: ['*.feature'], # Remove feature files after the run
198
+ delete_subdir: './features',
199
+ copy_patterns: [],
200
+ copy_subdir: ''
201
+ )
202
+ }
203
+
204
+ return @@builtin_actions.fetch(anEvent, nil)
205
+ end
206
+ end # class
207
+ end # module
208
+
209
+ # End of file