rcor 0.8.1 → 0.9.5

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 (60) hide show
  1. data/Rakefile.rb +1 -1
  2. data/lib/concordion.rb +1 -8
  3. data/lib/concordion_constants.rb +1 -1
  4. data/lib/concordion_css.rb +8 -1
  5. data/lib/concordion_css_decorator.rb +21 -4
  6. data/lib/concordion_error_condition.rb +26 -0
  7. data/lib/concordion_invoker.rb +103 -9
  8. data/lib/concordion_parse_result.rb +19 -1
  9. data/lib/concordion_parser.rb +1 -1
  10. data/lib/concordion_processor.rb +3 -2
  11. data/lib/concordion_string_utility.rb +36 -2
  12. data/lib/concordion_test_case.rb +12 -62
  13. data/lib/concordion_test_methods.rb +127 -0
  14. data/lib/concordion_utility.rb +15 -3
  15. data/lib/goldmaster_test_case.rb +22 -5
  16. data/lib/loader_helper.rb +16 -0
  17. data/nbproject/private/private.xml +0 -6
  18. data/nbproject/private/rake-d.txt +13 -0
  19. data/tests/apostrophe.html +7 -0
  20. data/tests/apostrophe_test.rb +18 -0
  21. data/tests/ariel_example.html +13 -0
  22. data/tests/ariel_example_test.rb +36 -0
  23. data/tests/attr_assert.html +2 -0
  24. data/tests/basic_assert_true_test.rb +5 -1
  25. data/tests/basic_set.html +3 -0
  26. data/tests/basic_text.html +8 -0
  27. data/tests/basic_text_test.rb +11 -0
  28. data/tests/concordion_parse_result_test.rb +16 -1
  29. data/tests/concordion_test.rb +0 -14
  30. data/tests/concordion_utility_test.rb +44 -0
  31. data/tests/failing.html +4 -0
  32. data/tests/failing_test.rb +10 -2
  33. data/tests/goldmaster_assert_true_failing.html +5 -0
  34. data/tests/goldmaster_assert_true_failing_goldmaster.html +169 -0
  35. data/tests/goldmaster_assert_true_failing_test.rb +14 -0
  36. data/tests/goldmaster_failing.html +40 -0
  37. data/tests/goldmaster_failing_goldmaster.html +48 -1
  38. data/tests/goldmaster_failing_test.rb +28 -2
  39. data/tests/goldmaster_malformed.html +7 -0
  40. data/tests/goldmaster_malformed_goldmaster.html +171 -0
  41. data/tests/goldmaster_malformed_test.rb +11 -0
  42. data/tests/goldmaster_passing_goldmaster.html +8 -1
  43. data/tests/goldmaster_table_bug.html +12 -0
  44. data/tests/goldmaster_table_bug_goldmaster.html +176 -0
  45. data/tests/goldmaster_table_bug_test.rb +24 -0
  46. data/tests/goldmaster_table_goldmaster.html +8 -1
  47. data/tests/image.html +5 -0
  48. data/tests/image.jpg +0 -0
  49. data/tests/image_test.rb +9 -0
  50. data/tests/mixed.html +5 -0
  51. data/tests/mixed_test.rb +19 -0
  52. data/tests/no_parens.html +15 -0
  53. data/tests/no_parens_test.rb +20 -0
  54. data/tests/numbers.html +5 -0
  55. data/tests/numbers_test.rb +11 -0
  56. data/tests/verify_rows_scsr_test.rb +2 -0
  57. data/tests/verify_rows_simple.html +14 -0
  58. data/tests/verify_rows_simple_test.rb +17 -0
  59. metadata +31 -4
  60. data/lib/concordion_invocation_string_builder.rb +0 -24
@@ -17,7 +17,7 @@ end
17
17
  task :default => [:clean, :test]
18
18
 
19
19
  PKG_FILES = FileList['**/*'].exclude(/_test_output\.html$/)
20
- PKG_VERSION = '0.8.1'
20
+ PKG_VERSION = '0.9.5'
21
21
 
22
22
  spec = Gem::Specification.new do |s|
23
23
  s.platform = Gem::Platform::RUBY
@@ -1,5 +1,4 @@
1
1
  require 'concordion_utility'
2
- require 'concordion_invocation_string_builder'
3
2
  require 'concordion_lookahead_handler'
4
3
  require 'concordion_verifier'
5
4
  require 'concordion_invoker'
@@ -12,11 +11,10 @@ class Concordion
12
11
  def self.TEXT_VAR
13
12
  @@TEXT_VAR
14
13
  end
