rcor 0.8.1
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/Rakefile.rb +39 -0
- data/lib/concordion.rb +66 -0
- data/lib/concordion_binder.rb +24 -0
- data/lib/concordion_constants.rb +13 -0
- data/lib/concordion_css.rb +172 -0
- data/lib/concordion_css_decorator.rb +52 -0
- data/lib/concordion_environment.rb +28 -0
- data/lib/concordion_instrumenter.rb +30 -0
- data/lib/concordion_invocation_string_builder.rb +24 -0
- data/lib/concordion_invoker.rb +33 -0
- data/lib/concordion_lookahead_handler.rb +17 -0
- data/lib/concordion_parse_result.rb +31 -0
- data/lib/concordion_parser.rb +47 -0
- data/lib/concordion_processor.rb +24 -0
- data/lib/concordion_reader.rb +18 -0
- data/lib/concordion_string_utility.rb +63 -0
- data/lib/concordion_string_writer.rb +13 -0
- data/lib/concordion_test_case.rb +97 -0
- data/lib/concordion_utility.rb +70 -0
- data/lib/concordion_verifier.rb +50 -0
- data/lib/concordion_writer.rb +43 -0
- data/lib/goldmaster_test_case.rb +32 -0
- data/lib/rcor.rb +2 -0
- data/nbproject/private/config.properties +0 -0
- data/nbproject/private/private.properties +4 -0
- data/nbproject/private/private.xml +10 -0
- data/nbproject/project.properties +11 -0
- data/nbproject/project.xml +16 -0
- data/test-lib/single_row_result.rb +9 -0
- data/test-lib/user.rb +8 -0
- data/tests/attr_assert.html +5 -0
- data/tests/attr_assert_test.rb +13 -0
- data/tests/basic_assert.html +5 -0
- data/tests/basic_assert_test.rb +9 -0
- data/tests/basic_assert_true.html +6 -0
- data/tests/basic_assert_true_test.rb +11 -0
- data/tests/basic_set.html +8 -0
- data/tests/basic_set_test.rb +8 -0
- data/tests/basic_text.html +6 -0
- data/tests/basic_text_test.rb +12 -0
- data/tests/concordion.css +2 -0
- data/tests/concordion_css_decorator_test.rb +28 -0
- data/tests/concordion_environment_test.rb +44 -0
- data/tests/concordion_parse_result_test.rb +33 -0
- data/tests/concordion_test.rb +49 -0
- data/tests/concordion_utility_test.rb +88 -0
- data/tests/concordion_verifier_test.rb +38 -0
- data/tests/concordion_writer_test.rb +26 -0
- data/tests/failing.html +5 -0
- data/tests/failing_test.rb +15 -0
- data/tests/goldmaster_failing.html +5 -0
- data/tests/goldmaster_failing_goldmaster.html +162 -0
- data/tests/goldmaster_failing_test.rb +11 -0
- data/tests/goldmaster_passing.html +5 -0
- data/tests/goldmaster_passing_goldmaster.html +162 -0
- data/tests/goldmaster_passing_test.rb +9 -0
- data/tests/goldmaster_table.html +46 -0
- data/tests/goldmaster_table_goldmaster.html +203 -0
- data/tests/goldmaster_table_test.rb +17 -0
- data/tests/lookahead_assert_true.html +25 -0
- data/tests/lookahead_assert_true_test.rb +17 -0
- data/tests/nested_element_lookahead.html +9 -0
- data/tests/nested_element_lookahead_test.rb +8 -0
- data/tests/processes_elements_in_sorted_order.html +12 -0
- data/tests/processes_elements_in_sorted_order_test.rb +13 -0
- data/tests/return_result.html +7 -0
- data/tests/return_result_test.rb +17 -0
- data/tests/single_row_table.html +13 -0
- data/tests/single_row_table_test.rb +9 -0
- data/tests/table.html +28 -0
- data/tests/table_test.rb +9 -0
- data/tests/test_helper.rb +9 -0
- data/tests/verify_rows.html +46 -0
- data/tests/verify_rows_scsr.html +27 -0
- data/tests/verify_rows_scsr_test.rb +15 -0
- data/tests/verify_rows_test.rb +16 -0
- metadata +142 -0
data/Rakefile.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/packagetask'
|
4
|
+
require 'rake/gempackagetask'
|
5
|
+
require 'rake/clean'
|
6
|
+
require 'lib/concordion_environment'
|
7
|
+
|
8
|
+
CLEAN.include(ConcordionEnvironment.clean_list)
|
9
|
+
|
10
|
+
Rake::TestTask.new do |t|
|
11
|
+
t.libs << "test-lib"
|
12
|
+
t.libs << "tests"
|
13
|
+
t.test_files = FileList['tests/*_test.rb']
|
14
|
+
t.verbose = true
|
15
|
+
end
|
16
|
+
|
17
|
+
task :default => [:clean, :test]
|
18
|
+
|
19
|
+
PKG_FILES = FileList['**/*'].exclude(/_test_output\.html$/)
|
20
|
+
PKG_VERSION = '0.8.1'
|
21
|
+
|
22
|
+
spec = Gem::Specification.new do |s|
|
23
|
+
s.platform = Gem::Platform::RUBY
|
24
|
+
s.summary = "Ruby based concordion"
|
25
|
+
s.name = 'rcor'
|
26
|
+
s.version = PKG_VERSION
|
27
|
+
s.author = 'Ben Goodspeed'
|
28
|
+
s.email = 'b.goodspeed@gmail.com'
|
29
|
+
s.add_dependency('hpricot', '>= 0.6')
|
30
|
+
s.requirements << 'hpricot HTML parser'
|
31
|
+
s.require_path = 'lib'
|
32
|
+
s.autorequire = 'rake'
|
33
|
+
s.files = PKG_FILES
|
34
|
+
end
|
35
|
+
|
36
|
+
Rake::GemPackageTask.new(spec) { |pkg|
|
37
|
+
pkg.need_zip = true
|
38
|
+
pkg.need_tar = true
|
39
|
+
}
|
data/lib/concordion.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'concordion_utility'
|
2
|
+
require 'concordion_invocation_string_builder'
|
3
|
+
require 'concordion_lookahead_handler'
|
4
|
+
require 'concordion_verifier'
|
5
|
+
require 'concordion_invoker'
|
6
|
+
require 'concordion_binder'
|
7
|
+
|
8
|
+
class Concordion
|
9
|
+
include ConcordionUtility
|
10
|
+
|
11
|
+
@@TEXT_VAR = "#TEXT"
|
12
|
+
def self.TEXT_VAR
|
13
|
+
@@TEXT_VAR
|
14
|
+
end
|
15
|
+
attr_reader :verification_variable, :verifier, :invocation_builder
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
@memory = {}
|
19
|
+
@invocation_builder = ConcordionInvocationStringBuilder.new(self)
|
20
|
+
@lookahead_handler = ConcordionLookaheadHandler.new
|
21
|
+
@verifier = ConcordionVerifier.new(self)
|
22
|
+
@invoker = ConcordionInvoker.new(self)
|
23
|
+
@binder = ConcordionBinder.new(self)
|
24
|
+
set_variable(@@TEXT_VAR, @@TEXT_VAR)
|
25
|
+
end
|
26
|
+
def set_variable(variable, value)
|
27
|
+
@memory[variable] = value
|
28
|
+
end
|
29
|
+
|
30
|
+
def get_variable(variable)
|
31
|
+
@memory[variable]
|
32
|
+
end
|
33
|
+
|
34
|
+
def build_invocation_string(conc_call, content)
|
35
|
+
@invocation_builder.build_invocation_string(conc_call,content)
|
36
|
+
end
|
37
|
+
|
38
|
+
def dereference(conc_call)
|
39
|
+
var_name = concordion_variable_name(conc_call)
|
40
|
+
var = get_variable(var_name)
|
41
|
+
|
42
|
+
if !has_property_reference?(conc_call)
|
43
|
+
return var
|
44
|
+
end
|
45
|
+
|
46
|
+
var.send(concordion_property_reference(conc_call))
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
def evaluate(cpr, test_context, processor)
|
51
|
+
@lookahead_handler.handle_lookahead(cpr, test_context, processor)
|
52
|
+
|
53
|
+
return { :result => true } if @binder.bind_if_set_command(cpr)
|
54
|
+
|
55
|
+
@verifier.update_if_verify_command(cpr)
|
56
|
+
|
57
|
+
sut_rv = @invoker.invoke_sut(cpr, test_context)
|
58
|
+
@binder.handle_assignment(cpr, sut_rv)
|
59
|
+
conc_rv = @invoker.invoke_concordion(cpr, sut_rv)
|
60
|
+
|
61
|
+
conc_rv
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'concordion_utility'
|
2
|
+
|
3
|
+
class ConcordionBinder
|
4
|
+
include ConcordionUtility
|
5
|
+
|
6
|
+
def initialize(concordion)
|
7
|
+
@concordion = concordion
|
8
|
+
end
|
9
|
+
def bind_if_set_command(cpr)
|
10
|
+
if cpr.is_set_command?
|
11
|
+
@concordion.set_variable(cpr.system_under_test, cpr.content)
|
12
|
+
true
|
13
|
+
else
|
14
|
+
false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def handle_assignment(cpr, sut_rv)
|
19
|
+
if has_assignment?(cpr.system_under_test)
|
20
|
+
@concordion.set_variable(concordion_assignment(cpr.system_under_test), sut_rv)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module ConcordionConstants
|
2
|
+
|
3
|
+
def concordion_command_attributes
|
4
|
+
["assertequals", "set", "execute", "verifyrows", "asserttrue"].collect do
|
5
|
+
|cmd| "concordion:#{cmd}"
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
def supported?(tagname)
|
10
|
+
['p', 'span', 'b', 'th', 'tr', 'div'].include?(tagname.downcase)
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
module ConcordionCSS
|
4
|
+
def self.css_filename
|
5
|
+
"concordion.css"
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.css_string
|
9
|
+
css = <<-eoscss
|
10
|
+
* {
|
11
|
+
font-family: Arial;
|
12
|
+
}
|
13
|
+
body {
|
14
|
+
padding: 32px;
|
15
|
+
}
|
16
|
+
pre {
|
17
|
+
padding: 6px 28px 6px 28px;
|
18
|
+
background-color: #E8EEF7;
|
19
|
+
}
|
20
|
+
pre, pre *, code, kbd {
|
21
|
+
font-family: Courier New, Courier;
|
22
|
+
font-size: 10pt;
|
23
|
+
}
|
24
|
+
h1, h1 * {
|
25
|
+
font-size: 24pt;
|
26
|
+
}
|
27
|
+
p, td, th, li, .breadcrumbs {
|
28
|
+
font-size: 10pt;
|
29
|
+
}
|
30
|
+
p, li {
|
31
|
+
line-height: 140%;
|
32
|
+
}
|
33
|
+
table {
|
34
|
+
border-collapse: collapse;
|
35
|
+
empty-cells: show;
|
36
|
+
margin: 8px 0px 8px 0px;
|
37
|
+
}
|
38
|
+
th, td {
|
39
|
+
border: 1px solid black;
|
40
|
+
padding: 3px;
|
41
|
+
}
|
42
|
+
td {
|
43
|
+
background-color: white;
|
44
|
+
vertical-align: top;
|
45
|
+
}
|
46
|
+
th {
|
47
|
+
background-color: #C3D9FF;
|
48
|
+
}
|
49
|
+
li {
|
50
|
+
margin-top: 6px;
|
51
|
+
margin-bottom: 6px;
|
52
|
+
}
|
53
|
+
|
54
|
+
|
55
|
+
.example {
|
56
|
+
padding: 2px 12px 6px 12px;
|
57
|
+
border: 1px solid #C3D9FF;
|
58
|
+
margin: 6px 0px 28px 0px;
|
59
|
+
background-color: #F5F9FD;
|
60
|
+
}
|
61
|
+
.example h3 {
|
62
|
+
margin-top: 8px;
|
63
|
+
margin-bottom: 8px;
|
64
|
+
font-size: 12pt;
|
65
|
+
}
|
66
|
+
|
67
|
+
p.success {
|
68
|
+
padding: 2px;
|
69
|
+
}
|
70
|
+
.concordion_success, .concordion_success * {
|
71
|
+
background-color: #afa !important;
|
72
|
+
}
|
73
|
+
.success pre {
|
74
|
+
background-color: #bbffbb;
|
75
|
+
}
|
76
|
+
.concordion_failure, .concordion_failure * {
|
77
|
+
background-color: #ffb0b0;
|
78
|
+
padding: 1px;
|
79
|
+
}
|
80
|
+
.concordion_failure .expected {
|
81
|
+
text-decoration: line-through;
|
82
|
+
color: #bb5050;
|
83
|
+
}
|
84
|
+
|
85
|
+
ins {
|
86
|
+
text-decoration: none;
|
87
|
+
}
|
88
|
+
|
89
|
+
.exceptionMessage {
|
90
|
+
background-color: #fdd;
|
91
|
+
font-family: Courier New, Courier, Monospace;
|
92
|
+
font-size: 10pt;
|
93
|
+
display: block;
|
94
|
+
font-weight: normal;
|
95
|
+
padding: 4px;
|
96
|
+
text-decoration: none !important;
|
97
|
+
}
|
98
|
+
.stackTrace, .stackTrace * {
|
99
|
+
font-weight: normal;
|
100
|
+
}
|
101
|
+
.stackTrace {
|
102
|
+
display: none;
|
103
|
+
padding: 1px 4px 4px 4px;
|
104
|
+
background-color: #fdd;
|
105
|
+
border-top: 1px dotted black;
|
106
|
+
}
|
107
|
+
.stackTraceExceptionMessage {
|
108
|
+
display: block;
|
109
|
+
font-family: Courier New, Courier, Monospace;
|
110
|
+
font-size: 8pt;
|
111
|
+
white-space: wrap;
|
112
|
+
padding: 1px 0px 1px 0px;
|
113
|
+
}
|
114
|
+
.stackTraceEntry {
|
115
|
+
white-space: nowrap;
|
116
|
+
font-family: Courier New, Courier, Monospace;
|
117
|
+
display: block;
|
118
|
+
font-size: 8pt;
|
119
|
+
padding: 1px 0px 1px 32px;
|
120
|
+
}
|
121
|
+
.stackTraceButton {
|
122
|
+
font-size: 8pt;
|
123
|
+
margin: 2px 8px 2px 0px;
|
124
|
+
font-weight: normal;
|
125
|
+
font-family: Arial;
|
126
|
+
}
|
127
|
+
|
128
|
+
.special {
|
129
|
+
font-style: italic;
|
130
|
+
}
|
131
|
+
.missing, .missing * {
|
132
|
+
background-color: #ff9999;
|
133
|
+
}
|
134
|
+
.surplus, .surplus * {
|
135
|
+
background-color: #ff9999;
|
136
|
+
}
|
137
|
+
.footer {
|
138
|
+
text-align: right;
|
139
|
+
margin-top: 40px;
|
140
|
+
font-size: 8pt;
|
141
|
+
width: 100%;
|
142
|
+
color: #999;
|
143
|
+
}
|
144
|
+
.footer .testTime {
|
145
|
+
padding: 2px 10px 0px 0px;
|
146
|
+
}
|
147
|
+
|
148
|
+
.idea {
|
149
|
+
font-size: 9pt;
|
150
|
+
color: #888;
|
151
|
+
font-style: italic;
|
152
|
+
}
|
153
|
+
.tight li {
|
154
|
+
margin-top: 1px;
|
155
|
+
margin-bottom: 1px;
|
156
|
+
}
|
157
|
+
.commentary {
|
158
|
+
float: right;
|
159
|
+
width: 200px;
|
160
|
+
background-color: #ffffd0;
|
161
|
+
padding:8px;
|
162
|
+
border: 3px solid #eeeeb0;
|
163
|
+
margin: 10px 0px 10px 10px;
|
164
|
+
}
|
165
|
+
.commentary, .commentary * {
|
166
|
+
font-size: 8pt;
|
167
|
+
}
|
168
|
+
eoscss
|
169
|
+
|
170
|
+
css.strip
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'concordion_css'
|
2
|
+
|
3
|
+
class ConcordionCSSDecorator
|
4
|
+
def add_concordion_css_link(root, html, type)
|
5
|
+
if html.at("head").nil?
|
6
|
+
root.search("html").prepend('<head></head>')
|
7
|
+
end
|
8
|
+
#TODO add an environment variable for this?
|
9
|
+
if type == :link
|
10
|
+
link_to_css(html)
|
11
|
+
else
|
12
|
+
inline_css(html)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def append_to_head(html, s)
|
17
|
+
html.search("head").append(s)
|
18
|
+
end
|
19
|
+
def link_to_css(html)
|
20
|
+
append_to_head(html, "<link rel='stylesheet' type='text/css' href='#{css_filename}' />")
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
def inline_css(html)
|
25
|
+
append_to_head(html, "<style type='text/css'>#{css}</style>")
|
26
|
+
end
|
27
|
+
|
28
|
+
def css
|
29
|
+
ConcordionCSS.css_string
|
30
|
+
end
|
31
|
+
|
32
|
+
def css_filename
|
33
|
+
ConcordionCSS.css_filename
|
34
|
+
end
|
35
|
+
|
36
|
+
def add_css_file_to_output_dir(writer, type)
|
37
|
+
if !writer.output_file_exists?(css_filename) && type == :link
|
38
|
+
writer.calculate_filename_and_overwrite(css, css_filename)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def decorate_tag(rv, tag)
|
43
|
+
if rv[:result]
|
44
|
+
tag[:class] = 'concordion_success'
|
45
|
+
return 0
|
46
|
+
end
|
47
|
+
|
48
|
+
tag[:class] = 'concordion_failure'
|
49
|
+
tag.inner_html += " expected but received #{rv[:actual]}"
|
50
|
+
1
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
class ConcordionEnvironment
|
3
|
+
def self.output_dir_key
|
4
|
+
'RCOR_OUTPUT_DIR'
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.css_type_key
|
8
|
+
'RCOR_CSS_TYPE'
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.with_dir(str)
|
12
|
+
File.join(output_dir, str)
|
13
|
+
end
|
14
|
+
def self.clean_list
|
15
|
+
[with_dir("*_test_output.html"), with_dir("concordion.css")] #TODO is this safe to delete? what if the user overwrites this file?
|
16
|
+
end
|
17
|
+
|
18
|
+
#TODO dry this up
|
19
|
+
def self.css_type
|
20
|
+
type = ENV[css_type_key]
|
21
|
+
type.nil? ? :inline : type.to_sym
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.output_dir
|
25
|
+
dir = ENV[output_dir_key]
|
26
|
+
dir.nil? ? "." : dir
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
|
2
|
+
class ConcordionInstrumenter
|
3
|
+
@@TH_CSS_QUERY_REGEXP = /tr:nth\(\d+\) > th:nth\((\d+)\)$/
|
4
|
+
@@TH_CSS_SINGLE_REGEXP = /tr:nth\(\d+\) > th$/
|
5
|
+
|
6
|
+
def instrument_from_headers(elem, attr, root)
|
7
|
+
header = @@TH_CSS_QUERY_REGEXP.match(elem.css_path)
|
8
|
+
if header
|
9
|
+
instrument_column(elem, attr, header.captures, @@TH_CSS_QUERY_REGEXP, root)
|
10
|
+
return true
|
11
|
+
end
|
12
|
+
|
13
|
+
single_header = @@TH_CSS_SINGLE_REGEXP.match(elem.css_path)
|
14
|
+
if single_header
|
15
|
+
instrument_column(elem, attr, 0, @@TH_CSS_SINGLE_REGEXP, root)
|
16
|
+
return true
|
17
|
+
end
|
18
|
+
|
19
|
+
false
|
20
|
+
end
|
21
|
+
|
22
|
+
def instrument_column(elem, attr, column_number, regex, root)
|
23
|
+
trimmed = elem.css_path.sub(regex, '')
|
24
|
+
td_css_query = trimmed + "tr > td:nth(#{column_number})"
|
25
|
+
|
26
|
+
value = elem.get_attribute(attr)
|
27
|
+
root.search(td_css_query).set(attr, value)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'concordion_utility'
|
2
|
+
|
3
|
+
|
4
|
+
class ConcordionInvocationStringBuilder
|
5
|
+
include ConcordionUtility
|
6
|
+
def initialize(concordion)
|
7
|
+
@concordion = concordion
|
8
|
+
end
|
9
|
+
|
10
|
+
def build_invocation_string(conc_call, content)
|
11
|
+
base = "self.send('#{concordion_method_name(conc_call)}'"
|
12
|
+
if has_arguments?(conc_call)
|
13
|
+
arg_vars = concordion_arguments(conc_call)
|
14
|
+
arg_values = arg_vars.collect {|var| "'#{@concordion.get_variable(var)}'" }
|
15
|
+
|
16
|
+
args = arg_values.join(", ")
|
17
|
+
base += ", " + args
|
18
|
+
end
|
19
|
+
|
20
|
+
rv = base + ")"
|
21
|
+
|
22
|
+
rv.gsub(Concordion.TEXT_VAR, content)
|
23
|
+
end
|
24
|
+
end
|