cuporter 0.2.9 → 0.3.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/README.textile +9 -17
- data/Rakefile +1 -1
- data/lib/cuporter/feature_parser.rb +47 -3
- data/lib/cuporter/formatter/cuporter.css +7 -61
- data/lib/cuporter/formatter/html_methods.rb +48 -9
- data/lib/cuporter/formatter/html_node_writer.rb +15 -21
- data/lib/cuporter/formatter/name_report/html.rb +23 -39
- data/lib/cuporter/formatter/name_report/html_node_writer.rb +2 -2
- data/lib/cuporter/formatter/name_report/style.css +58 -0
- data/lib/cuporter/formatter/tag_report/html.rb +18 -33
- data/lib/cuporter/formatter/tag_report/html_node_writer.rb +2 -2
- data/lib/cuporter/formatter/tag_report/style.css +78 -0
- data/lib/cuporter/name_list_parser.rb +44 -0
- data/lib/cuporter/node.rb +6 -2
- data/lib/cuporter/tag_list_parser.rb +39 -0
- data/lib/cuporter.rb +2 -2
- metadata +9 -7
- data/lib/cuporter/name_list.rb +0 -65
- data/lib/cuporter/tag_list.rb +0 -64
data/README.textile
CHANGED
@@ -2,13 +2,13 @@ h1. Cuporter
|
|
2
2
|
|
3
3
|
Scrapes your feature files and shows 2 possible reports:
|
4
4
|
|
5
|
-
# scenarios and examples per tag
|
5
|
+
# Tag Report: scenarios and examples per tag
|
6
6
|
** in Feature and Scenario Outline context, as appropriate
|
7
|
-
** sorted alphbetically
|
7
|
+
** sorted alphbetically by file path, scenario name, scenario outline name, example name
|
8
8
|
** optionally numbered*, counting scenarios and outline examples per tag
|
9
|
-
# feature, scenario and example names
|
9
|
+
# Inventory Report: feature, scenario and example names
|
10
10
|
** may be filtered by tags, using same CLI syntax as Cucumber
|
11
|
-
** sorted alphbetically
|
11
|
+
** sorted alphbetically by file path, scenario name, scenario outline name, example name
|
12
12
|
** optionally numbered*, using 1 count of all scenarios and outline examples for the report
|
13
13
|
|
14
14
|
<notextile>*</notextile> _HTML reports are always numbered._
|
@@ -106,20 +106,12 @@ h4. run script directly
|
|
106
106
|
# pretty-print demo report to stdout
|
107
107
|
$ ./bin/cuporter -i fixtures/self_text
|
108
108
|
|
109
|
-
# default input features/**/*.feature to named output file
|
110
|
-
$ ./bin/cuporter -f html -o feature_tag_report.html
|
111
|
-
|
112
109
|
# same, but number the scenarios and example rows
|
113
|
-
$ ./bin/cuporter -
|
114
|
-
|
115
|
-
# filtered html name report, with non-default title
|
116
|
-
$ ./bin/cuporter -f html -o active_customer.html -r name -n -T "Active Customer Test Inventory" -t ~@wip -t @customer,@client
|
117
|
-
</pre>
|
110
|
+
$ ./bin/cuporter -i fixtures/self_text -n
|
118
111
|
|
119
|
-
|
120
|
-
|
121
|
-
<pre>
|
122
|
-
$ rake cuporter:run["-i fixtures/self_text"]
|
112
|
+
# default input features/**/*.feature to named html output file
|
113
|
+
$ ./bin/cuporter -f html -o feature_tag_report.html
|
123
114
|
|
124
|
-
|
115
|
+
# filtered html name report, with non-default title
|
116
|
+
$ ./bin/cuporter -f html -o active_customer.html -r name -T "Active Customer Test Inventory" -t ~@wip -t @customer,@client
|
125
117
|
</pre>
|
data/Rakefile
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Copyright 2010 ThoughtWorks, Inc. Licensed under the MIT License
|
2
2
|
|
3
3
|
module Cuporter
|
4
|
-
|
4
|
+
class FeatureParser
|
5
5
|
FEATURE_LINE = /^\s*(Feature:[^#]+)/
|
6
6
|
TAG_LINE = /^\s*(@\w.+)/
|
7
7
|
SCENARIO_LINE = /^\s*(Scenario:[^#]+)$/
|
@@ -11,11 +11,55 @@ module Cuporter
|
|
11
11
|
EXAMPLE_LINE = /^\s*(\|.*\|)\s*$/
|
12
12
|
|
13
13
|
def self.tag_list(file)
|
14
|
-
|
14
|
+
TagListParser.new(file).parse_feature
|
15
15
|
end
|
16
16
|
|
17
17
|
def self.name_list(file, filter)
|
18
|
-
|
18
|
+
NameListParser.new(file, filter).parse_feature
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(file)
|
22
|
+
@file = file
|
23
|
+
@current_tags = []
|
24
|
+
@lines = File.read(@file).split(/\n/)
|
25
|
+
end
|
26
|
+
|
27
|
+
def parse_feature
|
28
|
+
@lines.each do |line|
|
29
|
+
case line
|
30
|
+
when FeatureParser::TAG_LINE
|
31
|
+
# may be more than one tag line
|
32
|
+
@current_tags |= $1.strip.split(/\s+/)
|
33
|
+
when FeatureParser::FEATURE_LINE
|
34
|
+
@feature = new_feature_node($1)
|
35
|
+
@feature.file = @file.sub(/^.*features\//,"features/")
|
36
|
+
@current_tags = []
|
37
|
+
when FeatureParser::SCENARIO_LINE
|
38
|
+
# How do we know when we have read all the lines from a "Scenario Outline:"?
|
39
|
+
# One way is when we encounter a "Scenario:"
|
40
|
+
close_scenario_outline
|
41
|
+
|
42
|
+
handle_scenario_line($1)
|
43
|
+
@current_tags = []
|
44
|
+
when FeatureParser::SCENARIO_OUTLINE_LINE
|
45
|
+
# ... another is when we hit a subsequent "Scenario Outline:"
|
46
|
+
close_scenario_outline
|
47
|
+
|
48
|
+
@scenario_outline = new_scenario_outline_node($1)
|
49
|
+
@current_tags = []
|
50
|
+
when FeatureParser::EXAMPLE_SET_LINE, FeatureParser::SCENARIO_SET_LINE
|
51
|
+
handle_example_set_line if @example_set
|
52
|
+
|
53
|
+
@example_set = new_example_set_node($1)
|
54
|
+
@current_tags = []
|
55
|
+
when @example_set && FeatureParser::EXAMPLE_LINE
|
56
|
+
@example_set.add_child(Node.new($1))
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# EOF is the final way that we know we are finished with a "Scenario Outline"
|
61
|
+
close_scenario_outline
|
62
|
+
return @feature
|
19
63
|
end
|
20
64
|
|
21
65
|
end
|
@@ -7,7 +7,6 @@ body {
|
|
7
7
|
padding-left: 2em;
|
8
8
|
padding-bottom: 0.3em;
|
9
9
|
padding-top: 0.05em;
|
10
|
-
background-color: #24A6C1;
|
11
10
|
color: white;
|
12
11
|
height: 7em;
|
13
12
|
}
|
@@ -15,12 +14,6 @@ body {
|
|
15
14
|
padding-right: 2em;
|
16
15
|
float: left;
|
17
16
|
}
|
18
|
-
#filter_summary {
|
19
|
-
width: 60em;
|
20
|
-
float: right;
|
21
|
-
padding-top: 1.2em;
|
22
|
-
}
|
23
|
-
|
24
17
|
#summary {
|
25
18
|
position: absolute;
|
26
19
|
right: 1em;
|
@@ -28,87 +21,40 @@ body {
|
|
28
21
|
top: 1.2em;
|
29
22
|
}
|
30
23
|
|
31
|
-
#summary p
|
24
|
+
#summary p {
|
32
25
|
margin: 0px 0px 0px 2px;
|
33
26
|
}
|
34
27
|
|
35
|
-
.tag_report #expand-collapse {
|
36
|
-
position: absolute;
|
37
|
-
right: 1em;
|
38
|
-
text-align: right;
|
39
|
-
top: 0.5em;
|
40
|
-
}
|
41
28
|
ul {
|
42
29
|
list-style-type: none;
|
43
30
|
}
|
44
|
-
.
|
31
|
+
.main_list {
|
45
32
|
padding-left: 0.5em;
|
46
33
|
}
|
47
|
-
.tag_name {
|
48
|
-
height: 2em;
|
49
|
-
font-weight: bold;
|
50
|
-
font-size: 1.5em;
|
51
|
-
}
|
52
|
-
.total {
|
53
|
-
margin-left: 0.5em;
|
54
|
-
font-weight: normal;
|
55
|
-
font-size: 0.8em;
|
56
|
-
}
|
57
|
-
.tag {
|
58
|
-
margin-bottom: 1em;
|
59
|
-
}
|
60
|
-
|
61
34
|
.feature {
|
62
35
|
margin-bottom: 0.5em;
|
63
36
|
margin-right: 1em;
|
64
37
|
}
|
65
38
|
.feature_name {
|
66
|
-
margin-left: -2em;
|
67
|
-
padding-left: 2em;
|
68
39
|
padding-top: 0.3em;
|
69
40
|
padding-bottom: 0.3em;
|
70
41
|
font-weight: bold;
|
71
|
-
background-color: #24A6C1;
|
72
|
-
color: white;
|
73
|
-
}
|
74
|
-
.example_rows {
|
75
|
-
background-color: lightblue;
|
76
|
-
margin-left: -7.2em;
|
77
|
-
padding-left: 7.2em;
|
78
42
|
}
|
79
43
|
|
80
|
-
.
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
44
|
+
.file {
|
45
|
+
float: right;
|
46
|
+
padding-right: 0.5em;
|
47
|
+
font-weight: normal;
|
48
|
+
color: black;
|
85
49
|
}
|
86
50
|
|
87
51
|
.example td.val {
|
88
52
|
padding-left: 0.5em;
|
89
53
|
}
|
90
|
-
.scenario_name {
|
91
|
-
margin-left: -3.8em;
|
92
|
-
padding-left: 3.8em;
|
93
|
-
background-color: lightblue;
|
94
|
-
|
95
|
-
}
|
96
54
|
|
97
55
|
.number {
|
98
56
|
position: absolute;
|
99
|
-
left: 4.5em;
|
100
57
|
font-weight: bold;
|
101
58
|
}
|
102
59
|
|
103
|
-
.name_report .number {
|
104
|
-
left: 4em;
|
105
|
-
}
|
106
|
-
.file {
|
107
|
-
float: right;
|
108
|
-
padding-right: 0.5em;
|
109
|
-
font-weight: normal;
|
110
|
-
font-size: 1.1em;
|
111
|
-
color: black;
|
112
|
-
|
113
|
-
}
|
114
60
|
|
@@ -6,24 +6,63 @@ module Cuporter
|
|
6
6
|
module Formatter
|
7
7
|
module HtmlMethods
|
8
8
|
|
9
|
-
def
|
10
|
-
|
9
|
+
def document
|
10
|
+
builder = Builder::XmlMarkup.new
|
11
|
+
builder.declare!(:DOCTYPE, :html,
|
12
|
+
:PUBLIC, "-//W3C//DTD XHTML 1.0 Transitional//EN",
|
13
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
|
14
|
+
)
|
15
|
+
builder
|
11
16
|
end
|
12
17
|
|
13
|
-
def
|
14
|
-
|
18
|
+
def html
|
19
|
+
document.html(:xmlns => "http://www.w3.org/1999/xhtml") do |html|
|
20
|
+
head(html)
|
21
|
+
body(html)
|
22
|
+
end.to_s.sub("<to_s/>",'')
|
15
23
|
end
|
16
24
|
|
17
|
-
def
|
18
|
-
|
25
|
+
def head(html)
|
26
|
+
html.head do |head|
|
27
|
+
head.title(title)
|
28
|
+
head.style(inline_file("cuporter.css"))
|
29
|
+
head.style(inline_file(inline_style))
|
30
|
+
head.script(:type => "text/javascript") do
|
31
|
+
head << inline_jquery # jquery is corrupted if it isn't handled this way
|
32
|
+
head << inline_js_content
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def body(html)
|
38
|
+
html.body do |body|
|
39
|
+
header(body)
|
40
|
+
body.ul(:class => :main_list) do |ul|
|
41
|
+
write_report_node(body)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def label(header)
|
47
|
+
header.div(:id => :label) do |div|
|
48
|
+
div.h1(title)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def inline_file(file_name)
|
53
|
+
File.read("#{File.dirname(__FILE__)}/#{file_name}")
|
54
|
+
end
|
55
|
+
|
56
|
+
def write_report_node(body)
|
57
|
+
report_node_writer.new(@report, body).write_report_node
|
19
58
|
end
|
20
59
|
|
21
60
|
def write
|
22
|
-
@output.puts
|
61
|
+
@output.puts html
|
23
62
|
end
|
24
63
|
|
25
64
|
def inline_jquery
|
26
|
-
|
65
|
+
inline_file('/jquery-min.js')
|
27
66
|
end
|
28
67
|
|
29
68
|
def inline_js_content
|
@@ -72,7 +111,7 @@ module Cuporter
|
|
72
111
|
});
|
73
112
|
|
74
113
|
// load page with features collapsed
|
75
|
-
$("#
|
114
|
+
$("#collapser, #collapse_features").click();
|
76
115
|
})
|
77
116
|
|
78
117
|
EOF
|
@@ -8,17 +8,11 @@ module Cuporter
|
|
8
8
|
|
9
9
|
attr_reader :builder
|
10
10
|
|
11
|
-
def initialize
|
12
|
-
@
|
11
|
+
def initialize(report, builder)
|
12
|
+
@report = report
|
13
|
+
@builder = builder
|
13
14
|
end
|
14
15
|
|
15
|
-
def write_nodes(report, number_scenarios)
|
16
|
-
report.report_node.number_all_descendants if number_scenarios
|
17
|
-
report.report_node.children.each do |child_node|
|
18
|
-
write_node(child_node)
|
19
|
-
end
|
20
|
-
builder
|
21
|
-
end
|
22
16
|
def write_node(node)
|
23
17
|
builder.li(:class => node_class(node.name)) do
|
24
18
|
write_node_name(node)
|
@@ -79,18 +73,18 @@ module Cuporter
|
|
79
73
|
|
80
74
|
def node_class(name)
|
81
75
|
case name
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
76
|
+
when FeatureParser::TAG_LINE
|
77
|
+
:tag
|
78
|
+
when FeatureParser::FEATURE_LINE
|
79
|
+
:feature
|
80
|
+
when FeatureParser::SCENARIO_LINE
|
81
|
+
:scenario
|
82
|
+
when FeatureParser::SCENARIO_OUTLINE_LINE
|
83
|
+
:scenario_outline
|
84
|
+
when FeatureParser::SCENARIO_SET_LINE, FeatureParser::EXAMPLE_SET_LINE
|
85
|
+
:example_set
|
86
|
+
else
|
87
|
+
:example
|
94
88
|
end
|
95
89
|
end
|
96
90
|
|
@@ -1,20 +1,34 @@
|
|
1
1
|
# Copyright 2010 ThoughtWorks, Inc. Licensed under the MIT License
|
2
|
-
require 'rubygems'
|
3
|
-
require 'erb'
|
4
|
-
|
5
2
|
module Cuporter
|
6
3
|
module Formatter
|
7
4
|
module NameReport
|
8
5
|
class Html < Writer
|
9
6
|
include HtmlMethods
|
10
7
|
|
8
|
+
def report_node_writer
|
9
|
+
Cuporter::Formatter::NameReport::HtmlNodeWriter
|
10
|
+
end
|
11
|
+
|
11
12
|
def title
|
12
13
|
@report.title
|
13
14
|
end
|
14
15
|
|
15
|
-
def
|
16
|
+
def header(body)
|
17
|
+
body.div(:class => :cuporter_header) do |header|
|
18
|
+
label(header)
|
19
|
+
filter_summary(header)
|
20
|
+
header.div(:id => :summary) do |div|
|
21
|
+
div.p("#{@report.report_node.total} Scenarios", :id => :total)
|
22
|
+
div.div(:id => "expand-collapse") do |exp_col|
|
23
|
+
exp_col.p("Expand All", :id => :expand_features)
|
24
|
+
exp_col.p("Collapse All", :id => :collapse_features)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def filter_summary(builder)
|
16
31
|
return if @report.filter.empty?
|
17
|
-
builder = Builder::XmlMarkup.new
|
18
32
|
builder.div(:id => :filter_summary) do |div|
|
19
33
|
div.p("Filtering:")
|
20
34
|
div.p("Include: #{@report.filter.all.join(' AND ')}") unless @report.filter.all.empty?
|
@@ -23,40 +37,10 @@ module Cuporter
|
|
23
37
|
end
|
24
38
|
end
|
25
39
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
<title><%= title %></title>
|
31
|
-
<style type="text/css">
|
32
|
-
<%= inline_style%>
|
33
|
-
</style>
|
34
|
-
<script type="text/javascript">
|
35
|
-
<%= inline_jquery%>
|
36
|
-
<%= inline_js_content%>
|
37
|
-
</script>
|
38
|
-
</head>
|
39
|
-
<body class="name_report">
|
40
|
-
<div class="cuporter_header">
|
41
|
-
<div id="label">
|
42
|
-
<h1><%= title %></h1>
|
43
|
-
</div>
|
44
|
-
<%= filter_summary %>
|
45
|
-
<div id="summary">
|
46
|
-
<p id="total"><%= @report.report_node.total%> Scenarios </p>
|
47
|
-
<div id="expand-collapse">
|
48
|
-
<p id="expand_features">Expand All</p>
|
49
|
-
<p id="collapse_features">Collapse All</p>
|
50
|
-
</div>
|
51
|
-
</div>
|
52
|
-
</div>
|
53
|
-
<ul class="tag_list, name_report">
|
54
|
-
<%= Cuporter::Formatter::NameReport::HtmlNodeWriter.new.write_nodes(@report)%>
|
55
|
-
</ul>
|
56
|
-
</body>
|
57
|
-
</html>
|
58
|
-
}
|
59
|
-
|
40
|
+
def inline_style
|
41
|
+
"name_report/style.css"
|
42
|
+
end
|
43
|
+
|
60
44
|
|
61
45
|
end
|
62
46
|
end
|
@@ -5,8 +5,8 @@ module Cuporter
|
|
5
5
|
module NameReport
|
6
6
|
class HtmlNodeWriter < Cuporter::Formatter::HtmlNodeWriter
|
7
7
|
|
8
|
-
def
|
9
|
-
report.report_node.children.each do |child_node|
|
8
|
+
def write_report_node
|
9
|
+
@report.report_node.children.each do |child_node|
|
10
10
|
write_node(child_node)
|
11
11
|
end
|
12
12
|
builder
|
@@ -0,0 +1,58 @@
|
|
1
|
+
/* Name Report */
|
2
|
+
.number {
|
3
|
+
left: 3.0em;
|
4
|
+
}
|
5
|
+
|
6
|
+
#filter_summary {
|
7
|
+
width: 60em;
|
8
|
+
float: right;
|
9
|
+
padding-top: 1.2em;
|
10
|
+
}
|
11
|
+
|
12
|
+
#filter_summary p {
|
13
|
+
margin: 0px 0px 0px 2px;
|
14
|
+
}
|
15
|
+
|
16
|
+
.cuporter_header {
|
17
|
+
background-color: #65C400;
|
18
|
+
}
|
19
|
+
|
20
|
+
.feature_name {
|
21
|
+
margin-left: 0.5em;
|
22
|
+
font-size: 1.5em;
|
23
|
+
}
|
24
|
+
|
25
|
+
.file {
|
26
|
+
font-size: 0.8em;
|
27
|
+
}
|
28
|
+
|
29
|
+
.scenario_name {
|
30
|
+
margin-left: -2.4em;
|
31
|
+
padding-left: 4.0em;
|
32
|
+
padding-top: 0.1em;
|
33
|
+
padding-bottom: 0.2em;
|
34
|
+
}
|
35
|
+
.scenario_outline_name {
|
36
|
+
margin-left: -2.4em;
|
37
|
+
padding-left: 4.5em;
|
38
|
+
padding-top: 0.1em;
|
39
|
+
padding-bottom: 0.2em;
|
40
|
+
|
41
|
+
}
|
42
|
+
|
43
|
+
.example {
|
44
|
+
background-color: #65C400;
|
45
|
+
}
|
46
|
+
|
47
|
+
.example_rows {
|
48
|
+
margin-left: -6.0em;
|
49
|
+
padding-left: 7.6em;
|
50
|
+
}
|
51
|
+
|
52
|
+
.scenario_name, .example_rows {
|
53
|
+
margin-top: 0.2em;
|
54
|
+
margin-bottom: 0.2em;
|
55
|
+
background-color: #DBFFB4;
|
56
|
+
border-left: 0.5em solid #65c400;
|
57
|
+
border-bottom: 1px solid #65c400;
|
58
|
+
}
|
@@ -1,48 +1,33 @@
|
|
1
1
|
# Copyright 2010 ThoughtWorks, Inc. Licensed under the MIT License
|
2
|
-
require 'rubygems'
|
3
|
-
require 'erb'
|
4
|
-
|
5
2
|
module Cuporter
|
6
3
|
module Formatter
|
7
4
|
module TagReport
|
8
5
|
class Html < Writer
|
9
6
|
include HtmlMethods
|
10
7
|
|
8
|
+
def report_node_writer
|
9
|
+
Cuporter::Formatter::TagReport::HtmlNodeWriter
|
10
|
+
end
|
11
|
+
|
11
12
|
def title
|
12
13
|
"Cucumber Tags"
|
13
14
|
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
</style>
|
23
|
-
<script type="text/javascript">
|
24
|
-
<%= inline_jquery%>
|
25
|
-
<%= inline_js_content%>
|
26
|
-
</script>
|
27
|
-
</head>
|
28
|
-
<body class="tag_report">
|
29
|
-
<div class="cuporter_header">
|
30
|
-
<div id="label">
|
31
|
-
<h1><%= title %></h1>
|
32
|
-
</div>
|
33
|
-
<div id="expand-collapse">
|
34
|
-
<p id="expand_tags">Expand Tags</p>
|
35
|
-
<p id="expand_all">Expand All</p>
|
36
|
-
<p id="collapser">Collapse All</p>
|
37
|
-
</div>
|
38
|
-
</div>
|
39
|
-
<ul class="tag_list">
|
40
|
-
<%= Cuporter::Formatter::TagReport::HtmlNodeWriter.new.write_nodes(@report)%>
|
41
|
-
</ul>
|
42
|
-
</body>
|
43
|
-
</html>
|
44
|
-
}
|
16
|
+
def inline_style
|
17
|
+
"tag_report/style.css"
|
18
|
+
end
|
19
|
+
|
20
|
+
def header(body)
|
21
|
+
body.div(:class => :cuporter_header) do |header|
|
22
|
+
label(header)
|
45
23
|
|
24
|
+
body.div(:id => "expand-collapse") do |div|
|
25
|
+
div.p("Expand Tags", :id => :expand_tags)
|
26
|
+
div.p("Expand All", :id => :expand_all)
|
27
|
+
div.p("Collapse All", :id => :collapser)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
46
31
|
|
47
32
|
end
|
48
33
|
end
|
@@ -5,8 +5,8 @@ module Cuporter
|
|
5
5
|
module TagReport
|
6
6
|
class HtmlNodeWriter < Cuporter::Formatter::HtmlNodeWriter
|
7
7
|
|
8
|
-
def
|
9
|
-
report.report_node.children.each do |tag_node|
|
8
|
+
def write_report_node
|
9
|
+
@report.report_node.children.each do |tag_node|
|
10
10
|
tag_node.number_all_descendants
|
11
11
|
write_node(tag_node)
|
12
12
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
/* Tag Report */
|
2
|
+
.number {
|
3
|
+
left: 4.5em;
|
4
|
+
}
|
5
|
+
|
6
|
+
#expand-collapse {
|
7
|
+
position: absolute;
|
8
|
+
right: 1em;
|
9
|
+
text-align: right;
|
10
|
+
top: 0.5em;
|
11
|
+
}
|
12
|
+
|
13
|
+
.cuporter_header {
|
14
|
+
background-color: #24A6C1;
|
15
|
+
}
|
16
|
+
|
17
|
+
.tag_name {
|
18
|
+
font-weight: bold;
|
19
|
+
font-size: 1.5em;
|
20
|
+
}
|
21
|
+
.total {
|
22
|
+
margin-left: 0.5em;
|
23
|
+
font-weight: normal;
|
24
|
+
font-size: 0.8em;
|
25
|
+
}
|
26
|
+
|
27
|
+
.tag {
|
28
|
+
margin-top: 0.5em;
|
29
|
+
margin-bottom: 0.5em;
|
30
|
+
}
|
31
|
+
|
32
|
+
.tag ul {
|
33
|
+
margin-top: 1.0em;
|
34
|
+
margin-bottom: 0.5em;
|
35
|
+
}
|
36
|
+
.feature_name {
|
37
|
+
margin-left: -2em;
|
38
|
+
padding-left: 1.5em;
|
39
|
+
background-color: #24A6C1;
|
40
|
+
color: white;
|
41
|
+
}
|
42
|
+
|
43
|
+
.file {
|
44
|
+
font-size: 1.1em;
|
45
|
+
}
|
46
|
+
|
47
|
+
.scenario_name {
|
48
|
+
margin-left: -4.0em;
|
49
|
+
padding-left: 4.0em;
|
50
|
+
background-color: lightblue;
|
51
|
+
}
|
52
|
+
|
53
|
+
.scenario_outline_name {
|
54
|
+
margin-left: -4.0em;
|
55
|
+
padding-left: 4.5em;
|
56
|
+
}
|
57
|
+
|
58
|
+
.example_rows {
|
59
|
+
margin-left: -7.7em;
|
60
|
+
padding-left: 7.7em;
|
61
|
+
background-color: lightblue;
|
62
|
+
}
|
63
|
+
|
64
|
+
.example {
|
65
|
+
background-color: #26A6C0;
|
66
|
+
}
|
67
|
+
|
68
|
+
.example_set_name {
|
69
|
+
margin-left: -2em;
|
70
|
+
}
|
71
|
+
|
72
|
+
.scenario_name, .example_rows {
|
73
|
+
margin-top: 0.2em;
|
74
|
+
margin-bottom: 0.2em;
|
75
|
+
background-color: #lightblue;
|
76
|
+
border-left: 0.5em solid #26A6C0;
|
77
|
+
border-bottom: 1px solid #26A6C0;
|
78
|
+
}
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Copyright 2010 ThoughtWorks, Inc. Licensed under the MIT License
|
2
|
+
|
3
|
+
module Cuporter
|
4
|
+
class NameListParser < FeatureParser
|
5
|
+
|
6
|
+
# ++sub_expression++ is the paren group in the regex, dereferenced with $1 in the caller
|
7
|
+
def new_feature_node(sub_expression)
|
8
|
+
TagListNode.new(sub_expression, @current_tags, @filter)
|
9
|
+
end
|
10
|
+
|
11
|
+
def handle_scenario_line(sub_expression)
|
12
|
+
@feature.filter_child(Node.new(sub_expression), @current_tags)
|
13
|
+
end
|
14
|
+
|
15
|
+
def new_scenario_outline_node(sub_expression)
|
16
|
+
TagListNode.new(sub_expression, @current_tags, @filter)
|
17
|
+
end
|
18
|
+
|
19
|
+
def handle_example_set_line
|
20
|
+
@scenario_outline.filter_child(@example_set, @example_set.tags)
|
21
|
+
end
|
22
|
+
|
23
|
+
def new_example_set_node(sub_expression)
|
24
|
+
ExampleSetNode.new(sub_expression, @feature.tags | @current_tags, @filter)
|
25
|
+
end
|
26
|
+
|
27
|
+
def close_scenario_outline
|
28
|
+
if @scenario_outline
|
29
|
+
if @example_set
|
30
|
+
@scenario_outline.filter_child(@example_set, @example_set.tags) if @example_set
|
31
|
+
@example_set = nil
|
32
|
+
end
|
33
|
+
@feature.add_child(@scenario_outline) if @scenario_outline.has_children?
|
34
|
+
@scenario_outline = nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def initialize(file, filter)
|
39
|
+
super(file)
|
40
|
+
@filter = filter
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
data/lib/cuporter/node.rb
CHANGED
@@ -48,9 +48,13 @@ module Cuporter
|
|
48
48
|
children.sort!
|
49
49
|
end
|
50
50
|
|
51
|
-
# sort on name
|
51
|
+
# sort on: file path, name, substring of name after any ':'
|
52
52
|
def <=>(other)
|
53
|
-
|
53
|
+
if file
|
54
|
+
file <=> other.file
|
55
|
+
else
|
56
|
+
name_without_title <=> other.name_without_title
|
57
|
+
end
|
54
58
|
end
|
55
59
|
|
56
60
|
# value equivalence
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# Copyright 2010 ThoughtWorks, Inc. Licensed under the MIT License
|
2
|
+
|
3
|
+
module Cuporter
|
4
|
+
class TagListParser < FeatureParser
|
5
|
+
|
6
|
+
# ++sub_expression++ is the paren group in the regex, dereferenced with $1 in the caller
|
7
|
+
def new_feature_node(sub_expression)
|
8
|
+
TagListNode.new(sub_expression, @current_tags)
|
9
|
+
end
|
10
|
+
|
11
|
+
def handle_scenario_line(sub_expression)
|
12
|
+
@feature.add_to_tag_nodes(TagListNode.new(sub_expression, @current_tags))
|
13
|
+
end
|
14
|
+
|
15
|
+
def new_scenario_outline_node(sub_expression)
|
16
|
+
TagListNode.new(sub_expression, @current_tags)
|
17
|
+
end
|
18
|
+
|
19
|
+
def handle_example_set_line
|
20
|
+
@scenario_outline.add_to_tag_nodes(@example_set)
|
21
|
+
end
|
22
|
+
|
23
|
+
def new_example_set_node(sub_expression)
|
24
|
+
ExampleSetNode.new(sub_expression, @feature.tags | @current_tags)
|
25
|
+
end
|
26
|
+
|
27
|
+
def close_scenario_outline
|
28
|
+
if @scenario_outline
|
29
|
+
if @example_set
|
30
|
+
@scenario_outline.add_to_tag_nodes(@example_set) if @example_set
|
31
|
+
@example_set = nil
|
32
|
+
end
|
33
|
+
@feature.merge_tag_nodes(@scenario_outline)
|
34
|
+
@scenario_outline = nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
data/lib/cuporter.rb
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
# Copyright 2010 ThoughtWorks, Inc. Licensed under the MIT License
|
2
2
|
require 'cuporter/node'
|
3
3
|
require 'cuporter/filter'
|
4
|
-
require 'cuporter/tag_list'
|
5
|
-
require 'cuporter/name_list'
|
6
4
|
require 'cuporter/tag_list_node'
|
7
5
|
require 'cuporter/example_set_node'
|
8
6
|
require 'cuporter/node_numberer'
|
9
7
|
require 'cuporter/feature_parser'
|
8
|
+
require 'cuporter/tag_list_parser'
|
9
|
+
require 'cuporter/name_list_parser'
|
10
10
|
require 'cuporter/extensions/string'
|
11
11
|
require 'cuporter/cli/options'
|
12
12
|
require 'cuporter/cli/filter_args_builder'
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cuporter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 19
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 3
|
9
|
+
- 0
|
10
|
+
version: 0.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Tim Camper
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-10-04 00:00:00 -04:00
|
19
19
|
default_executable: cuporter
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -47,7 +47,7 @@ files:
|
|
47
47
|
- LICENSE
|
48
48
|
- README.textile
|
49
49
|
- Rakefile
|
50
|
-
- lib/cuporter/
|
50
|
+
- lib/cuporter/tag_list_parser.rb
|
51
51
|
- lib/cuporter/example_set_node.rb
|
52
52
|
- lib/cuporter/formatter/tag_report/csv.rb
|
53
53
|
- lib/cuporter/formatter/tag_report/text_node_writer.rb
|
@@ -65,7 +65,6 @@ files:
|
|
65
65
|
- lib/cuporter/formatter/name_report/text.rb
|
66
66
|
- lib/cuporter/formatter/name_report/html_node_writer.rb
|
67
67
|
- lib/cuporter/formatter/name_report/html.rb
|
68
|
-
- lib/cuporter/tag_list.rb
|
69
68
|
- lib/cuporter/report/report.rb
|
70
69
|
- lib/cuporter/report/name_report.rb
|
71
70
|
- lib/cuporter/report/tag_report.rb
|
@@ -75,9 +74,12 @@ files:
|
|
75
74
|
- lib/cuporter/extensions/string.rb
|
76
75
|
- lib/cuporter/feature_parser.rb
|
77
76
|
- lib/cuporter/node.rb
|
77
|
+
- lib/cuporter/name_list_parser.rb
|
78
78
|
- lib/cuporter/filter.rb
|
79
79
|
- lib/cuporter/node_numberer.rb
|
80
80
|
- lib/cuporter.rb
|
81
|
+
- lib/cuporter/formatter/tag_report/style.css
|
82
|
+
- lib/cuporter/formatter/name_report/style.css
|
81
83
|
- lib/cuporter/formatter/cuporter.css
|
82
84
|
- lib/cuporter/formatter/jquery-min.js
|
83
85
|
- bin/cuporter
|
data/lib/cuporter/name_list.rb
DELETED
@@ -1,65 +0,0 @@
|
|
1
|
-
# Copyright 2010 ThoughtWorks, Inc. Licensed under the MIT License
|
2
|
-
|
3
|
-
module Cuporter
|
4
|
-
class NameList
|
5
|
-
|
6
|
-
def initialize(file, filter)
|
7
|
-
@file = file
|
8
|
-
@current_tags = []
|
9
|
-
@filter = filter
|
10
|
-
end
|
11
|
-
|
12
|
-
def parse_feature
|
13
|
-
lines = File.read(@file).split(/\n/)
|
14
|
-
|
15
|
-
lines.each do |line|
|
16
|
-
case line
|
17
|
-
when FeatureParser::TAG_LINE
|
18
|
-
# may be more than one tag line
|
19
|
-
@current_tags |= $1.strip.split(/\s+/)
|
20
|
-
when FeatureParser::FEATURE_LINE
|
21
|
-
@feature = TagListNode.new($1, @current_tags, @filter)
|
22
|
-
@feature.file = @file.sub(/^.*features\//,"features/")
|
23
|
-
@current_tags = []
|
24
|
-
when FeatureParser::SCENARIO_LINE
|
25
|
-
# How do we know when we have read all the lines from a "Scenario Outline:"?
|
26
|
-
# One way is when we encounter a "Scenario:"
|
27
|
-
close_scenario_outline
|
28
|
-
|
29
|
-
@feature.filter_child(Node.new($1), @current_tags)
|
30
|
-
@current_tags = []
|
31
|
-
when FeatureParser::SCENARIO_OUTLINE_LINE
|
32
|
-
# ... another is when we hit a subsequent "Scenario Outline:"
|
33
|
-
close_scenario_outline
|
34
|
-
|
35
|
-
@scenario_outline = TagListNode.new($1, @current_tags, @filter)
|
36
|
-
@current_tags = []
|
37
|
-
when FeatureParser::EXAMPLE_SET_LINE, FeatureParser::SCENARIO_SET_LINE
|
38
|
-
@scenario_outline.filter_child(@example_set, @example_set.tags) if @example_set
|
39
|
-
|
40
|
-
@example_set = ExampleSetNode.new($1, @feature.tags | @current_tags, @filter)
|
41
|
-
@current_tags = []
|
42
|
-
when @example_set && FeatureParser::EXAMPLE_LINE
|
43
|
-
@example_set.add_child(Node.new($1))
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
# EOF is the final way that we know we are finished with a "Scenario Outline"
|
48
|
-
close_scenario_outline
|
49
|
-
return @feature
|
50
|
-
end
|
51
|
-
|
52
|
-
def close_scenario_outline
|
53
|
-
if @scenario_outline
|
54
|
-
if @example_set
|
55
|
-
@scenario_outline.filter_child(@example_set, @example_set.tags) if @example_set
|
56
|
-
@example_set = nil
|
57
|
-
end
|
58
|
-
@feature.add_child(@scenario_outline) if @scenario_outline.has_children?
|
59
|
-
@scenario_outline = nil
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
end
|
64
|
-
|
65
|
-
end
|
data/lib/cuporter/tag_list.rb
DELETED
@@ -1,64 +0,0 @@
|
|
1
|
-
# Copyright 2010 ThoughtWorks, Inc. Licensed under the MIT License
|
2
|
-
|
3
|
-
module Cuporter
|
4
|
-
class TagList
|
5
|
-
|
6
|
-
def initialize(file)
|
7
|
-
@file = file
|
8
|
-
@current_tags = []
|
9
|
-
end
|
10
|
-
|
11
|
-
def parse_feature
|
12
|
-
lines = File.read(@file).split(/\n/)
|
13
|
-
|
14
|
-
lines.each do |line|
|
15
|
-
case line
|
16
|
-
when FeatureParser::TAG_LINE
|
17
|
-
# may be more than one tag line
|
18
|
-
@current_tags |= $1.strip.split(/\s+/)
|
19
|
-
when FeatureParser::FEATURE_LINE
|
20
|
-
@feature = TagListNode.new($1, @current_tags)
|
21
|
-
@feature.file = @file.sub(/^.*features\//,"features/")
|
22
|
-
@current_tags = []
|
23
|
-
when FeatureParser::SCENARIO_LINE
|
24
|
-
# How do we know when we have read all the lines from a "Scenario Outline:"?
|
25
|
-
# One way is when we encounter a "Scenario:"
|
26
|
-
close_scenario_outline
|
27
|
-
|
28
|
-
@feature.add_to_tag_nodes(TagListNode.new($1, @current_tags))
|
29
|
-
@current_tags = []
|
30
|
-
when FeatureParser::SCENARIO_OUTLINE_LINE
|
31
|
-
# ... another is when we hit a subsequent "Scenario Outline:"
|
32
|
-
close_scenario_outline
|
33
|
-
|
34
|
-
@scenario_outline = TagListNode.new($1, @current_tags)
|
35
|
-
@current_tags = []
|
36
|
-
when FeatureParser::EXAMPLE_SET_LINE, FeatureParser::SCENARIO_SET_LINE
|
37
|
-
@scenario_outline.add_to_tag_nodes(@example_set) if @example_set
|
38
|
-
|
39
|
-
@example_set = ExampleSetNode.new($1, @feature.tags | @current_tags)
|
40
|
-
@current_tags = []
|
41
|
-
when @example_set && FeatureParser::EXAMPLE_LINE
|
42
|
-
@example_set.add_child(Node.new($1))
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
# EOF is the final way that we know we are finished with a "Scenario Outline"
|
47
|
-
close_scenario_outline
|
48
|
-
return @feature
|
49
|
-
end
|
50
|
-
|
51
|
-
def close_scenario_outline
|
52
|
-
if @scenario_outline
|
53
|
-
if @example_set
|
54
|
-
@scenario_outline.add_to_tag_nodes(@example_set) if @example_set
|
55
|
-
@example_set = nil
|
56
|
-
end
|
57
|
-
@feature.merge_tag_nodes(@scenario_outline)
|
58
|
-
@scenario_outline = nil
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
end
|
63
|
-
|
64
|
-
end
|