cucumber-in-the-yard 1.7.2 → 1.7.3

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 (31) hide show
  1. data/History.txt +12 -0
  2. data/README.md +22 -0
  3. data/example/child_feature/child.feature +11 -0
  4. data/example/child_feature/grandchild_feature/grandchild.feature +12 -0
  5. data/example/scenario.feature +23 -13
  6. data/example/scenario_outline.feature +26 -6
  7. data/lib/city.rb +1 -1
  8. data/lib/cucumber/city_builder.rb +2 -2
  9. data/lib/templates/default/feature/html/feature.erb +24 -18
  10. data/lib/templates/default/feature/html/outline.erb +21 -6
  11. data/lib/templates/default/feature/html/pystring.erb +1 -1
  12. data/lib/templates/default/feature/html/scenario.erb +3 -2
  13. data/lib/templates/default/feature/html/steps.erb +1 -1
  14. data/lib/templates/default/feature/setup.rb +4 -0
  15. data/lib/templates/default/featuredirectory/html/setup.rb +1 -0
  16. data/lib/templates/default/featuretags/html/namespace.erb +68 -34
  17. data/lib/templates/default/featuretags/html/setup.rb +4 -3
  18. data/lib/templates/default/fulldoc/html/css/common.css +40 -25
  19. data/lib/templates/default/fulldoc/html/full_list.erb +2 -0
  20. data/lib/templates/default/fulldoc/html/js/cucumber.js +60 -32
  21. data/lib/templates/default/fulldoc/html/setup.rb +1 -1
  22. data/lib/templates/default/requirements/html/setup.rb +3 -0
  23. data/lib/templates/default/steptransformers/html/header.erb +5 -5
  24. data/lib/templates/default/steptransformers/html/transformers.erb +55 -49
  25. data/lib/templates/default/steptransformers/html/undefined_steps.erb +12 -6
  26. data/lib/templates/default/steptransformers/setup.rb +6 -0
  27. data/lib/yard/code_objects/cucumber/feature.rb +2 -2
  28. data/lib/yard/code_objects/cucumber/scenario_outline.rb +6 -1
  29. metadata +16 -10
  30. data/example/child_feature/grandchild_feature/scenario.feature +0 -52
  31. data/example/child_feature/scenario.feature +0 -57
@@ -21,13 +21,14 @@ def tags
21
21
  end
22
22
 
23
23
  def features
24
- @features ||= Registry.all(:feature).sort {|x,y| x.value <=> y.value }
24
+ @features ||= Registry.all(:feature).sort {|x,y| x.value.to_s <=> y.value.to_s }
25
25
  end
26
26
 
27
- def scenarios
28
- @scenarios ||= features.collect {|f| f.scenarios.reject {|s| s.background? } }.flatten.sort {|x,y| x.value <=> y.value }
27
+ def feature_tags_with_all_scenario_tags(feature)
28
+ feature.tags.collect {|t| t.value} + feature.scenarios.collect {|s| s.tags.collect {|t| t.value} }.flatten.uniq
29
29
  end
30
30
 
31
+
31
32
  def tagify(tag)
