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.
- checksums.yaml +8 -8
- data/CHANGELOG.md +4 -0
- data/Rakefile +4 -6
- data/lib/cukedep/application.rb +89 -91
- data/lib/cukedep/cli/cmd-line.rb +0 -7
- data/lib/cukedep/config.rb +70 -74
- data/lib/cukedep/constants.rb +1 -1
- data/lib/cukedep/cuke-runner.rb +0 -5
- data/lib/cukedep/customization.rb +0 -5
- data/lib/cukedep/feature-model.rb +1 -7
- data/lib/cukedep/feature-rep.rb +0 -4
- data/lib/cukedep/file-action.rb +209 -221
- data/lib/cukedep/gherkin-facade.rb +7 -10
- data/lib/cukedep/gherkin-listener.rb +82 -89
- data/lib/cukedep/hook-dsl.rb +0 -4
- data/lib/cukedep/sandbox.rb +0 -5
- data/sample/features/step_definitions/steps.rb +30 -26
- data/sample/features/support/env.rb +1 -1
- data/sample/model/model.rb +198 -205
- data/sample/result.html +1 -1
- data/spec/cukedep/application_spec.rb +15 -16
- data/spec/cukedep/cli/cmd-line_spec.rb +13 -16
- data/spec/cukedep/cuke-runner_spec.rb +55 -61
- data/spec/cukedep/customization_spec.rb +21 -26
- data/spec/cukedep/debug-file-action.rb +12 -10
- data/spec/cukedep/feature-model_spec.rb +13 -16
- data/spec/cukedep/feature-rep_spec.rb +4 -7
- data/spec/cukedep/file-action_spec.rb +18 -34
- data/spec/cukedep/file-parsing.rb +9 -11
- data/spec/cukedep/gherkin-facade_spec.rb +3 -8
- data/spec/cukedep/gherkin-listener_spec.rb +10 -12
- data/spec/cukedep/hook-dsl_spec.rb +6 -9
- data/spec/cukedep/sample_features/cukedep.rake +44 -37
- data/spec/cukedep/sample_features/cukedep_hooks.rb +2 -2
- data/spec/cukedep/sample_features/dependencies.dot +1 -1
- data/templates/rake.erb +36 -29
- metadata +2 -2
data/lib/cukedep/cuke-runner.rb
CHANGED
@@ -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
|
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
|
data/lib/cukedep/feature-rep.rb
CHANGED
@@ -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
|
data/lib/cukedep/file-action.rb
CHANGED
@@ -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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
#
|
83
|
-
#
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
# An
|
152
|
-
#
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
(
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
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
|