yard-cucumber 2.0.0
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.
- data/.rspec +3 -0
- data/History.txt +190 -0
- data/README.md +145 -0
- data/Rakefile +17 -0
- data/city.gemspec +66 -0
- data/example/README.md +8 -0
- data/example/child_feature/README.md +21 -0
- data/example/child_feature/child.feature +11 -0
- data/example/child_feature/grandchild_feature/grandchild.feature +12 -0
- data/example/empty.feature +2 -0
- data/example/scenario.feature +63 -0
- data/example/scenario_outline.feature +80 -0
- data/example/step_definitions/example.step.rb +109 -0
- data/example/step_definitions/first.step.rb +21 -0
- data/example/step_definitions/support/env.rb +7 -0
- data/example/step_definitions/support/env_support.rb +12 -0
- data/example/step_definitions/support/support.rb +6 -0
- data/example/tags.feature +18 -0
- data/example/transform.feature +13 -0
- data/lib/cucumber/city_builder.rb +209 -0
- data/lib/docserver/default/fulldoc/html/js/cucumber.js +85 -0
- data/lib/docserver/default/layout/html/headers.erb +13 -0
- data/lib/docserver/doc_server/full_list/html/full_list.erb +37 -0
- data/lib/docserver/doc_server/full_list/html/setup.rb +18 -0
- data/lib/templates/default/feature/html/feature.erb +39 -0
- data/lib/templates/default/feature/html/no_steps_defined.erb +1 -0
- data/lib/templates/default/feature/html/outline.erb +42 -0
- data/lib/templates/default/feature/html/pystring.erb +3 -0
- data/lib/templates/default/feature/html/scenario.erb +55 -0
- data/lib/templates/default/feature/html/setup.rb +55 -0
- data/lib/templates/default/feature/html/steps.erb +39 -0
- data/lib/templates/default/feature/html/table.erb +20 -0
- data/lib/templates/default/featuredirectory/html/alpha_table.erb +26 -0
- data/lib/templates/default/featuredirectory/html/directory.erb +32 -0
- data/lib/templates/default/featuredirectory/html/setup.rb +41 -0
- data/lib/templates/default/featuretags/html/namespace.erb +131 -0
- data/lib/templates/default/featuretags/html/setup.rb +34 -0
- data/lib/templates/default/fulldoc/html/css/common.css +214 -0
- data/lib/templates/default/fulldoc/html/full_list.erb +36 -0
- data/lib/templates/default/fulldoc/html/full_list_features.erb +28 -0
- data/lib/templates/default/fulldoc/html/full_list_stepdefinitions.erb +11 -0
- data/lib/templates/default/fulldoc/html/full_list_steps.erb +13 -0
- data/lib/templates/default/fulldoc/html/full_list_tags.erb +12 -0
- data/lib/templates/default/fulldoc/html/index.erb +24 -0
- data/lib/templates/default/fulldoc/html/js/cucumber.js +314 -0
- data/lib/templates/default/fulldoc/html/setup.rb +72 -0
- data/lib/templates/default/layout/html/headers.erb +14 -0
- data/lib/templates/default/layout/html/search.erb +7 -0
- data/lib/templates/default/requirements/html/alpha_table.erb +26 -0
- data/lib/templates/default/requirements/html/requirements.erb +50 -0
- data/lib/templates/default/requirements/html/setup.rb +51 -0
- data/lib/templates/default/steptransformers/html/header.erb +12 -0
- data/lib/templates/default/steptransformers/html/index.erb +10 -0
- data/lib/templates/default/steptransformers/html/setup.rb +94 -0
- data/lib/templates/default/steptransformers/html/transformers.erb +74 -0
- data/lib/templates/default/steptransformers/html/undefinedsteps.erb +26 -0
- data/lib/templates/default/tag/html/alpha_table.erb +32 -0
- data/lib/templates/default/tag/html/setup.rb +27 -0
- data/lib/templates/default/tag/html/tag.erb +35 -0
- data/lib/yard/code_objects/cucumber/base.rb +32 -0
- data/lib/yard/code_objects/cucumber/feature.rb +18 -0
- data/lib/yard/code_objects/cucumber/namespace_object.rb +45 -0
- data/lib/yard/code_objects/cucumber/scenario.rb +26 -0
- data/lib/yard/code_objects/cucumber/scenario_outline.rb +66 -0
- data/lib/yard/code_objects/cucumber/step.rb +35 -0
- data/lib/yard/code_objects/cucumber/tag.rb +27 -0
- data/lib/yard/code_objects/step_definition.rb +7 -0
- data/lib/yard/code_objects/step_transform.rb +7 -0
- data/lib/yard/code_objects/step_transformer.rb +51 -0
- data/lib/yard/handlers/cucumber/base.rb +22 -0
- data/lib/yard/handlers/cucumber/feature_handler.rb +93 -0
- data/lib/yard/handlers/legacy/step_definition_handler.rb +46 -0
- data/lib/yard/handlers/legacy/step_transform_handler.rb +24 -0
- data/lib/yard/handlers/step_definition_handler.rb +22 -0
- data/lib/yard/handlers/step_transform_handler.rb +23 -0
- data/lib/yard/parser/cucumber/feature.rb +46 -0
- data/lib/yard/parser/source_parser.rb +54 -0
- data/lib/yard/rake/city_task.rb +12 -0
- data/lib/yard/server/adapter.rb +29 -0
- data/lib/yard/server/commands/list_command.rb +25 -0
- data/lib/yard/server/router.rb +31 -0
- data/lib/yard/templates/helpers/base_helper.rb +26 -0
- data/lib/yard-cucumber.rb +53 -0
- 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;"> </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,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
|