15
- attr_reader :verification_variable, :verifier, :invocation_builder
14
+ attr_reader :verification_variable, :verifier
16
15
 
17
16
  def initialize
18
17
  @memory = {}
19
- @invocation_builder = ConcordionInvocationStringBuilder.new(self)
20
18
  @lookahead_handler = ConcordionLookaheadHandler.new
21
19
  @verifier = ConcordionVerifier.new(self)
22
20
  @invoker = ConcordionInvoker.new(self)
@@ -31,9 +29,6 @@ class Concordion
31
29
  @memory[variable]
32
30
  end
33
31
 
34
- def build_invocation_string(conc_call, content)
35
- @invocation_builder.build_invocation_string(conc_call,content)
36
- end
37
32
 
38
33
  def dereference(conc_call)
39
34
  var_name = concordion_variable_name(conc_call)
@@ -61,6 +56,4 @@ class Concordion
61
56
  conc_rv
62
57
  end
63
58
 
64
-
65
-
66
59
  end
@@ -1,7 +1,7 @@
1
1
  module ConcordionConstants
2
2
 
3
3
  def concordion_command_attributes
4
- ["assertequals", "set", "execute", "verifyrows", "asserttrue"].collect do
4
+ ["assertequals", "set", "execute", "verifyrows", "asserttrue", "assert_image"].collect do
5
5
  |cmd| "concordion:#{cmd}"
6
6
  end
7
7
  end
@@ -68,7 +68,7 @@ p.success {
68
68
  padding: 2px;
69
69
  }
70
70
  .concordion_success, .concordion_success * {
71
- background-color: #afa !important;
71
+ background-color: #afa;
72
72
  }
