yard-cucumber 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. data/.rspec +3 -0
  2. data/History.txt +190 -0
  3. data/README.md +145 -0
  4. data/Rakefile +17 -0
  5. data/city.gemspec +66 -0
  6. data/example/README.md +8 -0
  7. data/example/child_feature/README.md +21 -0
  8. data/example/child_feature/child.feature +11 -0
  9. data/example/child_feature/grandchild_feature/grandchild.feature +12 -0
  10. data/example/empty.feature +2 -0
  11. data/example/scenario.feature +63 -0
  12. data/example/scenario_outline.feature +80 -0
  13. data/example/step_definitions/example.step.rb +109 -0
  14. data/example/step_definitions/first.step.rb +21 -0
  15. data/example/step_definitions/support/env.rb +7 -0
  16. data/example/step_definitions/support/env_support.rb +12 -0
  17. data/example/step_definitions/support/support.rb +6 -0
  18. data/example/tags.feature +18 -0
  19. data/example/transform.feature +13 -0
  20. data/lib/cucumber/city_builder.rb +209 -0
  21. data/lib/docserver/default/fulldoc/html/js/cucumber.js +85 -0
  22. data/lib/docserver/default/layout/html/headers.erb +13 -0
  23. data/lib/docserver/doc_server/full_list/html/full_list.erb +37 -0
  24. data/lib/docserver/doc_server/full_list/html/setup.rb +18 -0
  25. data/lib/templates/default/feature/html/feature.erb +39 -0
  26. data/lib/templates/default/feature/html/no_steps_defined.erb +1 -0
  27. data/lib/templates/default/feature/html/outline.erb +42 -0
  28. data/lib/templates/default/feature/html/pystring.erb +3 -0
  29. data/lib/templates/default/feature/html/scenario.erb +55 -0
  30. data/lib/templates/default/feature/html/setup.rb +55 -0
  31. data/lib/templates/default/feature/html/steps.erb +39 -0
  32. data/lib/templates/default/feature/html/table.erb +20 -0
  33. data/lib/templates/default/featuredirectory/html/alpha_table.erb +26 -0
  34. data/lib/templates/default/featuredirectory/html/directory.erb +32 -0
  35. data/lib/templates/default/featuredirectory/html/setup.rb +41 -0
  36. data/lib/templates/default/featuretags/html/namespace.erb +131 -0
  37. data/lib/templates/default/featuretags/html/setup.rb +34 -0
  38. data/lib/templates/default/fulldoc/html/css/common.css +214 -0
  39. data/lib/templates/default/fulldoc/html/full_list.erb +36 -0
  40. data/lib/templates/default/fulldoc/html/full_list_features.erb +28 -0
  41. data/lib/templates/default/fulldoc/html/full_list_stepdefinitions.erb +11 -0
  42. data/lib/templates/default/fulldoc/html/full_list_steps.erb +13 -0
  43. data/lib/templates/default/fulldoc/html/full_list_tags.erb +12 -0
  44. data/lib/templates/default/fulldoc/html/index.erb +24 -0
  45. data/lib/templates/default/fulldoc/html/js/cucumber.js +314 -0
  46. data/lib/templates/default/fulldoc/html/setup.rb +72 -0
  47. data/lib/templates/default/layout/html/headers.erb +14 -0
  48. data/lib/templates/default/layout/html/search.erb +7 -0
  49. data/lib/templates/default/requirements/html/alpha_table.erb +26 -0
  50. data/lib/templates/default/requirements/html/requirements.erb +50 -0
  51. data/lib/templates/default/requirements/html/setup.rb +51 -0
  52. data/lib/templates/default/steptransformers/html/header.erb +12 -0
  53. data/lib/templates/default/steptransformers/html/index.erb +10 -0
  54. data/lib/templates/default/steptransformers/html/setup.rb +94 -0
  55. data/lib/templates/default/steptransformers/html/transformers.erb +74 -0
  56. data/lib/templates/default/steptransformers/html/undefinedsteps.erb +26 -0
  57. data/lib/templates/default/tag/html/alpha_table.erb +32 -0
  58. data/lib/templates/default/tag/html/setup.rb +27 -0
  59. data/lib/templates/default/tag/html/tag.erb +35 -0
  60. data/lib/yard/code_objects/cucumber/base.rb +32 -0
  61. data/lib/yard/code_objects/cucumber/feature.rb +18 -0
  62. data/lib/yard/code_objects/cucumber/namespace_object.rb +45 -0
  63. data/lib/yard/code_objects/cucumber/scenario.rb +26 -0
  64. data/lib/yard/code_objects/cucumber/scenario_outline.rb +66 -0
  65. data/lib/yard/code_objects/cucumber/step.rb +35 -0
  66. data/lib/yard/code_objects/cucumber/tag.rb +27 -0
  67. data/lib/yard/code_objects/step_definition.rb +7 -0
  68. data/lib/yard/code_objects/step_transform.rb +7 -0
  69. data/lib/yard/code_objects/step_transformer.rb +51 -0
  70. data/lib/yard/handlers/cucumber/base.rb +22 -0
  71. data/lib/yard/handlers/cucumber/feature_handler.rb +93 -0
  72. data/lib/yard/handlers/legacy/step_definition_handler.rb +46 -0
  73. data/lib/yard/handlers/legacy/step_transform_handler.rb +24 -0
  74. data/lib/yard/handlers/step_definition_handler.rb +22 -0
  75. data/lib/yard/handlers/step_transform_handler.rb +23 -0
  76. data/lib/yard/parser/cucumber/feature.rb +46 -0
  77. data/lib/yard/parser/source_parser.rb +54 -0
  78. data/lib/yard/rake/city_task.rb +12 -0
  79. data/lib/yard/server/adapter.rb +29 -0
  80. data/lib/yard/server/commands/list_command.rb +25 -0
  81. data/lib/yard/server/router.rb +31 -0
  82. data/lib/yard/templates/helpers/base_helper.rb +26 -0
  83. data/lib/yard-cucumber.rb +53 -0
  84. metadata +173 -0