32
33
  %{<span class="tag" href="#{url_for tag}">#{tag.value}</span>}
33
34
  end
@@ -4,10 +4,12 @@
4
4
  .tags { font-family: monospace; font-size: 14px; }
5
5
  .title { padding: 10px; font-size: 24px; }
6
6
 
7
- #view, #expand { float: right; font-size: 13px; color: gray; vertical-align: bottom; }
8
- .control { float: right; font-size: 13px; color: gray; vertical-align: bottom; font-family: monospace; font-size: 14px; cursor: pointer; }
7
+ .control { float: right; font-size: 13px; color: #05A; vertical-align: bottom; font-family: monospace; font-size: 14px; cursor: pointer; }
8
+
9
+ .title { margin: 20px 20px 10px 20px; padding-left: 0px; border-bottom: 1px solid #E3E3E3; }
10
+ .noborder { border: none; }
11
+ #header * .title { padding: 10px; margin: 0px; border: none; }
9
12
 
10
- .title { margin: 20px 20px 10px 20px; padding-left: 0px; border-bottom: 1px solid #E3E3E3; }
11
13
  .meta .file { float: right; margin-top: 5px; margin-right: 20px; }
12
14
  .title .pre { color: #696969; }
13
15
  .title .name { font-weight: bold; color: #3F3F3F; }
@@ -16,11 +18,14 @@
16
18
  .scenario .meta .tags { margin-left: 0px; }
17
19
  .feature .meta .tags { float: right; margin-right: 20px; }
18
20
 
21
+ .suggestion { color: #ff686e; }
22
+
19
23
 
20
24
  .feature .description, .requirements .summary {
21
25
  margin: 10px 20px 0px 30px;
22
26
  padding: 10px 20px 20px 10px;
23
27
  color: #343332;
28
+ font-size: 16px;
24
29
  font-family: 'Trebuchet MS', Arial, Helvetica;
25
30
  }
26
31
 
@@ -44,6 +49,10 @@
44
49
  padding: 6px 10px; margin-top: 18px;
45
50
  background: #e5e8ff; border: 1px solid #d8d8e5; -moz-border-radius: 3px; -webkit-border-radius: 3px;
46
51
  }
52
+ .nodefinitions .title {
53
+ background-color: #F5EADD; border: 1px solid #d8d8e5; -moz-border-radius: 3px; -webkit-border-radius: 3px;
54
+ }
55
+
47
56
  .scenario .title { border: none; }
48
57
  .background .title { background: #cbddeb; }
49
58
 
@@ -86,11 +95,11 @@
86
95
 
87
96
  .comments { margin-left: 25px; color: gray; padding: 5px; font-size: 13px; }
88
97
  .scenario .steps .comments { margin-left: 0px; }
89
-
98
+ .feature .comments { margin-left: 30px; padding: 10px 20px 20px 10px; }
90
99
 
91
100
  .step .predicate { color: #5D5C5B; }
92
-
93
101
  .step .defined {}
102
+ div.undefined { padding: 6px; }
94
103
  .step .definition { float: right; color: #343332; }
95
104
  .step .details .pre {}
96
105
  .step .details .name { font-family: monospace; color: black; }
@@ -104,6 +113,7 @@
104
113
  border: 1px solid #DEDEDE;
105
114
  }
106
115
 
116
+ /* Scenario Outline Table */
107
117
  .outline {
108
118
  margin-top: 20px;
109
119
  margin-left: 40px;
@@ -114,7 +124,6 @@
114
124
  font-size: 16px;
115
125
  }
116
126
 
117
-
118
127
  .multiline table tr, .outline table tr {
119
128
  padding: 4px;
120
129
  }
@@ -128,7 +137,8 @@
128
137
  padding: 4px 10px 4px 10px;
129
138
  }
130
139
 
131
- /* tag page */
140
+
141
+ /* Tag page */
132
142
  #tags #features, #tags #scenarios { margin-right: 20px;}
133
143
  #tags * .tag { font-family: monospace; font-size: 14px; cursor: pointer; }
134
144
 
@@ -137,39 +147,46 @@
137
147
  .tag .scenario { margin-top: 0px; margin-left: 20px; padding-left: 30px; }
138
148
  .tag .scenario .title { border-bottom: none; }
139
149
  .tag .scenario .meta { margin-top: 0px; }
140
- /* Overrides for scenarios in the tag view */
141
-
142
150
 
143
151
 
152
+ /* Step Transformer Page */
153
+ .transformer { margin-top: 20px; }
144
154
  .transformer * .docstring { margin-left: 20px; margin-top: 10px; padding: 5px 5px 5px 10px; }
145
- .transformer .steps, .method_details_list, .steps, .method_details_list {
146
- margin: 10px 20px 0px 30px;
147
- }
148
- .transformer .steps .step { padding: 4px; }
149
-
155
+ .transformer .steps, .method_details_list, .steps, .method_details_list { margin: 10px 20px 0px 30px; }
156
+ .transformer .steps .step { padding: 6px; font-size: 14px; }
150
157
 
151
158
 
159
+ /* Tag Search Page */
152
160
  #tags * li { padding: 5px; padding-left: 12px; margin: 0 0 0 10px; font-size: 1.1em; list-style: none; }
153
-
154
161
  #tag_search { margin: 10px 0px 10px 0px; width: 100%; min-width: 200px; height: 20px; }
155
162
  #tag_filtering {
156
- margin: 10px 20px 0px 40px;
163
+ margin: 10px 20px 0px 30px;
157
164
  font-weight: bold;
158
165
  padding: 20px;
159
166
  background-color: #F8F8FF;
160
167
  color: #444444;
161
- border: 1px solid #DEDEDE;
168
+ border: 1px solid #DEDEDE; -moz-border-radius: 3px; -webkit-border-radius: 3px;
162
169
  }
163
- #command_example { margin-top: 10px; margin-left: 10px; font-weight: normal; }
164
170
 
171
+ #command_example {
172
+ margin-top: 10px;
173
+ margin-left: 0px;
174
+ font-size: 1.1em; font-weight: normal; font-family: Monaco, Consolas, Courier, monospace;
175
+ color: #333;
176
+ padding: 8px 10px;
177
+ background: #A8E795; border: 1px solid #d8d8e5; -moz-border-radius: 3px; -webkit-border-radius: 3px;
178
+ }
165
179
 
166
180
 
167
- #cukes_links { margin: 10px auto 10px auto;
168
- border-bottom: 1px solid #E3E3E3;
169
- width: 762px; text-align: center;
170
- padding: 10px;
181
+ #cukes_links {
182
+ margin: 10px auto 10px auto;
183
+ border-bottom: 1px solid #E3E3E3;
184
+ width: 762px; text-align: center;
185
+ padding: 10px;
171
186
  }
172
187
 
188
+ /* Logo Image and Step Status Images */
189
+
173
190
  #cukes_logo {
174
191
  margin: 0px auto 10px auto;
175
192
  width: 762px;
@@ -188,6 +205,4 @@
188
205
  width: 15px;
189
206
  height: 15px;
190
207
  background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAIAAAC0tAIdAAAACXBIWXMAAA86AAAPOgGXOdvCAAABWUlEQVQoFS2SvVEEMQyFJdkspFcCVAAVUREZXVAHHRAwZOQwQ3YM67X4nnwe3+3afn+S18/P9366s5yZ042R6c3c3bRKDw+WwZxf791Pt/3hMcev5QBpFtauPLoBYrYr6zcem/Xr8frUbc4c59zPPoekQeSesTm47IaD74kfTjnDbNqxC5pTzrJfQcCFBQClIh7bIdDc9S+6E8WIQXTl9somfA1S4iJVbUnJmyOhJT+51AMRkXVArMtBdUNLGcpmaReDdSIGHw4m2iyNIiMslTWqBvMuZSVZB4QhMRRp6IUjzYuPctvq3TpWumq2sIfNw/KQ3DwomfIv6aVBT+ZQMFKxhB8uLfhlzkO3Sstlwh1ja3+oEKVuqipGHhMztEGvvlZEQHwyMKPD1NDtrrpBR3jbalv90hWzo05FBr1vlKGXtvGF9fz5HG8vFRpK1a5yV0/KVuZSzO+Pf3G6tVs/+L00AAAAAElFTkSuQmCC) no-repeat center;
191
- }
192
-
193
- .conflicted {}
208
+ }
@@ -19,6 +19,8 @@
19
19
  <div id="content">
20
20
  <h1 id="full_list_header"><%= @list_title %></h1>
21
21
  <div id="nav">
22
+ <a target="_self" href="feature_list.html">Features</a> |
23
+ <a target="_self" href="tag_list.html">Tags</a> |
22
24
  <a target="_self" href="class_list.html">Classes</a> |
23
25
  <a target="_self" href="method_list.html">Methods</a> |
24
26
  <a target="_self" href="file_list.html">Files</a>
@@ -7,7 +7,22 @@ function cucumberSearchFrameLinks() {
7
7
  });
