Permalink
Browse files

[#18 state:resolved] Added TableBodyMatcher.

  • Loading branch information...
1 parent 176ab7a commit 894cd7c75ac4a363f7e77f53cf6ef50f4ed026ea Stephen Anderson committed Jan 4, 2009
Showing with 115 additions and 0 deletions.
  1. +4 −0 lib/html_matchers.rb
  2. +46 −0 lib/matchers/table_matcher.rb
  3. +65 −0 spec/table_matcher_spec.rb
View
@@ -32,6 +32,10 @@ def have_span_text target_id, expected_text
SpanTextMatcher.new target_id, expected_text
end
+ def have_table table_id_or_expected, expected = nil
+ TableMatcher.new table_id_or_expected, expected
+ end
+
def have_table_header table_id_or_expected, expected = nil
TableHeaderMatcher.new table_id_or_expected, expected
end
@@ -0,0 +1,46 @@
+module Spec # :nodoc:
+ module Rails
+ module Matchers
+ class TableMatcher
+
+ def initialize table_id_or_expected, expected
+ case table_id_or_expected
+ when String
+ @table_id = table_id_or_expected
+ @expected = expected
+ when Array
+ @expected = table_id_or_expected
+ end
+ raise 'Invalid "expected" argument' if @expected.nil?
+ end
+
+ def matches? response
+ @actual = extract_html_content response.body
+ @actual == @expected
+ end
+
+ def failure_message
+ "\nWrong table contents.\nexpected: #{@expected.inspect}\n found: #{@actual.inspect}\n\n"
+ end
+
+ def negative_failure_message
+ "\nTable should not have matched: #{@expected.inspect}\n"
+ end
+
+ def extract_html_content html
+ doc = Hpricot.XML(html)
+
+ rows = doc.search("table#{"##{@table_id}" if @table_id} tr")
+ header_elements = rows.select{|e| ! e.search('th').empty? }
+ header_content = header_elements.map{|n| n.search('/th').map{|n| n.inner_text.strip.gsub(/\n \t\t/, "\n")}}
+
+ body_elements = rows.select{|e| ! e.search('td').empty? }
+ body_content = body_elements.map{|n| n.search('/td').map{|n| n.inner_text.strip.gsub(/\n \t\t/, "\n")}}
+
+ header_content + body_content
+ end
+
+ end
+ end
+ end
+end
View
@@ -0,0 +1,65 @@
+require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
+
+describe 'table_matcher' do
+ describe 'with <thead> and <tbody> elements' do
+ it 'should find header and body rows' do
+ response = mock_model(Object, :body => '<table id="my_id"><thead><tr><th>h1</th><th>h2</th></tr></thead><tbody><tr><td>c1</td><td>c2</td></tr></tbody></table>')
+ response.should have_table('my_id', [['h1', 'h2'], ['c1', 'c2']])
+ end
+ end
+
+ describe 'without <thead> and <tbody> elements' do
+ it 'should work' do
+ response = mock_model(Object, :body => '<table id="my_id"><tr><th>h1</th><th>h2</th></tr><tr><td>c1</td><td>c2</td></tr></table>')
+ response.should have_table('my_id', [['h1', 'h2'], ['c1', 'c2']])
+ end
+ end
+
+ it 'can be called without a table_id' do
+ response = mock_model(Object, :body => '<table><tr><td>c1</td><td>c2</td></tr></table>')
+ response.should have_table([['c1', 'c2']])
+ end
+
+ it 'matches multiple body rows' do
+ response = mock_model(Object, :body => '<table><tr><td>c1</td><td>c2</td></tr><tr><td>c3</td><td>c4</td></tr></table>')
+ response.should have_table([['c1', 'c2'], ['c3', 'c4']])
+ end
+
+ describe 'passed wrong id' do
+ it 'should not match' do
+ response = mock_model(Object, :body => '<table id="my_id"><tr><td>c1</td><td>c2</td></tr></table>')
+ response.should_not have_table('wrong_id', [['c1', 'c2']])
+ end
+ end
+
+ describe 'passed non-matching expected' do
+ it 'should not match' do
+ response = mock_model(Object, :body => '<table id="my_id"><tr><td>c1</td><td>c2</td></tr></table>')
+ response.should_not have_table('my_id', [['c3', 'c2']])
+ end
+ end
+
+ describe 'with normal failure' do
+ it 'should raise ExpectationNotMetError with correct message' do
+ response = mock_model Object, :body => 'Some non-matching HTML'
+ lambda do
+ response.should have_table('my_id', [['c1', 'c2']])
+ end.should raise_error(Spec::Expectations::ExpectationNotMetError, "\nWrong table contents.\nexpected: [[\"c1\", \"c2\"]]\n found: []\n\n")
+ end
+ end
+
+ describe 'with negative failure' do
+ it 'should raise ExpectationNotMetError' do
+ response = mock_model Object, :body => '<table id="my_id"><tr><td>c1</td><td>c2</td></tr></table>'
+ lambda{response.should_not have_table('my_id', [['c1', 'c2']])}.should raise_error(Spec::Expectations::ExpectationNotMetError,
+ "\nTable should not have matched: [[\"c1\", \"c2\"]]\n")
+ end
+ end
+
+ describe 'passed nil expected' do
+ it 'should raise error' do
+ response = mock_model(Object, :body => '<table id="my_id"><tr><td>c1</td><td>c2</td></tr></table>')
+ lambda{ response.should have_table('my_id', nil)}.should raise_error(RuntimeError, 'Invalid "expected" argument')
+ end
+ end
+end

0 comments on commit 894cd7c

Please sign in to comment.