cukedep 0.1.11 → 0.2.00

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 (45) hide show
  1. checksums.yaml +6 -14
  2. data/.ruby-version +1 -1
  3. data/.travis.yml +10 -10
  4. data/CHANGELOG.md +6 -0
  5. data/Gemfile +5 -5
  6. data/LICENSE.txt +1 -1
  7. data/README.md +1 -1
  8. data/Rakefile +30 -30
  9. data/bin/cukedep +15 -15
  10. data/lib/cukedep/application.rb +105 -112
  11. data/lib/cukedep/cli/cmd-line.rb +11 -13
  12. data/lib/cukedep/config.rb +85 -89
  13. data/lib/cukedep/constants.rb +5 -5
  14. data/lib/cukedep/cuke-runner.rb +191 -198
  15. data/lib/cukedep/customization.rb +30 -30
  16. data/lib/cukedep/feature-model.rb +43 -46
  17. data/lib/cukedep/feature-rep.rb +9 -11
  18. data/lib/cukedep/file-action.rb +11 -18
  19. data/lib/cukedep/gherkin-facade.rb +11 -6
  20. data/lib/cukedep/gherkin-listener.rb +12 -42
  21. data/lib/cukedep/hook-dsl.rb +78 -78
  22. data/lib/cukedep/sandbox.rb +15 -16
  23. data/lib/cukedep.rb +1 -2
  24. data/sample/features/step_definitions/steps.rb +2 -2
  25. data/sample/model/model.rb +19 -20
  26. data/spec/cukedep/application_spec.rb +80 -80
  27. data/spec/cukedep/cli/cmd-line_spec.rb +88 -88
  28. data/spec/cukedep/cuke-runner_spec.rb +74 -74
  29. data/spec/cukedep/customization_spec.rb +31 -31
  30. data/spec/cukedep/debug-file-action.rb +29 -29
  31. data/spec/cukedep/feature-model_spec.rb +100 -100
  32. data/spec/cukedep/feature-rep_spec.rb +2 -1
  33. data/spec/cukedep/file-action_spec.rb +365 -366
  34. data/spec/cukedep/file-parsing.rb +39 -41
  35. data/spec/cukedep/gherkin-facade_spec.rb +48 -49
  36. data/spec/cukedep/gherkin-listener_spec.rb +55 -57
  37. data/spec/cukedep/hook-dsl_spec.rb +182 -182
  38. data/spec/cukedep/sample_features/cukedep_hooks.rb +30 -30
  39. data/spec/cukedep/sample_features/standalone.feature +1 -1
  40. data/templates/rake.erb +12 -21
  41. metadata +80 -58
  42. data/sample/result.html +0 -472
  43. data/spec/cukedep/sample_features/cukedep.rake +0 -215
  44. data/spec/cukedep/sample_features/dependencies.dot +0 -38
  45. data/spec/cukedep/sample_features/feature2id.csv +0 -7
@@ -3,10 +3,10 @@
3
3
 
4
4
  module Cukedep # Module used as a namespace
5
5
  # The version number of the gem.
6
- Version = '0.1.11'
6
+ Version = '0.2.00'.freeze
7
7
 
8
8
  # Brief description of the gem.
9
- Description = 'Manage dependencies between Cucumber feature files'
9
+ Description = 'Manage dependencies between Cucumber feature files'.freeze
10
10
 
11
11
  # Constant Cukedep::RootDir contains the absolute path of Rodent's
12
12
  # root directory. Note: it also ends with a slash character.
@@ -22,11 +22,11 @@ module Cukedep # Module used as a namespace
22
22
  end
23
23
 
24
24
  # The file name for the user's settings
25
- YMLFilename = '.cukedep.yml'
26
-
25
+ YMLFilename = '.cukedep.yml'.freeze
26
+
27
27
  # The file name for the custom block codes associated
28
28
  # with before/after events.