8
8
  }
9
9
 
10
+ function cucumberKeyboardShortcuts() {
11
+ if (window.top.frames.main) return;
12
+ $(document).keypress(function(evt) {
13
+ if (evt.altKey || evt.ctrlKey || evt.metaKey || evt.shiftKey) return;
14
+ if (typeof evt.orignalTarget !== "undefined" &&
15
+ (evt.originalTarget.nodeName == "INPUT" ||
16
+ evt.originalTarget.nodeName == "TEXTAREA")) return;
17
+ switch (evt.charCode) {
18
+ case 82: case 114: $('#features_list_link').click(); break; // 'r'
19
+ case 84: case 116: $('#tags_list_link').click(); break; // 't'
20
+ }
21
+ });
22
+ }
23
+
10
24
  $(cucumberSearchFrameLinks);
25
+ $(cucumberKeyboardShortcuts);
11
26
 
12
27
 
13
28
  $(function() {
@@ -92,6 +107,11 @@ $(function() {
92
107
 
93
108
  if (typeof eventObject.currentTarget !== "undefined") {
94
109
  var exampleRow = $(eventObject.currentTarget);
110
+
111
+ if (eventObject.currentTarget.className.match(/example\d+/) == null) {
112
+ return false;
113
+ }
114
+
95
115
  var exampleClass = eventObject.currentTarget.className.match(/example\d+/)[0];
96
116
  var example = exampleRow.closest('div.details').find('.' + exampleClass);
97
117
 
@@ -151,21 +171,24 @@ function updateTagFiltering(tagString) {
151
171
  var formulaTags = determineTagsUsedInFormula(tagString);
152
172
  displayExampleCommandLine(formulaTags);
153
173
  displayQualifyingFeaturesAndScenarios(formulaTags);
154
- hideEmptySections();
155
174
  fixSectionRowAlternations();
156
175
  }
157
176
 
177
+ function clearTagFiltering() {
178
+ updateTagFiltering("");
179
+ }
180
+
158
181
  function determineTagsUsedInFormula(tagString) {
159
182
 
160
183
  tagString = tagString.replace(/^(\s+)|(\s+)$/,'').replace(/\s{2,}/,' ');
161
184
 
162
- var tagGroup = tagString.match(/@\w+(,@\w+)*/g);
185
+ var tagGroup = tagString.match(/(?:~)?@\w+(,(?:~)?@\w+)*/g);
163
186
 
164
187
  var returnTags = [];
165
188
 
166
189
  if (tagGroup) {
167
190
  tagGroup.forEach(function(tag, index, array) {
168
- //console.log("Tag Group: " + tag);
191
+ console.log("Tag Group: " + tag);
169
192
  var validTags = removeInvalidTags(tag)
170
193
  if (validTags != "") {
171
194
  returnTags.push(validTags);
@@ -178,8 +201,11 @@ function determineTagsUsedInFormula(tagString) {
178
201
 
179
202
  function removeInvalidTags(tagGroup) {
180
203
  tagGroup.split(",").forEach(function(tag, index, array) {
204
+
205
+ baseTag = tag.match(/^~(.+)/) ? tag.match(/^~(.+)/)[1] : tag;
206
+
181
207
  //console.log("Validating Tag: " + tag)
182
- if (tag_list.indexOf(tag) === -1) {
208
+ if (tag_list.indexOf(baseTag) === -1) {
183
209
  //console.log("Removing Tag: " + tag);
184
210
  tagGroup = tagGroup.replace(new RegExp(',?' + tag + ',?'),"")
185
211
  }
@@ -197,28 +223,9 @@ function displayExampleCommandLine(tags) {
197
223
  }
198
224
  }
199
225
 
200
- function hideEmptySections() {
201
-
202
- ["feature","scenario"].forEach(function(section,index,sections) {
203
-
204
- if ( $("." + section + ":visible").length == 0 ) {
205
- $("#" + section + "s")[0].style.display = "none";
206
- } else {
207
- $("#" + section + "s")[0].style.display = "block";
208
- }
209
-
210
- });
211
- }
212
-
213
226
  function fixSectionRowAlternations() {
214
-
215
- ["feature","scenario"].forEach(function(section,index,sections) {
216
-
217
- $("." + section + ":visible")
218
- $("." + section + ":visible").each(function(index) {
219
- $(this).removeClass("r1 r2").addClass("r" + ((index % 2) + 1));
220
- });
221
-
227
+ $(".feature:visible,.scenario:visible").each(function(index){
228
+ $(this).removeClass("odd even").addClass( ((index + 1) % 2 == 0 ? "even" : "odd") );
222
229
  });
223
230
  }
224
231
 
@@ -227,20 +234,34 @@ function displayQualifyingFeaturesAndScenarios(tags) {
227
234
  if (tags.length > 0) {
228
235
 
229
236
  $(".feature,.scenario").each(function(feature){
230
- this.style.display = "none";
237
+ $(this).hide();
231
238
  });
232
239
 
233
240
  var tagSelectors = generateCssSelectorFromTags(tags);
234
241
 
235
242
  tagSelectors.forEach(function(selector,selectorIndex,selectorArray) {
236
- $(".feature." + selector.replace(/@/g,"\\@").replace(/\s/,".") + ",.scenario." + selector.replace(/@/g,"\\@").replace(/\s/,".")).each(function(matchItem) {
237
- this.style.display = "block";
243
+ var tags = selector;
244
+
245
+ $(".feature." + tags).each(function(index) {
246
+ $(this).show();
247
+ });
248
+ $(".scenario." + tags).each(function(index) {
249
+ $(this).show();
250
+ $(this).parent().prev().show();
238
251
  });
252
+
239
253
  });
254
+
255
+ if ( $(".feature:visible,.scenario:visible").length == 0 ) {
256
+ $("#features div.undefined").show();
257
+ } else {
258
+ $("#features div.undefined").hide();
259
+ }
260
+
240
261
 
241
262
  } else {
242
- $(".feature,.scenario").each(function(feature){
243
- this.style.display = "block";
263
+ $(".feature:hidden,.scenario:hidden").each(function(feature){
264
+ $(this).show();
244
265
  });
245
266
  }
246
267
 
@@ -255,8 +276,15 @@ function generateCssSelectorFromTags(tagGroups) {
255
276
 
256
277
  tagSelectors.forEach(function(selector,selectorIndex,selectorArray) {
257
278
  tagGroup.split(",").forEach(function(tag,tagIndex,tagArray) {
258
- //console.log("selector: " + (selector + " " + tag).trim());
259
- newTagSelectors.push((selector + " " + tag).trim());
279
+
280
+ if ( tag.match(/^~@.+$/) ) {
281
+ tag = tag.match(/^~(@.+)$/)[1]
282
+ //console.log("selector: " + (selector + " :not(" + tag + ")").trim());
283
+ newTagSelectors.push((selector + ":not(." + tag.replace(/@/g,"\\@") +")").trim());
284
+ } else {
285
+ //console.log("selector: " + (selector + " " + tag).trim());
286
+ newTagSelectors.push((selector + "." + tag.replace(/@/g,"\\@")).trim());
287
+ }
260
288
  });
261
289
 
262
290
  });
@@ -8,7 +8,7 @@ def init
8
8
 
9
9
  if @features
10
10
  @features.each {|feature| serialize(feature) }
11
- generate_full_list(@features)
11
+ generate_full_list @features.sort {|x,y| x.value.to_s <=> y.value.to_s }
12
12
  end
13
13
 
14
14
  @tags = Registry.all(:tag)
@@ -14,6 +14,7 @@ def all_features_by_letter
14
14
  objects = features
15
15
  objects = run_verifier(objects)
16
16
  objects.each {|o| (hash[o.value.to_s[0,1].upcase] ||= []) << o }
17
+ hash.values.each {|v| v.sort! {|a,b| b.value.to_s <=> a.value.to_s } }
17
18
  hash
18
19
  end
19
20
 
@@ -22,6 +23,7 @@ def all_scenarios_by_letter
22
23
  objects = scenarios
23
24
  objects = run_verifier(objects)
24
25
  objects.each {|o| (hash[o.value.to_s[0,1].upcase] ||= []) << o }
26
+ hash.values.each {|v| v.sort! {|a,b| b.value.to_s <=> a.value.to_s } }
25
27
  hash
26
28
  end
27
29
 
@@ -30,6 +32,7 @@ def all_directories_by_letter
30
32
  objects = feature_directories
31
33
  objects = run_verifier(objects)
32
34
  objects.each {|o| (hash[o.value.to_s[0,1].upcase] ||= []) << o }
35
+ hash.values.each {|v| v.sort! {|a,b| b.value.to_s <=> a.value.to_s } }
33
36
  hash
34
37
  end
35
38
 
@@ -1,9 +1,9 @@
1
1
  <div class="title">
2
- <div class="name"><%= @item_title %></div>
3
-
4
2
  <% if @item_type %>
5
- <div class="control" id="<%= @item_type.gsub(/\s/,'') %>">[Collapse All]</div>
6
- <div style="clear: right;"></div>
7
- <% end %>
3
+ <a class="control" href="#" id="<%= @item_type.gsub(/\s/,'') %>">[Collapse All]</a>
4
+ <div style="clear: right;"></div>
5
+ <% end %>
6
+
7
+ <div class="name"><%= @item_title %></div>
8
8
  </div>
9
9
 
@@ -1,61 +1,67 @@
1
1
  <% @items.each do |item| %>
2
2
 
3
- <div class="transformer <%= @item_type.gsub(/\s/,'') %>">
4
- <a name="<%= anchor_for item %>"></a>
5
- <div class="title">
6
- <span class="pre"><%= h item.keyword %></span>
7
- <span class="name"><%= h item.value %></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>
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"><%= h item.value %></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
11
 
12
- <div class="details">
12
+ <div class="details">
13
13
 
14
- <div class="meta" style="clear: right;">
15
- <div class="file"><%= h item.location %></div>
16
- </div>
14
+ <!-- Comments -->
15
+ <div>
16
+ <%= T('docstring').run(options.dup.merge({:object => item})) %>
17
+ </div>
17
18
 
18
- <!-- Comments -->
19
- <div>
20
- <%= T('docstring').run(options.dup.merge({:object => item})) %>
21
- </div>
19
+ <div class="meta" style="clear: right;">
20
+ <div class="file"><%= h item.location %></div>
21
+ </div>
22
22
 
23
- <!-- Source Code -->
24
- <div class="method_details_list">
25
- <table class="source_code">
26
- <tr>
27
- <td>
28
- <pre class="lines"><%= "" %><%= h format_lines(item) %></pre>
29
- </td>
30
- <td>
31
- <pre class="code"><%= "" %><%= html_syntax_highlight item.source %></pre>
32
- </td>
33
- </tr>
34
- </table>
35
- </div>
23
+ <!-- Source Code -->
24
+ <div class="method_details_list">
25
+ <table class="source_code">
26
+ <tr>
27
+ <td>
28
+ <pre class="lines"><%= "" %><%= h format_lines(item) %></pre>
29
+ </td>
30
+ <td>
31
+ <pre class="code"><%= "" %><%= html_syntax_highlight item.source %></pre>
32
+ </td>
33
+ </tr>
34
+ </table>
35
+ </div>
36
36
 
37
- <!-- Matching Step Instances -->
38
- <div class="steps">
39
- <% if item.steps && !item.steps.empty? %>
40
- <% item.steps.each_with_index do |step,step_index| %>
41
- <div class="step <%= (step_index + 1) % 2 == 0 ? 'even' : 'odd' %>">
42
- <span class="predicate">
43
- <%= h step.keyword %>
44
- </span>
45
- <span class="defined">
46
- <%= link_transformed_step(step) %>
47
- </span>
48
- <a class="definition" href="<%= url_for step.scenario.feature %>"><%= h step.location %></a>
49
- <div style="clear: both;"></div>
50
- </div>
51
- <% end %>
52
- <% else %>
53
- <div class="undefined">No steps were found to match this <%= @item_type %>.</div>
54
- <% end%>
55
- </div>
37
+ <!-- Matching Step Instances -->
56
38
 
39
+ <div class="steps">
40
+ <% if item.steps && !item.steps.empty? %>
41
+ <% unique_steps(item.steps).each_with_index do |uniq_step,step_index| %>
42
+ <div class="step <%= (step_index + 1) % 2 == 0 ? 'even' : 'odd' %>">
43
+ <div>
44
+ <span class="predicate">
45
+ <%= h uniq_step.last.first.keyword %>
46
+ </span>
47
+ <span class="defined">
48
+ <%= link_transformed_step(uniq_step.last.first) %>
49
+ </span>
50
+ </div>
51
+ <% uniq_step.last.each do |step| %>
52
+ <a class="definition" style="clear: right;" href="<%= url_for step.scenario.feature %>"><%= h step.location %></a>
53
+ <% end %>
54
+ <div style="clear: both;"></div>
55
+ </div>
56
+ <% end %>
57
+ <% else %>
58
+ <div class="undefined">No steps were found to match this <%= @item_type %>.</div>
59
+ <% end%>
57
60
  </div>
58
-
59
61
  </div>
62
+
63
+ <div style="margin: 30px 20px; border-top: 1px dotted #AAA;"></div>
64
+
65
+ </div>
60
66
 
61
67
  <% end %>