@@ -0,0 +1,74 @@
1
+ <% @items.each do |item| %>
2
+
3
+ <div class="transformer <%= @item_type.gsub(/\s/,'') %> <%= "nodefinitions" if item.steps.nil? || item.steps.empty? %>">
4
+ <a name="<%= anchor_for item %>"></a>
5
+ <div class="title">
6
+ <span class="pre"><%= h item.keyword %></span>
7
+ <span class="name"><%= link_constants item %></span>
8
+ <a style="float: right;" href="http://rubular.com/?regex=<%= urlencode item.value %>" target="_blank">Rubular</a>
9
+ <div style="clear: both;"></div>
10
+ </div>
11
+
12
+ <div class="details">
13
+
14
+ <div class="meta" style="clear: right;">
15
+ <div class="file"><%= h item.location %></div>
16
+ </div>
17
+
18
+
19
+ <!-- Comments -->
20
+ <div>
21
+ <%= display_comments_for item %>
22
+ </div>
23
+
24
+
25
+ <!-- Source Code -->
26
+ <div class="method_details_list">
27
+ <table class="source_code">
28
+ <tr>
29
+ <td>
30
+ <pre class="lines"><%= "" %><%= h format_lines(item) %></pre>
31
+ </td>
32
+ <td>
33
+ <pre class="code"><%= "" %><%= html_syntax_highlight item.source %></pre>
34
+ </td>
35
+ </tr>
36
+ </table>
37
+ </div>
38
+
39
+ <!-- Matching Step Instances -->
40
+ <% if item.steps.length > 0 %>
41
+ <div class='showSteps'>
42
+ [<a href='#' class='toggleSteps' alt="<%= item.steps.length %> steps">Hide <%= item.steps.length %> steps</a>]
43
+ </div>
44
+ <% end %>
45
+ <div class="steps">
46
+ <% if item.steps && !item.steps.empty? %>
47
+ <% unique_steps(item.steps).each_with_index do |uniq_step,step_index| %>
48
+ <div class="step <%= (step_index + 1) % 2 == 0 ? 'even' : 'odd' %>">
49
+ <div>
50
+ <span class="predicate">
51
+ <%= h uniq_step.last.first.keyword %>
52
+ </span>
53
+ <span class="defined">
54
+ <%= link_transformed_step(uniq_step.last.first) %>
55
+ </span>
56
+ </div>
57
+ <% uniq_step.last.each do |step| %>
58
+ <a class="definition" style="clear: right;" href="<%= url_for step.scenario.feature %>"><%= h step.location %></a>
59
+ <% end %>
60
+ <div style="clear: both;"></div>
61
+ </div>
62
+ <% end %>
63
+ <% else %>
64
+ <div class="undefined">No steps were found to match this <%= @item_type %>.</div>
65
+ <% end%>
66
+ </div>
67
+
68
+ </div>
69
+
70
+ <div style="margin: 30px 20px; border-top: 1px dotted #AAA;"></div>
71
+
72
+ </div>
73
+
74
+ <% end %>
@@ -0,0 +1,26 @@
1
+ <div class="transformer">
2
+ <div class="steps">
3
+ <% if @undefined_steps && !@undefined_steps.empty? %>
4
+ <% @undefined_steps.each_with_index do |uniq_step,step_index| %>
5
+ <div class="step <%= (step_index + 1) % 2 == 0 ? 'even' : 'odd' %>">
6
+ <div>
7
+ <span class="predicate"><%= uniq_step.last.first.keyword %></span>
8
+ <span class="undefined">
9
+ <%= h uniq_step.last.first.value %>
10
+ </span>
11
+ </div>
12
+ <% uniq_step.last.each do |step| %>
13
+ <a class="definition" style="clear: right;" href="<%= url_for step.scenario.feature %>">
14
+ <%= h step.location %>
15
+ </a>
16
+ <% end%>
17
+ <div style="clear: both;"></div>
18
+ </div>
19
+ <% end %>
20
+ <% else %>
21
+ <div class="steps">
22
+ <div class="undefined">No undefined steps</div>
23
+ </div>
24
+ <% end%>
25
+ </div>
26
+ </div>
@@ -0,0 +1,32 @@
1
+ <% if @elements && !@elements.empty? %>
2
+ <% i = (@elements.length % 2 == 0 ? 1 : 0) %>
3
+ <table style="margin-left: 10px; width: 100%;">
4
+ <tr>
5
+ <td valign='top' width="50%">
6
+ <% @elements.each do |letter, objects| %>
7
+ <% if (i += 1) > (@elements.length / 2 + 1) %>
8
+ </td><td valign='top' width="50%">
9
+ <% i = 0 %>
10
+ <% end %>
11
+ <ul id="alpha_<%= letter %>" class="alpha">
12
+ <li class="letter"><%= letter %></li>
13
+ <ul>
14
+ <% objects.each do |obj| %>
15
+ <li>
16
+ <% if obj.is_a?(YARD::CodeObjects::Cucumber::Scenario) || obj.is_a?(YARD::CodeObjects::Cucumber::ScenarioOutline) %>
17
+ <a href="<%= url_for(obj.feature,"scenario_#{obj.path[(/.+_(\d+)$/),1]}") %>">
18
+ <%= h obj.value %>
19
+ </a>
20
+ <% else %>
21
+ <%= linkify obj, obj.value %>
22
+ <% end %>
23
+ <small>(<%= obj.file %>)</small>
24
+ </li>
25
+ <% end %>
26
+ </ul>
27
+ </ul>
28
+ <% end %>
29
+ </td>
30
+ </tr>
31
+ </table>
32
+ <% end %>
@@ -0,0 +1,27 @@
1
+ def init
2
+ super
3
+ @tag = object
4
+
5
+ sections.push :tag
6
+ end
7
+
8
+ def features
9
+ @tag.features
10
+ end
11
+
12
+ def scenarios
13
+ @tag.scenarios
14
+ end
15
+
16
+
17
+ def alpha_table(objects)
18
+ @elements = Hash.new
19
+
20
+ objects = run_verifier(objects)
21
+ objects.each {|o| (@elements[o.value.to_s[0,1].upcase] ||= []) << o }
22
+ @elements.values.each {|v| v.sort! {|a,b| b.value.to_s <=> a.value.to_s } }
23
+ @elements = @elements.sort_by {|l,o| l.to_s }
24
+
25
+ @elements.each {|letter,objects| objects.sort! {|a,b| b.value.to_s <=> a.value.to_s }}
26
+ erb(:alpha_table)
27
+ end
@@ -0,0 +1,35 @@
1
+ <div class="tag">
2
+ <div class="title">
3
+ <span class="pre">Tag:</span>
4
+ <span class="name"><%= @tag.value %></span>
5
+
6
+ </div>
7
+
8
+ <div class="meta">
9
+ <div class="file">
10
+ <%= @tag.features.size > 0 ? "#{@tag.features.size} feature#{@tag.features.size > 1 ? 's' : ''} (with #{@tag.indirect_scenarios.size} scenario#{@tag.indirect_scenarios.size > 1 ? 's' : ''})" : "" %>
11
+ <%= " and " if @tag.features.size > 0 && @tag.scenarios.size > 0 %>
12
+ <%= @tag.scenarios.size > 0 ? "#{@tag.scenarios.size} scenario#{@tag.scenarios.size > 1 ? 's' : ''}" : "" %>
13
+ </div>
14
+ </div>
15
+
16
+ <div style="margin-top: 20px;">&nbsp;</div>
17
+
18
+ <% if features && !features.empty? %>
19
+ <div id="features" style="margin-left: 40px;">
20
+ <div class="title"><span class="name">Features</span></div>
21
+ </div>
22
+ <%= alpha_table(features) %>
23
+
24
+ <% end %>
25
+
26
+ <% if scenarios && !scenarios.empty? %>
27
+ <div id="features" style="margin-left: 40px;">
28
+ <div class="title"><span class="name">Scenarios</span></div>
29
+ </div>
30
+ <%= alpha_table(scenarios) %>
31
+
32
+ <% end %>
33
+
34
+
35
+ </div>
@@ -0,0 +1,32 @@
1
+
2
+ module YARD::CodeObjects::Cucumber
3
+
4
+ module LocationHelper
5
+
6
+ def line_number
7
+ files.first.last
8
+ end
9
+
10
+ def file
11
+ files.first.first if files && !files.empty?
12
+ end
13
+
14
+ def location
15
+ "#{file}:#{line_number}"
16
+ end
17
+
18
+ end
19
+
20
+ class Base < YARD::CodeObjects::Base
21
+ include LocationHelper
22
+
23
+ def path
24
+ @value || super
25
+ end
26
+
27
+ end
28
+
29
+
30
+
31
+ end
32
+
@@ -0,0 +1,18 @@
1
+
2
+
3
+ module YARD::CodeObjects::Cucumber
4
+
5
+ class Feature < NamespaceObject
6
+
7
+ attr_accessor :background, :comments, :description, :keyword, :scenarios, :tags, :value
8
+
9
+ def initialize(namespace,name)
10
+ @comments = ""
11
+ @scenarios = []
12
+ @tags = []
13
+ super(namespace,name.to_s.strip)
14
+ end
15
+
16
+ end
17
+
18
+ end
@@ -0,0 +1,45 @@
1
+
2
+ module YARD::CodeObjects::Cucumber
3
+
4
+ class NamespaceObject < YARD::CodeObjects::NamespaceObject
5
+ include LocationHelper
6
+ def value ; nil ; end
7
+ end
8
+
9
+ class Requirements < NamespaceObject ; end
10
+ class FeatureTags < NamespaceObject ; end
11
+ class StepTransformersObject < NamespaceObject ; end
12
+
13
+ class FeatureDirectory < YARD::CodeObjects::NamespaceObject
14
+
15
+ attr_accessor :description
16
+
17
+ def initialize(namespace,name)
18
+ super(namespace,name)
19
+ @description = ""
20
+ end
21
+
22
+ def location
23
+ files.first.first if files && !files.empty?
24
+ end
25
+
26
+ def value ; name ; end
27
+
28
+ def features
29
+ children.find_all {|d| d.is_a?(Feature) }
30
+ end
31
+
32
+ def subdirectories
33
+ subdirectories = children.find_all {|d| d.is_a?(FeatureDirectory) }
34
+ subdirectories + subdirectories.collect {|s| s.subdirectories }.flatten
35
+ end
36
+
37
+ end
38
+
39
+ CUCUMBER_NAMESPACE = Requirements.new(:root, "requirements") unless defined?(CUCUMBER_NAMESPACE)
40
+
41
+ CUCUMBER_TAG_NAMESPACE = FeatureTags.new(CUCUMBER_NAMESPACE, "tags") unless defined?(CUCUMBER_TAG_NAMESPACE)
42
+
43
+ CUCUMBER_STEPTRANSFORM_NAMESPACE = StepTransformersObject.new(CUCUMBER_NAMESPACE, "step_transformers") unless defined?(CUCUMBER_STEPTRANSFORM_NAMESPACE)
44
+
45
+ end
@@ -0,0 +1,26 @@
1
+
2
+
3
+ module YARD::CodeObjects::Cucumber
4
+
5
+ class Scenario < NamespaceObject
6
+
7
+ attr_accessor :value, :comments, :keyword, :description, :steps, :tags, :feature
8
+
9
+ def initialize(namespace,name)
10
+ super(namespace,name.to_s.strip)
11
+ @comments = @description = @keyword = @value = @feature = nil
12
+ @steps = []
13
+ @tags = []
14
+ end
15
+
16
+ def background?
17
+ @keyword == "Background"
18
+ end
19
+
20
+ def outline?
21
+ false
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -0,0 +1,66 @@
1
+
2
+
3
+ module YARD::CodeObjects::Cucumber
4
+
5
+ class ScenarioOutline < NamespaceObject
6
+
7
+ attr_accessor :value, :comments, :keyword, :description, :steps, :tags, :feature
8
+ attr_accessor :scenarios, :examples
9
+
10
+ def initialize(namespace,name)
11
+ super(namespace,name.to_s.strip)
12
+ @comments = @description = @value = @feature = nil
13
+ @steps = []
14
+ @tags = []
15
+ @scenarios = []
16
+ @examples = {}
17
+ end
18
+
19
+ def background?
20
+ false
21
+ end
22
+
23
+ def outline?
24
+ true
25
+ end
26
+
27
+ def examples?
28
+ !@examples[:rows].nil?
29
+ end
30
+
31
+ def example_keyword
32
+ @examples[:keyword]
33
+ end
34
+
35
+ def example_headers
36
+ @examples[:rows].first
37
+ end
38
+
39
+ def example_data
40
+ return "" unless @examples[:rows]
41
+ @examples[:rows][1..-1]
42
+ end
43
+
44
+ def example_values_for_row(row)
45
+ hash = {}
46
+
47
+ example_headers.each_with_index do |header,index|
48
+ hash[header] = example_data[row][index]
49
+ end
50
+
51
+ hash
52
+ end
53
+
54
+ def example_hash
55
+ hash = {}
56
+
57
+ @examples[:rows].each_with_index do |header,index|
58
+ hash[header] = @examples[:rows].collect {|row| row[index] }
59
+ end
60
+
61
+ hash
62
+ end
63
+
64
+ end
65
+
66
+ end
@@ -0,0 +1,35 @@
1
+
2
+
3
+ module YARD::CodeObjects::Cucumber
4
+
5
+ class Step < Base
6
+
7
+ attr_accessor :comments, :definition, :examples, :keyword, :scenario, :table, :text, :transforms, :value
8
+
9
+ def initialize(namespace,name)
10
+ super(namespace,name.to_s.strip)
11
+ @comments = @definition = @description = @keyword = @table = @text = @value = nil
12
+ @examples = {}
13
+ @transforms = []
14
+ end
15
+
16
+ def has_table?
17
+ !@table.nil?
18
+ end
19
+
20
+ def has_text?
21
+ !@text.nil?
22
+ end
23
+
24
+ def definition=(stepdef)
25
+ @definition = stepdef
26
+ stepdef.steps << self
27
+ end
28
+
29
+ def transformed?
30
+ !@transforms.empty?
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,27 @@
1
+
2
+
3
+ module YARD::CodeObjects::Cucumber
4
+
5
+ class Tag < NamespaceObject
6
+
7
+ attr_accessor :value, :owners
8
+
9
+ def features
10
+ @owners.find_all{|owner| owner.is_a?(Feature) }
11
+ end
12
+
13
+ def scenarios
14
+ @owners.find_all{|owner| owner.is_a?(Scenario) || owner.is_a?(ScenarioOutline) }
15
+ end
16
+
17
+ def indirect_scenarios
18
+ @owners.find_all{|owner| owner.is_a?(Feature) }.collect {|feature| feature.scenarios }.flatten
19
+ end
20
+
21
+ def all_scenarios
22
+ scenarios + indirect_scenarios
23
+ end
24
+
25
+ end
26
+
27
+ end
@@ -0,0 +1,7 @@
1
+
2
+
3
+ module YARD::CodeObjects
4
+
5
+ class StepDefinitionObject < StepTransformerObject ; end
6
+
7
+ end
@@ -0,0 +1,7 @@
1
+
2
+
3
+ module YARD::CodeObjects
4
+
5
+ class StepTransformObject < StepTransformerObject ; end
6
+
7
+ end
@@ -0,0 +1,51 @@
1
+
2
+ module YARD::CodeObjects
3
+
4
+ class StepTransformerObject < Base
5
+
6
+ include Cucumber::LocationHelper
7
+
8
+ attr_reader :constants, :keyword, :source, :value, :literal_value
9
+ attr_accessor :steps
10
+
11
+ ESCAPE_PATTERN = /#\{\s*(\w+)\s*\}/ unless defined?(ESCAPE_PATTERN)
12
+
13
+ def value=(value)
14
+ @literal_value = format_source(value)
15
+ @value = format_source(value)
16
+
17
+ until (nested = constants_from_value).empty?
18
+ nested.each {|n| @value.gsub!(value_regex(n),find_value_for_constant(n)) }
19
+ end
20
+
21
+ @steps = []
22
+ end
23
+
24
+ def regex
25
+ @regex ||= /#{strip_regex_from(@value)}/
26
+ end
27
+
28
+ def constants_from_value(data=@value)
29
+ data.scan(ESCAPE_PATTERN).flatten.collect { |value| value.strip }
30
+ end
31
+
32
+ protected
33
+
34
+ def find_value_for_constant(name)
35
+ constant = YARD::Registry.all(:constant).find{|c| c.name == name.to_sym }
36
+ log.warn "StepTransformer#find_value_for_constant : Could not find the CONSTANT [#{name}] using the string value." unless constant
37
+ constant ? strip_regex_from(constant.value) : name
38
+ end
39
+
40
+ def value_regex(value)
41
+ /#\{\s*#{value}\s*\}/
42
+ end
43
+
44
+ def strip_regex_from(value)
45
+ value.gsub(/^\/|\/$/,'')
46
+ end
47
+
48
+
49
+ end
50
+
51
+ end
@@ -0,0 +1,22 @@
1
+ module YARD
2
+ module Handlers
3
+ module Cucumber
4
+
5
+ class Base < Handlers::Base
6
+ class << self
7
+ include Parser::Cucumber
8
+ def handles?(node)
9
+ handlers.any? do |a_handler|
10
+ #log.debug "YARD::Handlers::Cucumber::Base#handles?(#{node.class})"
11
+ node.class == a_handler
12
+ end
13
+ end
14
+ include Parser::Cucumber
15
+ end
16
+
17
+ end
18
+
19
+ Processor.register_handler_namespace :feature, Cucumber
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,93 @@
1
+ module YARD
2
+ module Handlers
3
+ module Cucumber
4
+ class FeatureHandler < Base
5
+
6
+ handles CodeObjects::Cucumber::Feature
7
+
8
+ @@step_definitions = nil
9
+ @@step_transforms = nil
10
+
11
+ def process
12
+
13
+ # Create a cache of all of the step definitions and the step transforms
14
+ @@step_definitions = cache(:stepdefinition) unless @@step_definitions
15
+ @@step_transforms = cache(:steptransform) unless @@step_transforms
16
+
17
+ if statement
18
+ # For the background and the scenario, find the steps that have definitions
19
+ process_scenario(statement.background) if statement.background
20
+
21
+ statement.scenarios.each do |scenario|
22
+ if scenario.outline?
23
+ #log.info "Scenario Outline: #{scenario.value}"
24
+ scenario.scenarios.each_with_index do |example,index|
25
+ #log.info " * Processing Example #{index + 1}"
26
+ process_scenario(example)
27
+ end
28
+ else
29
+ process_scenario(scenario)
30
+ end
31
+ end
32
+
33
+
34
+ else
35
+ log.warn "Empty feature file. A feature failed to process correctly or contains no feature"
36
+ end
37
+
38
+ rescue YARD::Handlers::NamespaceMissingError
39
+ rescue Exception => exception
40
+ log.error "Skipping feature because an error has occurred."
41
+ log.debug "\n#{exception}\n#{exception.backtrace.join("\n")}\n"
42
+ end
43
+
44
+ #
45
+ # Store all comparable items with their compare_value as the key and the item as the value
46
+ # - Reject any compare values that contain escapes #{} as that means they have unpacked constants
47
+ #
48
+ def cache(type)
49
+ YARD::Registry.all(type).inject({}) do |hash,item|
50
+ hash[item.regex] = item if item.regex
51
+ hash
52
+ end
53
+ end
54
+
55
+
56
+ def process_scenario(scenario)
57
+ scenario.steps.each {|step| process_step(step) }
58
+ end
59
+
60
+ def process_step(step)
61
+ match_step_to_step_definition_and_transforms(step)
62
+
63
+ end
64
+
65
+ def match_step_to_step_definition_and_transforms(step)
66
+ @@step_definitions.each_pair do |stepdef,stepdef_object|
67
+ stepdef_matches = step.value.match(stepdef)
68
+
69
+ if stepdef_matches
70
+ step.definition = stepdef_object
71
+ stepdef_matches[-1..1].each do |match|
72
+ @@step_transforms.each do |steptrans,steptransform_object|
73
+ if steptrans.match(match)
74
+ step.transforms << steptransform_object
75
+ steptransform_object.steps << step
76
+ end
77
+ end
78
+ end
79
+
80
+ # Step has been matched to step definition and step transforms
81
+ # TODO: If the step were to match again then we would be able to display ambigous step definitions
82
+ break
83
+
84
+ end
85
+
86
+ end
87
+
88
+
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,46 @@
1
+ class YARD::Handlers::Ruby::Legacy::StepDefinitionHandler < YARD::Handlers::Ruby::Legacy::Base
2
+ #TODO: This needs to become language independent.
3
+ STEP_DEFINITION_MATCH = /^((When|Given|And|Then)\s*(\/.+\/)\s+do(?:\s*\|.+\|)?\s*)$/ unless defined?(STEP_DEFINITION_MATCH)
4
+ handles STEP_DEFINITION_MATCH
5
+
6
+ @@unique_name = 0
7
+
8
+ def process
9
+ keyword = statement.tokens.to_s[STEP_DEFINITION_MATCH,2]
10
+ step_definition = statement.tokens.to_s[STEP_DEFINITION_MATCH,3]
11
+
12
+ @@unique_name = @@unique_name + 1
13
+
14
+ stepdef_instance = StepDefinitionObject.new(YARD::CodeObjects::Cucumber::CUCUMBER_STEPTRANSFORM_NAMESPACE, "definition_#{@@unique_name}") do |o|
15
+ o.source = "#{keyword} #{step_definition} do #{statement.block.to_s =~ /^\s*\|.+/ ? '' : "\n "}#{statement.block.to_s}\nend"
16
+ o.value = step_definition
17
+ o.keyword = keyword
18
+ end
19
+
20
+ obj = register stepdef_instance
21
+ parse_block :owner => obj
22
+
23
+ rescue YARD::Handlers::NamespaceMissingError
24
+ end
25
+
26
+ #
27
+ # Step Definitions can contain defined steps within them. While it is likely that they could not
28
+ # very easily be parsed because of variables that are only calculated at runtime, it would be nice
29
+ # to at least list those in use within a step definition and if you can find a match, go ahead and
30
+ # make it
31
+ #
32
+ def find_steps_defined_in_block(block)
33
+ #log.debug "#{block} #{block.class}"
34
+ block.each_with_index do |token,index|
35
+ #log.debug "Token #{token.class} #{token.text}"
36
+ if token.is_a?(YARD::Parser::Ruby::Legacy::RubyToken::TkCONSTANT) &&
37
+ token.text =~ /^(given|when|then|and)$/i &&
38
+ block[index + 2].is_a?(YARD::Parser::Ruby::Legacy::RubyToken::TkSTRING)
39
+ log.debug "Step found in Step Definition: #{block[index + 2].text} "
40
+ end
41
+
42
+ end
43
+
44
+ end
45
+
46
+ end