29
- HookFilename = 'cukedep_hooks.rb'
29
+ HookFilename = 'cukedep_hooks.rb'.freeze
30
30
  end
31
31
  end # module
32
32
 
@@ -1,198 +1,191 @@
1
- # File: cuke-runner.rb
2
-
3
- require 'pathname'
4
- require 'rake'
5
-
6
- # Run Cucumber via specialized Rake task
7
- require 'cucumber/rake/task'
8
-
9
- require_relative 'file-action'
10
- require_relative 'customization'
11
-
12
- # UGLY workaround for bug in Cucumber's rake task
13
- if Gem::VERSION[0].to_i >= 2 && Cucumber::VERSION <= '1.3.2'
14
- # Monkey-patch a buggy method
15
- module Cucumber
16
- module Rake
17
- class Task
18
- class ForkedCucumberRunner
19
- def gem_available?(gemname)
20
- if Gem::VERSION[0].to_i >= 2
21
- gem_available_new_rubygems?(gemname)
22
- else
23
- gem_available_old_rubygems?(gemname)
24
- end
25
- end
26
- end # class
27
- end # class
28
- end # module
29
- end # module
30
- end
31
-
32
-
33
-
34
- module Cukedep # This module is used as a namespace
35
- # Purpose: to launch Cucumber in the appropriate directory
36
- # and pass it command-line arguments.
37
- # Responsibilities:
38
- # Know how to invoke Cucumber
39
- # Know the base directory
40
- # Know the project's root dir
41
- class CukeRunner
42
- # The current state of the runner.
43
- attr_reader(:state)
44
-
45
- # The absolute path of the root's project directory
46
- attr_reader(:proj_dir)
47
- attr_reader(:base_dir)
48
- attr_reader(:config)
49
- attr_reader(:handlers)
50
-
51
- attr(:cucumber_opts, true)
52
-
53
- # Constructor
54
- def initialize(baseDir, projectDir, aConfig)
55
- @base_dir = baseDir
56
- @proj_dir = validated_proj_dir(projectDir)
57
- @config = aConfig
58
- @handlers = Customization.new.build_handlers(baseDir)
59
-
60
- @state = :Initialized
61
- end
62
-
63
- # Launch Cucumber in the project directory.
64
- def invoke()
65
- options = [] # TODO: retrieve Cucumber options
66
- orig_dir = Dir.getwd
67
- Dir.chdir(proj_dir)
68
-
69
- begin
70
- cuke_task = Cucumber::Rake::Task.new do |t|
71
- t.cucumber_opts = options
72
- end
73
-
74
- cuke_task.runner.run
75
- rescue SystemExit => exc # Cucumber reports a failure.
76
- raise StandardError, "Cucumber exited with status #{exc.status}"
77
- ensure
78
- Dir.chdir(orig_dir)
79
- end
80
- end
81
-
82
- # Event handler that is triggered
83
- # before any other event.
84
- # It executes the before all hook first.
85
- # Then it executes in the following order:
86
- # Built-in save action, Custom save action
87
- # Built-in delete action, Custom delete action
88
- # Built-in copy action, Custom copy action
89
- def before_all()
90
- expected_state(:Initialized)
91
-
92
- # Execute before all hook code
93
- run_code_block
94
-
95
- # Execute file actions
96
- builtin_actions = ActionTriplet.builtin(:before_all)
97
- custom_actions = ActionTriplet.new(config.before_all_f_actions)
98
- run_triplets([builtin_actions, custom_actions])
99
- @state = :ReadyToRun
100
- end
101
-
102
-
103
- # Event handler that is triggered
104
- # after any other event.
105
- # It executes first actions in the following order:
106
- # Built-in save action, Custom save action
107
- # Built-in delete action, Custom delete action
108
- # Built-in copy action, Custom copy action
109
- # Then it executes the after all hook last.
110
- def after_all()
111
- expected_state(:ReadyToRun)
112
-
113
- builtin_actions = ActionTriplet.builtin(:after_all)
114
- custom_actions = ActionTriplet.new(config.after_all_f_actions)
115
- run_triplets([builtin_actions, custom_actions])
116
-
117
- # Execute before all hook code
118
- run_code_block
119
- @state = :Complete
120
- end
121
-
122
-
123
- def run!(fileNames)
124
- expected_state(:ReadyToRun)
125
- before_each(fileNames)
126
- invoke
127
- after_each
128
- end
129
-
130
-
131
- private
132
-
133
- def validated_proj_dir(projectDir)
134
- path = Pathname.new(projectDir)
135
- path = path.expand_path if path.relative?
136
- fail StandardError, "No such project path: '#{path}'" unless path.exist?
137
-
138
- return path.to_s
139
- end
140
-
141
- def expected_state(aState)
142
- return if state == aState
143
- msg = "expected state was '#{aState}' instead of '#{state}'."
144
- fail StandardError, msg
145
- end
146
-
147
-
148
- def before_each(fileNames)
149
- # Execute before each hook code
150
- run_code_block(fileNames)
151
-
152
- builtins = ActionTriplet.builtin(:before_each).dup
153
- builtins.copy_action.patterns = fileNames unless builtins.nil?
154
-
155
- custom_actions = ActionTriplet.new(config.before_each_f_actions)
156
- run_triplets([builtins, custom_actions])
157
- end
158
-
159
-
160
- def after_each()
161
- builtin_actions = ActionTriplet.builtin(:after_each)
162
-
163
- custom_actions = ActionTriplet.new(config.after_each_f_actions)
164
- run_triplets([builtin_actions, custom_actions])
165
-
166
- # Execute after each hook code
167
- run_code_block
168
- end
169
-
170
-
171
- def run_triplets(theTriplets)
172
- all_triplets = theTriplets.compact # Remove nil elements
173
-
174
- # Do all save actions...
175
- all_triplets.each { |t| t.save_action.run!(proj_dir, base_dir) }
176
-
177
- # Do all delete actions...
178
- all_triplets.each { |t| t.delete_action.run!(proj_dir) }
179
-
180
- # Do all copy actions...
181
- all_triplets.each { |t| t.copy_action.run!(base_dir, proj_dir) }
182
- end
183
-
184
-
185
- def run_code_block(*args)
186
- # Retrieve the name of the parent method.
187
- parent_mth = (caller[0].sub(/^(.+):in (.+)$/, '\2'))[1..-2]
188
- kind, scope = parent_mth.split('_')
189
- hook_kind = (kind + '_hooks')
190
-
191
- kode = handlers[hook_kind.to_sym][scope.to_sym]
192
- return if kode.nil?
193
- safe_args = args.map { |one_arg| one_arg.dup.freeze }
194
- kode.call(*safe_args)
195
- end
196
- end # class
197
- end # module
198
- # End of file
1
+ # File: cuke-runner.rb
2
+
3
+ require 'pathname'
4
+ require 'rake'
5
+
6
+ # Run Cucumber via specialized Rake task
7
+ require 'cucumber/rake/task'
8
+
9
+ require_relative 'file-action'
10
+ require_relative 'customization'
11
+
12
+ # UGLY workaround for bug in Cucumber's rake task
13
+ if Gem::VERSION[0].to_i >= 2 && Cucumber::VERSION <= '1.3.2'
14
+ # Monkey-patch a buggy method
15
+ module Cucumber
16
+ module Rake
17
+ class Task
18
+ class ForkedCucumberRunner
19
+ def gem_available?(gemname)
20
+ if Gem::VERSION[0].to_i >= 2
21
+ gem_available_new_rubygems?(gemname)
22
+ else
23
+ gem_available_old_rubygems?(gemname)
24
+ end
25
+ end
26
+ end # class
27
+ end # class
28
+ end # module
29
+ end # module
30
+ end
31
+
32
+
33
+
34
+ module Cukedep # This module is used as a namespace
35
+ # Purpose: to launch Cucumber in the appropriate directory
36
+ # and pass it command-line arguments.
37
+ # Responsibilities:
38
+ # Know how to invoke Cucumber
39
+ # Know the base directory
40
+ # Know the project's root dir
41
+ class CukeRunner
42
+ # The current state of the runner.
43
+ attr_reader(:state)
44
+
45
+ # The absolute path of the root's project directory
46
+ attr_reader(:proj_dir)
47
+ attr_reader(:base_dir)
48
+ attr_reader(:config)
49
+ attr_reader(:handlers)
50
+
51
+ attr_accessor(:cucumber_opts)
52
+
53
+ # Constructor
54
+ def initialize(baseDir, projectDir, aConfig)
55
+ @base_dir = baseDir
56
+ @proj_dir = validated_proj_dir(projectDir)
57
+ @config = aConfig
58
+ @handlers = Customization.new.build_handlers(baseDir)
59
+
60
+ @state = :Initialized
61
+ end
62
+
63
+ # Launch Cucumber in the project directory.
64
+ def invoke
65
+ options = [] # TODO: retrieve Cucumber options
66
+ orig_dir = Dir.getwd
67
+ Dir.chdir(proj_dir)
68
+
69
+ begin
70
+ cuke_task = Cucumber::Rake::Task.new do |t|
71
+ t.cucumber_opts = options
72
+ end
73
+
74
+ cuke_task.runner.run
75
+ rescue SystemExit => exc # Cucumber reports a failure.
76
+ raise StandardError, "Cucumber exited with status #{exc.status}"
77
+ ensure
78
+ Dir.chdir(orig_dir)
79
+ end
80
+ end
81
+
82
+ # Event handler that is triggered
83
+ # before any other event.
84
+ # It executes the before all hook first.
85
+ # Then it executes in the following order:
86
+ # Built-in save action, Custom save action
87
+ # Built-in delete action, Custom delete action
88
+ # Built-in copy action, Custom copy action
89
+ def before_all
90
+ expected_state(:Initialized)
91
+
92
+ # Execute before all hook code
93
+ run_code_block
94
+
95
+ # Execute file actions
96
+ builtin_actions = ActionTriplet.builtin(:before_all)
97
+ custom_actions = ActionTriplet.new(config.before_all_f_actions)
98
+ run_triplets([builtin_actions, custom_actions])
99
+ @state = :ReadyToRun
100
+ end
101
+
102
+ # Event handler that is triggered
103
+ # after any other event.
104
+ # It executes first actions in the following order:
105
+ # Built-in save action, Custom save action
106
+ # Built-in delete action, Custom delete action
107
+ # Built-in copy action, Custom copy action
108
+ # Then it executes the after all hook last.
109
+ def after_all
110
+ expected_state(:ReadyToRun)
111
+
112
+ builtin_actions = ActionTriplet.builtin(:after_all)
113
+ custom_actions = ActionTriplet.new(config.after_all_f_actions)
114
+ run_triplets([builtin_actions, custom_actions])
115
+
116
+ # Execute before all hook code
117
+ run_code_block
118
+ @state = :Complete
119
+ end
120
+
121
+ def run!(fileNames)
122
+ expected_state(:ReadyToRun)
123
+ before_each(fileNames)
124
+ invoke
125
+ after_each
126
+ end
127
+
128
+ private
129
+
130
+ def validated_proj_dir(projectDir)
131
+ path = Pathname.new(projectDir)
132
+ path = path.expand_path if path.relative?
133
+ raise StandardError, "No such project path: '#{path}'" unless path.exist?
134
+
135
+ return path.to_s
136
+ end
137
+
138
+ def expected_state(aState)
139
+ return if state == aState
140
+ msg = "expected state was '#{aState}' instead of '#{state}'."
141
+ raise StandardError, msg
142
+ end
143
+
144
+ def before_each(fileNames)
145
+ # Execute before each hook code
146
+ run_code_block(fileNames)
147
+
148
+ builtins = ActionTriplet.builtin(:before_each).dup
149
+ builtins.copy_action.patterns = fileNames unless builtins.nil?
150
+
151
+ custom_actions = ActionTriplet.new(config.before_each_f_actions)
152
+ run_triplets([builtins, custom_actions])
153
+ end
154
+
155
+ def after_each
156
+ builtin_actions = ActionTriplet.builtin(:after_each)
157
+
158
+ custom_actions = ActionTriplet.new(config.after_each_f_actions)
159
+ run_triplets([builtin_actions, custom_actions])
160
+
161
+ # Execute after each hook code
162
+ run_code_block
163
+ end
164
+
165
+ def run_triplets(theTriplets)
166
+ all_triplets = theTriplets.compact # Remove nil elements
167
+
168
+ # Do all save actions...
169
+ all_triplets.each { |t| t.save_action.run!(proj_dir, base_dir) }
170
+
171
+ # Do all delete actions...
172
+ all_triplets.each { |t| t.delete_action.run!(proj_dir) }
173
+
174
+ # Do all copy actions...
175
+ all_triplets.each { |t| t.copy_action.run!(base_dir, proj_dir) }
176
+ end
177
+
178
+ def run_code_block(*args)
179
+ # Retrieve the name of the parent method.
180
+ parent_mth = (caller[0].sub(/^(.+):in (.+)$/, '\2'))[1..-2]
181
+ kind, scope = parent_mth.split('_')
182
+ hook_kind = (kind + '_hooks')
183
+
184
+ kode = handlers[hook_kind.to_sym][scope.to_sym]
185
+ return if kode.nil?
186
+ safe_args = args.map { |one_arg| one_arg.dup.freeze }
187
+ kode.call(*safe_args)
188
+ end
189
+ end # class
190
+ end # module
191
+ # End of file
@@ -1,30 +1,30 @@
1
- # File: customization.rb
2
-
3
- require_relative 'constants'
4
- require_relative 'hook-dsl'
5
-
6
- module Cukedep # This module is used as a namespace
7
- class Customization
8
- # Retrieve before/after handlers from file
9
- # Handlers are put in a Hash with keys :before_hooks, :after_hooks.
10
- def build_handlers(directory)
11
- handlers = nil
12
-
13
- filepath = directory + '/' + Cukedep::HookFilename
14
- if File.exist? filepath
15
- obj = Object.new
16
- obj.extend(HookDSL)
17
- hook_source = File.read(filepath)
18
- obj.instance_eval(hook_source)
19
- handlers = {
20
- before_hooks: obj.before_hooks,
21
- after_hooks: obj.after_hooks
22
- }
23
- end
24
-
25
- return handlers
26
- end
27
- end # class
28
- end # module
29
-
30
- # End of file
1
+ # File: customization.rb
2
+
3
+ require_relative 'constants'
4
+ require_relative 'hook-dsl'
5
+
6
+ module Cukedep # This module is used as a namespace
7
+ class Customization
8
+ # Retrieve before/after handlers from file
9
+ # Handlers are put in a Hash with keys :before_hooks, :after_hooks.
10
+ def build_handlers(directory)
11
+ handlers = nil
12
+
13
+ filepath = directory + '/' + Cukedep::HookFilename
14
+ if File.exist? filepath
15
+ obj = Object.new
16
+ obj.extend(HookDSL)
17
+ hook_source = File.read(filepath)
18
+ obj.instance_eval(hook_source)
19
+ handlers = {
20
+ before_hooks: obj.before_hooks,
21
+ after_hooks: obj.after_hooks
22
+ }
23
+ end
24
+
25
+ return handlers
26
+ end
27
+ end # class
28
+ end # module
29
+
30
+ # End of file