cucumber-in-the-yard 1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +3 -0
- data/Manifest +51 -0
- data/README.txt +55 -0
- data/Rakefile +28 -0
- data/cucumber-in-the-yard.gemspec +42 -0
- data/example/example.feature +13 -0
- data/example/example.step.rb +48 -0
- data/example/example.third.feature +30 -0
- data/example/second_example.feature +36 -0
- data/lib/city.rb +23 -0
- data/lib/cucumber/city_builder.rb +130 -0
- data/lib/yard/code_objects/cucumber_location_helper.rb +15 -0
- data/lib/yard/code_objects/feature.rb +24 -0
- data/lib/yard/code_objects/scenario.rb +25 -0
- data/lib/yard/code_objects/step.rb +25 -0
- data/lib/yard/code_objects/tags.rb +63 -0
- data/lib/yard/extensions.rb +38 -0
- data/lib/yard/handlers/base.rb +21 -0
- data/lib/yard/handlers/feature_handler.rb +41 -0
- data/lib/yard/parser/feature.rb +46 -0
- data/lib/yard/rake/city_task.rb +12 -0
- data/lib/yard/rb_extensions.rb +152 -0
- data/lib/yard/templates/default/feature/html/feature.erb +243 -0
- data/lib/yard/templates/default/feature/setup.rb +5 -0
- data/lib/yard/templates/default/fulldoc/html/css/common.css +182 -0
- data/lib/yard/templates/default/fulldoc/html/full_list.erb +34 -0
- data/lib/yard/templates/default/fulldoc/html/full_list_features.erb +10 -0
- data/lib/yard/templates/default/fulldoc/html/full_list_scenarios.erb +10 -0
- data/lib/yard/templates/default/fulldoc/html/full_list_stepdefinitions.erb +11 -0
- data/lib/yard/templates/default/fulldoc/html/full_list_steps.erb +13 -0
- data/lib/yard/templates/default/fulldoc/html/full_list_tagusages.erb +10 -0
- data/lib/yard/templates/default/fulldoc/html/index.erb +24 -0
- data/lib/yard/templates/default/fulldoc/html/js/cucumber.js +13 -0
- data/lib/yard/templates/default/fulldoc/html/setup.rb +73 -0
- data/lib/yard/templates/default/layout/html/headers.erb +14 -0
- data/lib/yard/templates/default/layout/html/search.erb +8 -0
- data/lib/yard/templates/default/module/html/step_transforms.erb +23 -0
- data/lib/yard/templates/default/module/setup.rb +5 -0
- data/lib/yard/templates/default/scenario/html/scenario.erb +26 -0
- data/lib/yard/templates/default/scenario/setup.rb +5 -0
- data/lib/yard/templates/default/steptransformers/html/stepdefinition.erb +38 -0
- data/lib/yard/templates/default/steptransformers/setup.rb +5 -0
- data/lib/yard/templates/default/tagusage/html/tagusage.erb +65 -0
- data/lib/yard/templates/default/tagusage/setup.rb +5 -0
- data/spec/city/feature_parser_spec_examples.rb +153 -0
- data/spec/city/gherkin_loader_spec.rb +39 -0
- data/spec/city/test.feature +36 -0
- data/spec/city/yard_handlers_cucumber_spec.rb +24 -0
- data/spec/city/yard_namespace_object_spec.rb +8 -0
- data/spec/city/yard_parser_cucumber_spec.rb +215 -0
- data/spec/city/yard_rb_extensions_spec.rb +128 -0
- data/spec/spec_helper.rb +5 -0
- data.tar.gz.sig +0 -0
- metadata +201 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,38 @@
|
|
1
|
+
|
2
|
+
module YARD::CodeObjects
|
3
|
+
|
4
|
+
NamespaceObject.class_eval do
|
5
|
+
|
6
|
+
attr_accessor :features
|
7
|
+
|
8
|
+
def features(opts = {})
|
9
|
+
children.select {|child| child.type == :feature }
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_accessor :scenarios
|
13
|
+
|
14
|
+
def scenarios(opts = {})
|
15
|
+
children.select {|child| child.type == :scenario }
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_accessor :steps
|
19
|
+
|
20
|
+
def steps(opts = {})
|
21
|
+
children.select {|child| child.type == :step }
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_accessor :step_definitions
|
25
|
+
|
26
|
+
def step_definitions(opts = {})
|
27
|
+
children.select {|child| child.type == :stepdefinition }
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_accessor :step_transforms
|
31
|
+
|
32
|
+
def step_transforms(opts = {})
|
33
|
+
children.select {|child| child.type == :steptransform }
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,21 @@
|
|
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?"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
include Parser::Cucumber
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
|
18
|
+
Processor.register_handler_namespace :feature, Cucumber
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module YARD
|
2
|
+
module Handlers
|
3
|
+
module Cucumber
|
4
|
+
|
5
|
+
class FeatureHandler < Base
|
6
|
+
|
7
|
+
handles CodeObjects::Cucumber::Feature
|
8
|
+
|
9
|
+
def process
|
10
|
+
|
11
|
+
# For the background and the scenario, find the steps that have definitions
|
12
|
+
process_scenario(statement.background) if statement.background
|
13
|
+
|
14
|
+
statement.scenarios.each do |scenario|
|
15
|
+
process_scenario(scenario)
|
16
|
+
end
|
17
|
+
|
18
|
+
rescue YARD::Handlers::NamespaceMissingError
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def process_scenario(scenario)
|
23
|
+
scenario.steps.each do |step|
|
24
|
+
owner.step_definitions.each do |stepdef|
|
25
|
+
if %r{#{stepdef.compare_value}}.match(step.value)
|
26
|
+
step.definition = stepdef
|
27
|
+
stepdef.steps << step
|
28
|
+
log.info "STEP #{step} has found its definition #{stepdef}"
|
29
|
+
break
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module YARD::Parser::Cucumber
|
2
|
+
|
3
|
+
class FeatureParser < YARD::Parser::Base
|
4
|
+
|
5
|
+
def initialize(source, file = '(stdin)')
|
6
|
+
|
7
|
+
@builder = Cucumber::Parser::CityBuilder.new(file)
|
8
|
+
@tag_counts = {}
|
9
|
+
@tag_formatter = Gherkin::Formatter::TagCountFormatter.new(@builder, @tag_counts)
|
10
|
+
@parser = Gherkin::Parser::Parser.new(@tag_formatter, true, "root", false)
|
11
|
+
|
12
|
+
@source = source
|
13
|
+
@file = file
|
14
|
+
|
15
|
+
@feature = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def parse
|
19
|
+
begin
|
20
|
+
@parser.parse(@source, @file, 0)
|
21
|
+
@feature = @builder.ast
|
22
|
+
return nil if @feature.nil? # Nothing matched
|
23
|
+
@feature.language = @parser.i18n_language
|
24
|
+
rescue Gherkin::Lexer::LexingError, Gherkin::Parser::ParseError => e
|
25
|
+
e.message.insert(0, "#{@file}: ")
|
26
|
+
raise e
|
27
|
+
end
|
28
|
+
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
def tokenize
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
def enumerator
|
38
|
+
[@feature]
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
YARD::Parser::SourceParser.register_parser_type :feature, FeatureParser, 'feature'
|
45
|
+
|
46
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
|
2
|
+
module YARD::CodeObjects
|
3
|
+
|
4
|
+
|
5
|
+
#
|
6
|
+
# StepDefinitions, as implemented in a ruby file
|
7
|
+
#
|
8
|
+
class StepDefinitionObject < Base
|
9
|
+
|
10
|
+
attr_reader :keyword, :value, :compare_value, :source
|
11
|
+
attr_accessor :constants, :steps
|
12
|
+
|
13
|
+
def value=(value)
|
14
|
+
@value = format_source(value)
|
15
|
+
@constants = {}
|
16
|
+
@steps = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def compare_value
|
20
|
+
base_value = value.gsub(/^\/|\/$/,'')
|
21
|
+
@constants.each do |name,value|
|
22
|
+
base_value.gsub!(/\#\{\s*#{name.to_s}\s*\}/,value.gsub(/^\/|\/$/,''))
|
23
|
+
end
|
24
|
+
base_value
|
25
|
+
end
|
26
|
+
|
27
|
+
def _value_constants(data=@value)
|
28
|
+
#Hash[*data.scan(/\#\{([^\}]+)\}/).flatten.collect {|value| [value.strip,nil]}.flatten]
|
29
|
+
data.scan(/\#\{([^\}]+)\}/).flatten.collect { |value| value.strip }
|
30
|
+
end
|
31
|
+
|
32
|
+
def constants=(value)
|
33
|
+
value.each do |val|
|
34
|
+
@constants[val.name.to_s] = val if val.respond_to?(:name) && val.respond_to?(:value)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
class StepTransformersObject < Base
|
41
|
+
|
42
|
+
attr_reader :source
|
43
|
+
attr_accessor :definitions, :transforms
|
44
|
+
|
45
|
+
def push(stepobject)
|
46
|
+
if stepobject.is_a?(StepDefinitionObject)
|
47
|
+
@definitions = [] unless @definitions
|
48
|
+
@definitions << stepobject
|
49
|
+
elsif stepobject.ia_a?(StepTransformObject)
|
50
|
+
@transforms = [] unless @transforms
|
51
|
+
@transforms << stepobject
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
alias_method :<< , :push
|
56
|
+
|
57
|
+
def filename
|
58
|
+
"#{name}.html"
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
#
|
65
|
+
# Transforms
|
66
|
+
#
|
67
|
+
class StepTransformObject < Base
|
68
|
+
attr_reader :value
|
69
|
+
|
70
|
+
def value=(value)
|
71
|
+
@value = format_source(value)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
|
81
|
+
class StepDefinitionHandler < YARD::Handlers::Ruby::Legacy::Base
|
82
|
+
MATCH = /^((When|Given|And|Then)\s*(\/[^\/]+\/).+)$/
|
83
|
+
handles MATCH
|
84
|
+
|
85
|
+
@@unique_name = 0
|
86
|
+
|
87
|
+
def process
|
88
|
+
|
89
|
+
keyword = statement.tokens.to_s[MATCH,2]
|
90
|
+
step_definition = statement.tokens.to_s[MATCH,3]
|
91
|
+
@@unique_name = @@unique_name + 1
|
92
|
+
|
93
|
+
stepdef_instance = StepDefinitionObject.new(namespace, "StepDefinition_#{@@unique_name}") {|o| o.source = statement.block.to_s ; o.value = step_definition ; o.keyword = keyword}
|
94
|
+
|
95
|
+
begin
|
96
|
+
# Look for all constants within the step definitions
|
97
|
+
stepdef_instance.constants = stepdef_instance._value_constants.each do |stepdef_constant|
|
98
|
+
owner.constants.each do |constant|
|
99
|
+
if stepdef_constant.to_sym == constant.name
|
100
|
+
log.info "Replacing #{constant.name} with its value in the step definition #{stepdef_instance.value}"
|
101
|
+
stepdef_instance.constants[constant.name] = unpack_constants(constant.value)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
rescue Exception => e
|
107
|
+
log.error "Failed to link step definition to constants. This will make step definition to step linking impossible if constants are present. #{e}"
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
obj = register stepdef_instance
|
112
|
+
|
113
|
+
|
114
|
+
parse_block :owner => obj
|
115
|
+
rescue YARD::Handlers::NamespaceMissingError
|
116
|
+
end
|
117
|
+
|
118
|
+
|
119
|
+
def unpack_constants(constant_value)
|
120
|
+
constant_value.scan(/\#\{([^\}]+)\}/).flatten.collect { |value| value.strip }.each do |inner_constant|
|
121
|
+
inner_constant_match = owner.constants.find {|constant| constant.name.to_s == inner_constant }
|
122
|
+
if inner_constant_match
|
123
|
+
constant_value.gsub!(/\#\{#{inner_constant}\}/,unpack_constants(inner_constant_match.value))
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
constant_value.gsub!(/^('|"|\/)|('|"|\/)$/,'')
|
128
|
+
constant_value
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
class StepTransformHandler < YARD::Handlers::Ruby::Legacy::Base
|
135
|
+
MATCH = /^Transform\s*(\/[^\/]+\/).+$/
|
136
|
+
handles MATCH
|
137
|
+
|
138
|
+
@@unique_name = 0
|
139
|
+
|
140
|
+
def process
|
141
|
+
transformDefinition = statement.tokens.to_s[MATCH,1]
|
142
|
+
#log.debug "#process - transformDefinition = #{transformDefinition}"
|
143
|
+
@@unique_name = @@unique_name + 1
|
144
|
+
|
145
|
+
obj = register StepTransformObject.new(namespace, "StepTransform_#{@@unique_name}") {|o| o.source = statement.block.to_s ; o.value = transformDefinition }
|
146
|
+
|
147
|
+
parse_block :owner => obj
|
148
|
+
|
149
|
+
rescue YARD::Handlers::NamespaceMissingError
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
@@ -0,0 +1,243 @@
|
|
1
|
+
<div class="feature">
|
2
|
+
<div class="title">
|
3
|
+
<span class="pre"><%= @feature.keyword %>:</span>
|
4
|
+
<span class="name"><%= @feature.value %></span>
|
5
|
+
</div>
|
6
|
+
|
7
|
+
<div class="meta">
|
8
|
+
<div class="file"><%= h(@feature.file) %></div>
|
9
|
+
<div class="tags">
|
10
|
+
<% @feature.tags.each do |tag| %>
|
11
|
+
<a href="tag_<%= tag.value %>.html"><%= tag.value %></a>
|
12
|
+
<% end %>
|
13
|
+
</div>
|
14
|
+
</div>
|
15
|
+
|
16
|
+
<div class="description">
|
17
|
+
<%= @feature.description %>
|
18
|
+
</div>
|
19
|
+
|
20
|
+
<% if @feature.background %>
|
21
|
+
|
22
|
+
<script type="text/javascript" charset="utf-8">
|
23
|
+
$(function() {
|
24
|
+
$('#background .toggle').click(function() {
|
25
|
+
$("#backgroundSteps").toggle('blind');
|
26
|
+
|
27
|
+
var stateIndicator = $('#background a.toggle')[0]
|
28
|
+
|
29
|
+
stateIndicator.innerHTML = (stateIndicator.innerHTML === '+' ? '-' : '+');
|
30
|
+
return false;
|
31
|
+
});
|
32
|
+
});
|
33
|
+
</script>
|
34
|
+
|
35
|
+
<div id="background">
|
36
|
+
<div class="title">
|
37
|
+
<a class="toggle">-</a>
|
38
|
+
<span class="pre">Background</span>
|
39
|
+
</div>
|
40
|
+
<% unless @feature.background.description.empty? %>
|
41
|
+
<div class="description">
|
42
|
+
<%= h(@feature.background.description.join("\n<br/>")) %>
|
43
|
+
</div>
|
44
|
+
<% end %>
|
45
|
+
|
46
|
+
<!-- Background and scenario should have the same display with some minor changes -->
|
47
|
+
|
48
|
+
<div id="backgroundSteps" class="steps">
|
49
|
+
<% if @feature.background.steps %>
|
50
|
+
<% @feature.background.steps.each_with_index do |step,index| %>
|
51
|
+
<div <%= "id='backgroundStep#{index}'" %> class="step <%= (index + 1) % 2 == 0 ? 'even' : 'odd' %>">
|
52
|
+
<span class="predicate"><%= step.keyword %></span>
|
53
|
+
|
54
|
+
<% if step.definition %>
|
55
|
+
<script type="text/javascript" charset="utf-8">
|
56
|
+
$('<%= "#backgroundStep#{index}" %>').hover(
|
57
|
+
function () { $('<%= "#backgroundStep#{index} div.details" %>').toggle('slide'); },
|
58
|
+
function () { $('<%= "#backgroundStep#{index} div.details" %>').toggle('slide'); }
|
59
|
+
);
|
60
|
+
|
61
|
+
$('<%= "#backgroundStep#{index} div.details" %>').show();
|
62
|
+
|
63
|
+
</script>
|
64
|
+
<span class="defined">
|
65
|
+
<a href="steptransformers.html#<%= step.definition.name %>"><%= h(step.value) %></a>
|
66
|
+
<div class="details" style="display: none;">
|
67
|
+
(<%= h("#{step.definition.files.first.first}:#{step.definition.files.first.last}") %>)
|
68
|
+
</div>
|
69
|
+
</span>
|
70
|
+
<% else %>
|
71
|
+
<span class="undefined"><%= h(step.value) %></span>
|
72
|
+
<% end %>
|
73
|
+
|
74
|
+
<% if step.has_text? %>
|
75
|
+
<div class="text">
|
76
|
+
<%= h(step.text) %>
|
77
|
+
</div>
|
78
|
+
<% end %>
|
79
|
+
|
80
|
+
<% if step.has_table? %>
|
81
|
+
<div class="multiline">
|
82
|
+
<table style="">
|
83
|
+
|
84
|
+
<thead>
|
85
|
+
<tr>
|
86
|
+
<% step.table.each_with_index do |column,column_index| %>
|
87
|
+
<th class="<%= (column_index + 1) % 2 == 0 ? 'even' : 'odd' %>"><%= h(column.to_s.strip) %></td>
|
88
|
+
<% end %>
|
89
|
+
</tr>
|
90
|
+
</thead>
|
91
|
+
|
92
|
+
<% step.table[1..-1].each do |row| %>
|
93
|
+
<tr>
|
94
|
+
<% row.split("|").each_with_index do |column,column_index| %>
|
95
|
+
<td class="<%= (column_index + 1) % 2 == 0 ? 'even' : 'odd' %>"><%= h(column.to_s.strip) %></td>
|
96
|
+
<% end %>
|
97
|
+
</tr>
|
98
|
+
<% end %>
|
99
|
+
</table>
|
100
|
+
</div>
|
101
|
+
|
102
|
+
<% end %>
|
103
|
+
|
104
|
+
</div>
|
105
|
+
|
106
|
+
<% end %>
|
107
|
+
<% else %>
|
108
|
+
<span>No Steps Defined</span>
|
109
|
+
<% end %>
|
110
|
+
</div>
|
111
|
+
|
112
|
+
</div>
|
113
|
+
<% end %>
|
114
|
+
|
115
|
+
<% if @feature.scenarios %>
|
116
|
+
<% @feature.scenarios.each_with_index do |scenario,scenario_index| %>
|
117
|
+
|
118
|
+
<script type="text/javascript" charset="utf-8">
|
119
|
+
$(function() {
|
120
|
+
$('#scenario<%=scenario_index%> .toggle').click(function() {
|
121
|
+
$("#scenario<%=scenario_index%>Steps").toggle('blind');
|
122
|
+
|
123
|
+
var stateIndicator = $('#scenario<%=scenario_index%> a.toggle')[0]
|
124
|
+
|
125
|
+
stateIndicator.innerHTML = (stateIndicator.innerHTML === '+' ? '-' : '+');
|
126
|
+
return false;
|
127
|
+
});
|
128
|
+
});
|
129
|
+
</script>
|
130
|
+
|
131
|
+
<div <%= "id='scenario#{scenario_index}'" %> class="scenario">
|
132
|
+
<div class="title">
|
133
|
+
<a class="toggle">-</a>
|
134
|
+
<span class="pre">Scenario<%= !scenario.examples.empty? ? " Outline" : "" %>:</span>
|
135
|
+
<span class="name"><%= h(scenario.value) %></span>
|
136
|
+
</div>
|
137
|
+
<div class="meta">
|
138
|
+
<div class="file">Line: <%= scenario.files.first.last %></div>
|
139
|
+
<% unless scenario.tags.empty? %>
|
140
|
+
<div class="tags">
|
141
|
+
<% scenario.tags.each do |tag| %>
|
142
|
+
<a href="tag_<%= tag.value %>.html"><%= tag.value %></a>
|
143
|
+
<% end %>
|
144
|
+
</div>
|
145
|
+
<% end%>
|
146
|
+
</div>
|
147
|
+
<% unless scenario.description.empty? %>
|
148
|
+
<div class="description">
|
149
|
+
<%= h(scenario.description.join("\n<br/>")) %>
|
150
|
+
</div>
|
151
|
+
<% end %>
|
152
|
+
|
153
|
+
<div <%= "id='scenario#{scenario_index}Steps'" %> class="steps">
|
154
|
+
<% if scenario.steps %>
|
155
|
+
<% scenario.steps.each_with_index do |step,index| %>
|
156
|
+
<div <%= "id='scenario#{scenario_index}Step#{index}'" %> class="step <%= (index + 1) % 2 == 0 ? 'even' : 'odd' %>">
|
157
|
+
<span class="predicate"><%= step.keyword %></span>
|
158
|
+
|
159
|
+
<% if step.definition %>
|
160
|
+
<script type="text/javascript" charset="utf-8">
|
161
|
+
$('<%= "#scenario#{scenario_index}Step#{index}" %>').hover(
|
162
|
+
function () { $('<%= "#scenario#{scenario_index}Step#{index} div.details" %>').toggle('slide'); },
|
163
|
+
function () { $('<%= "#scenario#{scenario_index}Step#{index} div.details" %>').toggle('slide'); }
|
164
|
+
);
|
165
|
+
|
166
|
+
$('<%= "#scenario#{scenario_index}Step#{index} div.details" %>').show();
|
167
|
+
|
168
|
+
</script>
|
169
|
+
<span class="defined">
|
170
|
+
<a href="steptransformers.html#<%= step.definition.name %>"><%= h(step.value) %></a>
|
171
|
+
<div class="details" style="display: none;">
|
172
|
+
(<%= h("#{step.definition.files.first.first}:#{step.definition.files.first.last}") %>)
|
173
|
+
</div>
|
174
|
+
</span>
|
175
|
+
<% else %>
|
176
|
+
<span class="undefined"><%= h(step.value) %></span>
|
177
|
+
<% end %>
|
178
|
+
|
179
|
+
<% if step.has_text? %>
|
180
|
+
<div class="text">
|
181
|
+
<%= h(step.text) %>
|
182
|
+
</div>
|
183
|
+
<% end %>
|
184
|
+
|
185
|
+
<% if step.has_table? %>
|
186
|
+
<div class="multiline">
|
187
|
+
<table style="">
|
188
|
+
|
189
|
+
<thead>
|
190
|
+
<tr>
|
191
|
+
<% step.table.first.each_with_index do |column,column_index| %>
|
192
|
+
<th class="<%= (column_index + 1) % 2 == 0 ? 'even' : 'odd' %>"><%= h(column.strip) %></td>
|
193
|
+
<% end %>
|
194
|
+
</tr>
|
195
|
+
</thead>
|
196
|
+
|
197
|
+
<% step.table[1..-1].each do |row| %>
|
198
|
+
<tr>
|
199
|
+
<% row.each_with_index do |column,column_index| %>
|
200
|
+
<td class="<%= (column_index + 1) % 2 == 0 ? 'even' : 'odd' %>"><%= h(column.strip) %></td>
|
201
|
+
<% end %>
|
202
|
+
</tr>
|
203
|
+
<% end %>
|
204
|
+
</table>
|
205
|
+
</div>
|
206
|
+
|
207
|
+
<% end %>
|
208
|
+
|
209
|
+
|
210
|
+
</div>
|
211
|
+
|
212
|
+
<% end %>
|
213
|
+
<% else %>
|
214
|
+
<span>No Steps Defined</span>
|
215
|
+
<% end %>
|
216
|
+
</div>
|
217
|
+
|
218
|
+
<% if scenario.examples && !scenario.examples.empty? %>
|
219
|
+
<div class="outline">
|
220
|
+
<table>
|
221
|
+
<thead>
|
222
|
+
<tr>
|
223
|
+
<th class="odd" colspan="10"><%= h(scenario.examples.first.first.to_s.strip) %></td>
|
224
|
+
</tr>
|
225
|
+
</thead>
|
226
|
+
<% scenario.examples.first.find {|example| example.is_a?(Array) }.each_with_index do |row,row_index| %>
|
227
|
+
<tr>
|
228
|
+
<% row.each do |column| %>
|
229
|
+
<td class="<%= (row_index + 1) % 2 == 0 ? 'even' : 'odd' %>"><%= h(column.to_s.strip) %></td>
|
230
|
+
<% end %>
|
231
|
+
</tr>
|
232
|
+
<% end %>
|
233
|
+
</table>
|
234
|
+
</div>
|
235
|
+
|
236
|
+
<% end %>
|
237
|
+
|
238
|
+
</div>
|
239
|
+
<% end %>
|
240
|
+
<% end %>
|
241
|
+
|
242
|
+
</div>
|
243
|
+
|