cukedep 0.1.10 → 0.1.11

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. 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