73
73
  .success pre {
74
74
  background-color: #bbffbb;
@@ -82,6 +82,13 @@ p.success {
82
82
  color: #bb5050;
83
83
  }
84
84
 
85
+ td.concordion_failure {
86
+ background-color: #ffb0b0 !important;
87
+ }
88
+ td.concordion_success {
89
+ background-color: #afa !important;
90
+ }
91
+
85
92
  ins {
86
93
  text-decoration: none;
87
94
  }
@@ -1,4 +1,5 @@
1
1
  require 'concordion_css'
2
+ require 'concordion_error_condition'
2
3
 
3
4
  class ConcordionCSSDecorator
4
5
  def add_concordion_css_link(root, html, type)
@@ -39,14 +40,30 @@ class ConcordionCSSDecorator
39
40
  end
40
41
  end
41
42
 
42
- def decorate_tag(rv, tag)
43
+ def decorate_tag(rv, tag, cpr)
44
+ context = tag.to_html
45
+ expected = tag.inner_html
46
+ xpath = tag.xpath
47
+
43
48
  if rv[:result]
44
49
  tag[:class] = 'concordion_success'
45
- return 0
50
+ return nil
46
51
  end
47
52
 
48
53
  tag[:class] = 'concordion_failure'
49
- tag.inner_html += " expected but received #{rv[:actual]}"
50
- 1
54
+ if cpr.is_verify_command?
55
+ if rv[:actual] > rv[:expected]
56
+ diff = rv[:actual] - rv[:expected]
57
+ tag.inner_html += "<tr><td>[#{diff} Surplus Row(s) Returned By Fixture]</td></tr>"
58
+ end
59
+ else
60
+ if cpr.is_assert_true_command?
61
+ tag.inner_html += ": expected true but received #{rv[:actual]}"
62
+ else
63
+ tag.inner_html += " expected but received #{rv[:actual]}"
64
+ end
65
+ end
66
+ #TODO refactor: move some of this logic into the conc parse result?
67
+ ConcordionErrorCondition.new(expected, rv[:actual], xpath, context, cpr.is_assert_true_command?)
51
68
  end
52
69
  end
@@ -0,0 +1,26 @@
1
+ #
2
+ # To change this template, choose Tools | Templates
3
+ # and open the template in the editor.
4
+
5
+
6
+ class ConcordionErrorCondition
7
+ attr_reader :expected, :actual
8
+ def initialize(expected, actual, xpath, context = nil, assert_true_command = false)
9
+ @expected = expected
10
+ @actual = actual
11
+ @xpath = xpath
12
+ @context = context
13
+ @assert_true_command = assert_true_command
14
+ end
15
+
16
+ def to_s
17
+ @expected = "true" if @assert_true_command
18
+
19
+ base = "expected (#{@expected}) but got (#{@actual}) in tag: #{@xpath}"
20
+
21
+
22
+ return base if @context.nil?
23
+
24
+ base + "\n\tcontext of error: #{@context}"
25
+ end
26
+ end
@@ -1,31 +1,125 @@
1
+ require 'loader_helper'
2
+ require 'concordion_utility'
3
+
1
4
  class ConcordionInvoker
5
+ include LoaderHelper
6
+ include ConcordionUtility
7
+
2
8
  def initialize(conc)
3
9
  @concordion = conc
4
- @builder = conc.invocation_builder
5
10
  end
6
11
 
12
+ def try_to_dereference(cpr)
13
+ rv = nil
14
+ begin
15
+ rv = @concordion.dereference(cpr.system_under_test)
16
+ rescue NoMethodError => e
17
+ method = method_from_no_method_error(e)
18
+
19
+ rv = dereference_error_message(e)
20
+ end
21
+ rv
22
+ end
23
+
24
+ def dereference_error_message(e)
25
+ rv = "["
26
+ clazz = e.to_s.split(":")[1]
27
+ if clazz == 'NilClass'
28
+ rv += "No more rows"
29
+ else
30
+ rv += " on #{clazz} but was not found"
31
+ end
32
+ rv += "]"
33
+ end
34
+
35
+
7
36
  def invoke_sut(cpr, test_context)
8
37
  sut_rv = nil
9
38
  if cpr.needs_dereference?
10
- sut_rv = @concordion.dereference(cpr.system_under_test)
39
+ sut_rv = try_to_dereference(cpr)
11
40
  else
12
- invocation_str = @builder.build_invocation_string(cpr.system_under_test, cpr.content)
13
- sut_rv = test_context.instance_eval invocation_str
41
+
42
+ sut_rv = try_to_invoke_sut(cpr,test_context)
14
43
  end
15
44
 
16
45
  sut_rv
17
46
  end
47
+
48
+
49
+ def try_to_invoke_sut(cpr, test_context)
50
+ sut_rv = nil
51
+ begin
52
+ #TODO refactor, inlined/amended from former string builder
53
+ conc_method = concordion_method_name(cpr.system_under_test)
54
+ arg_values = []
55
+ if has_arguments?(cpr.system_under_test)
56
+ arg_vars = concordion_arguments(cpr.system_under_test)
57
+ arg_values = arg_vars.collect {|var|
58
+ if var == '#TEXT'
59
+ escape_single_quotes(cpr.content)
60
+ else
61
+ @concordion.get_variable(var)
62
+ end
63
+ }
64
+ end
65
+ args = arg_values.join(",")
66
+ sut_rv = test_context.send(conc_method, *arg_values)
67
+ rescue NoMethodError => e
68
+
69
+ if e.to_s =~ /nil:NilClass/
70
+ sut_rv = "[Parse failed for: #{cpr}, cause: (#{e})]"
71
+ else
72
+ method = method_from_no_method_error(e)
73
+ clazz = class_from_no_method_error(e)
74
+ sut_rv = "[Missing method '#{method}' in fixture #{clazz} ]"
75
+ end
76
+ end
77
+ sut_rv
78
+ end
79
+
80
+ def method_from_no_method_error(e)
81
+ except_str_from(e).split("`")[1].split("'")[0]
82
+ end
83
+
84
+ def except_str_from(e)
85
+ e.exception.to_s
86
+ end
87
+
88
+ def class_from_no_method_error(e)
89
+ except_str_from(e).split("<")[1].split(":")[0]
90
+ end
91
+
18
92
  def invoke_concordion(cpr, sut_rv)
19
- commands[cpr.concordion_command].call(sut_rv, cpr.content)
93
+ cmd = commands[cpr.concordion_command]
94
+ if cpr.is_assert_image_command?
95
+ cmd.call(sut_rv, cpr.image_location)
96
+ elsif cpr.is_verify_command?
97
+ cmd.call(sut_rv, cpr.num_results_expected)
98
+ else
99
+ cmd.call(sut_rv, cpr.content)
100
+ end
101
+
20
102
  end
21
103
 
22
104
 
23
105
  def commands
24
106
  cmds = {}
25
- cmds["assertequals"] = Proc.new { |a, b| { :result => a == b, :actual => a, :expected => b } }
26
- cmds["execute"] = Proc.new { |a,b| {:result => true, :actual => a, :expected => b } }
27
- cmds["verifyrows"] = Proc.new { |a,b| { :result => true, :actual => a, :expected => b } }
28
- cmds["asserttrue"] = Proc.new { |a, b| { :result => a, :actual => a, :expected => true } }
107
+ cmds["assertequals"] = Proc.new { |a, b|
108
+ result = (a.to_s == b)
109
+ { :result => result, :actual => a, :expected => b } }
110
+ cmds["execute"] = Proc.new { |a,b|
111
+ result = true
112
+ result = false if a.to_s =~ /Missing method/
113
+ {:result => result, :actual => a, :expected => b } }
114
+ cmds["verifyrows"] = Proc.new { |a,b| { :result => a.size == b, :actual => a.size, :expected => b } }
115
+ cmds["asserttrue"] = Proc.new { |a, b|
116
+ result = a
117
+ result = false if a.instance_of?(String)
118
+ { :result => result, :actual => false, :expected => true } }
119
+ cmds["assert_image"] = Proc.new { |actual_data, expected_image_url|
120
+ expected_data = File.read(path_for(expected_image_url))
121
+ { :result => actual_data == expected_data, :actual => "[Image data of size #{actual_data.size} omitted]", :expected => "[Expected to match #{expected_image_url}]" }
122
+ }
29
123
  cmds
30
124
  end
31
125
 
@@ -1,3 +1,5 @@
1
+ require 'concordion_utility'
2
+
1
3
  class ConcordionParseResult
2
4
  include ConcordionUtility
3
5
  attr_accessor :concordion_command, :system_under_test, :content, :tag
@@ -8,9 +10,13 @@ class ConcordionParseResult
8
10
  @tag = tag
9
11
  end
10
12
  def to_s
11
- "CPR: #{@concordion_command}, #{@system_under_test}, #{@content}"
13
+ "Concordion command[#{@concordion_command}], System under test method[#{@system_under_test}], Tag Content[#{@content}] Image Location[#{image_location}]"
12
14
  end
13
15
 
16
+ def is_assert_image_command?
17
+ "assert_image" == @concordion_command
18
+ end
19
+
14
20
  def is_set_command?
15
21
  "set" == @concordion_command
16
22
  end
@@ -20,7 +26,19 @@ class ConcordionParseResult
20
26
  def is_execute_command?
21
27
  "execute" == @concordion_command
22
28
  end
29
+ def is_assert_true_command?
30
+ "asserttrue" == @concordion_command
31
+ end
23
32
 
33
+ def num_results_expected
34
+ @tag.search("tr").size - 1
35
+ end
36
+
37
+ def image_location
38
+ return nil if @tag.nil?
39
+ @tag.get_attribute('src')
40
+ end
41
+
24
42
  def assignment
25
43
  concordion_assignment(@system_under_test)
26
44
  end
@@ -32,7 +32,7 @@ class ConcordionParser
32
32
 
33
33
  def each_eligible_concordion_element(&block)
34
34
  each_concordion_element do |elem|
35
- if concordion_cmd_attr_exists?(elem)
35
+ if concordion_cmd_attr_exists?(elem)
36
36
  attr = concordion_cmd_attr_for(elem)
37
37
  @verifier.update_row(elem)
38
38
  if !@instrumenter.instrument_from_headers(elem, attr, @root)
@@ -11,8 +11,9 @@ class ConcordionProcessor
11
11
  def process(tag, test_context)
12
12
  attr = concordion_cmd_attr_for(tag)
13
13
  instrumented_value = tag.get_attribute(attr)
14
- rv = @concordion.evaluate(create_parse_result(tag, attr, instrumented_value), test_context, self)
15
- @decorator.decorate_tag(rv, tag)
14
+ cpr = create_parse_result(tag, attr, instrumented_value)
15
+ rv = @concordion.evaluate(cpr, test_context, self)
16
+ @decorator.decorate_tag(rv, tag, cpr)
16
17
  end
17
18
 
18
19
  def create_parse_result(tag, attr, value)
@@ -34,9 +34,17 @@ module ConcordionStringUtility
34
34
  include PluralToSingularUtility
35
35
 
36
36
  def has_arguments?(name)
37
- name !~ /\(\)$/
37
+ !(ends_in_empty_parens?(name) || is_direct_method_call?(name))
38
38
  end
39
39
 
40
+ def is_direct_method_call?(name)
41
+ name =~ /^[\w]+$/
42
+ end
43
+
44
+ def ends_in_empty_parens?(name)
45
+ name =~ /\(\)$/
46
+ end
47
+
40
48
  def concordion_assignment(name)
41
49
  name.split("=")[0].strip
42
50
  end
@@ -45,19 +53,45 @@ module ConcordionStringUtility
45
53
  name =~ /=/
46
54
  end
47
55
 
48
-
56
+ def attr_writer_method?(name)
57
+ name =~ /=$/
58
+ end
59
+
49
60
  def concordion_method_name(name)
50
61
  if name =~ /\(/
51
62
  base = name.split("(")[0].strip
52
63
  else
64
+
65
+
53
66
  base = name.strip
67
+ if base =~ /\s/
68
+
69
+ if base =~ /=/ && base =~ /^#/
70
+ base = base.split("=")[1].strip
71
+ end
72
+ elements = base.split(/\s/)
73
+ base = elements[0]
74
+ end
54
75
  end
55
76
 
56
77
  if !has_assignment?(base)
57
78
  return base
58
79
  end
80
+
81
+ if attr_writer_method?(base)
82
+ return base if base.count("=") == 1
83
+ return assignment(base) + "="
84
+ end
85
+
86
+ assignment(base)
87
+ end
59
88
 
89
+ def assignment(base)
60
90
  base.split("=")[1].strip
61
91
  end
92
+
93
+ def escape_single_quotes(s)
94
+ s.gsub(/[']/, '\\\\\\\\\'')
95
+ end
62
96
 
63
97
  end
@@ -10,50 +10,26 @@ require 'concordion'
10
10
  require 'concordion_css_decorator'
11
11
  require 'test/unit'
12
12
 
13
- class ConcordionTestCase < Test::Unit::TestCase
13
+ require 'concordion_test_methods'
14
14
 
15
- @@EXPECTED_FAILURE_COUNT = 0
16
15
 
17
- include ConcordionUtility
16
+ class ConcordionTestCase < Test::Unit::TestCase
18
17
 
19
- def self.inherited(subclass)
20
- subclass.class_eval do
21
- define_method :test_spec do
22
- filename = snake_cased_test_name(subclass.to_s)
23
- parse_spec(filename)
24
- run_spec(filename)
25
- report_spec(filename)
26
- end
27
- end
28
- subclass
18
+ include ConcordionConfigMethods
19
+ extend ConcordionConfigMethods
20
+ include ConcordionInternalTestMethods
21
+ class << self
22
+ alias_method :original_inherited, :inherited
29
23
  end
30
24
 
31
- def self.default_config
32
- concordion = Concordion.new
33
- parser = ConcordionParser.new(ConcordionReader.new, concordion)
34
- decorator = ConcordionCSSDecorator.new
35
- processor = ConcordionProcessor.new(concordion, decorator)
36
- { :expected_failure_count => @@EXPECTED_FAILURE_COUNT,
37
- :parser => parser,
38
- :writer => ConcordionWriter.new(ConcordionEnvironment.output_dir),
39
- :concordion => concordion,
40
- :decorator => decorator,
41
- :processor => processor,
42
- :write_goldmaster => false,
43
- :css_type => ConcordionEnvironment.css_type
44
- }
25
+ def self.inherited(subclass)
26
+ original_inherited(subclass)
27
+ bind_test_method_to(subclass, default_config)
45
28
  end
46
29
 
47
- def initialize(arg, conf = ConcordionTestCase.default_config)
30
+ def initialize(arg, conf = default_config())
48
31
  super(arg)
49
- config = ConcordionTestCase.default_config.merge(conf)
50
- @parser = config[:parser]
51
- @writer = config[:writer]
52
- @concordion = config[:concordion]
53
- @decorator = config[:decorator]
54
- @expected_failure_count = config[:expected_failure_count]
55
- @processor = config[:processor]
56
- @css_type = config[:css_type]
32
+ @config = default_config.merge(conf)
57
33
  end
58
34
 
59
35
  def test_something_trivial_to_shut_runit_up
@@ -68,30 +44,4 @@ class ConcordionTestCase < Test::Unit::TestCase
68
44
  @trivial
69
45
  end
70
46
 
71
- def parse_spec(filename)
72
- @parser.parse(filename)
73
- assert_concordion_document
74
- @decorator.add_concordion_css_link(@parser.root, @parser.html, @css_type)
75
- end
76
-
77
- def run_spec(filename)
78
- @failures = 0
79
- @parser.each_eligible_concordion_element do |elem|
80
- @failures += @processor.process(elem, self)
81
- end
82
- end
83
-
84
- def report_spec(filename)
85
- @decorator.add_css_file_to_output_dir(@writer, @css_type)
86
- outfilename = @writer.calculate_filename_and_overwrite(@parser.root, filename)
87
- assert_no_failures(@failures, outfilename)
88
- end
89
-
90
- def assert_no_failures(failures, outfilename)
91
- assert_equal @expected_failure_count, failures, "Wrote output to #{outfilename}"
92
- end
93
-
94
- def assert_concordion_document
95
- assert_equal "http://www.concordion.org/2007/concordion", @parser.html.get_attribute("xmlns:concordion")
96
- end
97
47
  end