diff options
| author | Dan Allen <dan.j.allen@gmail.com> | 2013-01-11 14:28:23 -0700 |
|---|---|---|
| committer | Dan Allen <dan.j.allen@gmail.com> | 2013-01-13 17:09:24 -0700 |
| commit | 31fa4f68947618e27677a2dd7376a9fc080cd15d (patch) | |
| tree | cadbb84ae2787249ec4b8e757463d8561307e239 /test | |
| parent | ad0172ae0d0e3cda65c399e90b8f43fed9474ac6 (diff) | |
fully-compliance AsciiDoc table support (psv, dsv, csv)
- classes to manage table content
- parser method for processing table content
- support for nested tables
- support for tables containing a nested AsciiDoc document
- table templates for HTML5 and DocBook45
- constant for default docbook page width
- optimization for matching any block
- rename :title regex to :blk_title
- change option attributes from foo-option to option-foo
- convenience method for checking for block title
- various compliance fixes
- let literal block masquerade as listing block
- require [source] block attribute to treat listing as source code
- don't clobber custom authorinitials
- additional method on test_helper to perform css assertions
- additional method on test_helper to retrieve xml node for xpath or css
Diffstat (limited to 'test')
| -rw-r--r-- | test/blocks_test.rb | 7 | ||||
| -rw-r--r-- | test/document_test.rb | 16 | ||||
| -rw-r--r-- | test/headers_test.rb | 9 | ||||
| -rw-r--r-- | test/lexer_test.rb | 2 | ||||
| -rw-r--r-- | test/lists_test.rb | 10 | ||||
| -rw-r--r-- | test/paragraphs_test.rb | 2 | ||||
| -rw-r--r-- | test/tables_test.rb | 482 | ||||
| -rw-r--r-- | test/test_helper.rb | 58 |
8 files changed, 564 insertions, 22 deletions
diff --git a/test/blocks_test.rb b/test/blocks_test.rb index cd475b60..a66d7a85 100644 --- a/test/blocks_test.rb +++ b/test/blocks_test.rb @@ -144,7 +144,7 @@ EOS output = render_string(input) assert_xpath '//pre', output, 1 assert_xpath '//pre/text()', output, 1 - text = node_from_string(output, '//pre/text()').content + text = xmlnodes_at_xpath('//pre/text()', output, 1).text lines = text.lines.entries assert_equal 5, lines.size expected = "line one\n\nline two\n\nline three".lines.entries @@ -153,6 +153,7 @@ EOS test "should preserve endlines in listing block" do input = <<-EOS +[source] ---- line one @@ -164,7 +165,7 @@ EOS output = render_string(input) assert_xpath '//pre/code', output, 1 assert_xpath '//pre/code/text()', output, 1 - text = node_from_string(output, '//pre/code/text()').content + text = xmlnodes_at_xpath('//pre/code/text()', output, 1).text lines = text.lines.entries assert_equal 5, lines.size expected = "line one\n\nline two\n\nline three".lines.entries @@ -185,7 +186,7 @@ EOS output = render_string(input) assert_xpath '//*[@class="verseblock"]/pre', output, 1 assert_xpath '//*[@class="verseblock"]/pre/text()', output, 1 - text = node_from_string(output, '//*[@class="verseblock"]/pre/text()').content + text = xmlnodes_at_xpath('//*[@class="verseblock"]/pre/text()', output, 1).text lines = text.lines.entries assert_equal 5, lines.size expected = "line one\n\nline two\n\nline three".lines.entries diff --git a/test/document_test.rb b/test/document_test.rb index 729f905b..6ff731ea 100644 --- a/test/document_test.rb +++ b/test/document_test.rb @@ -24,7 +24,7 @@ context 'Document' do assert !renderer.nil? views = renderer.views assert !views.nil? - assert_equal 25, views.size + assert_equal 26, views.size assert views.has_key? 'document' assert views['document'].is_a?(Asciidoctor::HTML5::DocumentTemplate) end @@ -39,7 +39,7 @@ context 'Document' do assert !renderer.nil? views = renderer.views assert !views.nil? - assert_equal 25, views.size + assert_equal 26, views.size assert views.has_key? 'document' assert views['document'].is_a?(Asciidoctor::DocBook45::DocumentTemplate) end @@ -182,5 +182,17 @@ chapter body assert_xpath '/book/bookinfo/date', result, 1 assert_xpath '/book/simpara[text() = "text"]', result, 1 end + + test 'do not override explicit author initials' do + input = <<-EOS += AsciiDoc +Stuart Rackham <founder@asciidoc.org> +:Author Initials: SJR + +more info... + EOS + output = render_string input, :attributes => {'backend' => 'docbook45'} + assert_xpath '/article/articleinfo/authorinitials[text()="SJR"]', output, 1 + end end end diff --git a/test/headers_test.rb b/test/headers_test.rb index 92ab48a4..2deb374c 100644 --- a/test/headers_test.rb +++ b/test/headers_test.rb @@ -1,3 +1,4 @@ +# encoding: UTF-8 require 'test_helper' context "Headers" do @@ -94,6 +95,14 @@ context "Headers" do test "with custom non-blank idprefix" do assert_xpath "//h2[@id='ref_my_title'][text() = 'My Title']", render_string(":idprefix: ref_\n\n== My Title ") end + + test 'with multibyte characters' do + input = <<-EOS +== Asciidoctor in 中文 + EOS + output = render_string input + assert_xpath '//h2[@id="_asciidoctor_in"][text()="Asciidoctor in 中文"]', output + end end context "level 2" do diff --git a/test/lexer_test.rb b/test/lexer_test.rb index 6e1c5706..c573cc6b 100644 --- a/test/lexer_test.rb +++ b/test/lexer_test.rb @@ -122,7 +122,7 @@ context "Lexer" do test "collect options attribute" do attributes = {} line = "quote, options='opt1,opt2 , opt3'" - expected = {1 => 'quote', 'options' => 'opt1,opt2 , opt3', 'option-opt1' => nil, 'option-opt2' => nil, 'option-opt3' => nil} + expected = {1 => 'quote', 'options' => 'opt1,opt2 , opt3', 'opt1-option' => nil, 'opt2-option' => nil, 'opt3-option' => nil} Asciidoctor::AttributeList.new(line).parse_into(attributes) assert_equal expected, attributes end diff --git a/test/lists_test.rb b/test/lists_test.rb index 606b8949..44edd33d 100644 --- a/test/lists_test.rb +++ b/test/lists_test.rb @@ -2362,6 +2362,7 @@ end context 'Callout lists' do test 'listing block with sequential callouts followed by adjacent callout list' do input = <<-EOS +[source] ---- require 'asciidoctor' # <1> doc = Asciidoctor::Document.new('Hello, World!') # <2> @@ -2385,6 +2386,7 @@ puts doc.render # <3> test 'listing block with sequential callouts followed by non-adjacent callout list' do input = <<-EOS +[source] ---- require 'asciidoctor' # <1> doc = Asciidoctor::Document.new('Hello, World!') # <2> @@ -2412,6 +2414,7 @@ Paragraph. test 'listing block with a callout that refers to two different lines' do input = <<-EOS +[source] ---- require 'asciidoctor' # <1> doc = Asciidoctor::Document.new('Hello, World!') # <2> @@ -2433,6 +2436,7 @@ puts doc.render # <2> test 'listing block with non-sequential callouts followed by adjacent callout list' do input = <<-EOS +[source] ---- require 'asciidoctor' # <2> doc = Asciidoctor::Document.new('Hello, World!') # <3> @@ -2457,11 +2461,13 @@ puts doc.render # <1> test 'two listing blocks can share the same callout list' do input = <<-EOS .Import library +[source] ---- require 'asciidoctor' # <1> ---- .Use library +[source] ---- doc = Asciidoctor::Document.new('Hello, World!') # <2> puts doc.render # <3> @@ -2486,12 +2492,14 @@ puts doc.render # <3> test 'two listing blocks each followed by an adjacent callout list' do input = <<-EOS .Import library +[source] ---- require 'asciidoctor' # <1> ---- <1> Describe the first line .Use library +[source] ---- doc = Asciidoctor::Document.new('Hello, World!') # <1> puts doc.render # <2> @@ -2516,6 +2524,7 @@ puts doc.render # <2> test 'callout list with block content' do input = <<-EOS +[source] ---- require 'asciidoctor' # <1> doc = Asciidoctor::Document.new('Hello, World!') # <2> @@ -2542,6 +2551,7 @@ You can write this to file rather than printing to stdout. test 'escaped callout should not be interpreted as a callout' do input = <<-EOS +[source] ---- require 'asciidoctor' # \\<1> ---- diff --git a/test/paragraphs_test.rb b/test/paragraphs_test.rb index 69a2007a..4f88a770 100644 --- a/test/paragraphs_test.rb +++ b/test/paragraphs_test.rb @@ -39,7 +39,7 @@ You're good to go! end test "listing paragraph" do - assert_xpath "//pre[@class='highlight']", render_string("----\nblah blah blah\n----") + assert_xpath "//pre[@class='highlight']", render_string("[source]\n----\nblah blah blah\n----") end test "source code paragraph" do diff --git a/test/tables_test.rb b/test/tables_test.rb new file mode 100644 index 00000000..351b74e2 --- /dev/null +++ b/test/tables_test.rb @@ -0,0 +1,482 @@ +require 'test_helper' + +context 'Tables' do + + context 'PSV' do + test 'renders simple psv table' do + input = <<-EOS +|======= +|A |B |C +|a |b |c +|1 |2 |3 +|======= + EOS + cells = [%w(A B C), %w(a b c), %w(1 2 3)] + output = render_embedded_string input + assert_css 'table', output, 1 + assert_css 'table.tableblock.frame-all.grid-all[style~="width: 100%;"]', output, 1 + assert_css 'table > colgroup > col[style~="width: 33%;"]', output, 3 + assert_css 'table tr', output, 3 + assert_css 'table > tbody > tr', output, 3 + assert_css 'table td', output, 9 + assert_css 'table > tbody > tr > td.tableblock.halign-left.valign-top > p.tableblock', output, 9 + cells.each_with_index {|row, rowi| + assert_css "table tr:nth-child(#{rowi + 1}) > td", output, row.size + assert_css "table tr:nth-child(#{rowi + 1}) > td > p", output, row.size + row.each_with_index {|cell, celli| + assert_xpath "(//tr)[#{rowi + 1}]/td[#{celli + 1}]/p[text()='#{cell}']", output, 1 + } + } + end + + test 'renders caption on simple psv table' do + input = <<-EOS +.Simple psv table +|======= +|A |B |C +|a |b |c +|1 |2 |3 +|======= + EOS + output = render_embedded_string input + assert_xpath '/table/caption[@class="title"][text()="Simple psv table"]', output, 1 + assert_xpath '/table/caption/following-sibling::colgroup', output, 1 + end + + test 'ignores escaped separators' do + input = <<-EOS +|=== +|A \\| here| a \\| there +|=== + EOS + output = render_embedded_string input + assert_css 'table', output, 1 + assert_css 'table > colgroup > col', output, 2 + assert_css 'table > tbody > tr', output, 1 + assert_css 'table > tbody > tr > td', output, 2 + assert_xpath '/table/tbody/tr/td[1]/p[text()="A | here"]', output, 1 + assert_xpath '/table/tbody/tr/td[2]/p[text()="a | there"]', output, 1 + end + + test 'performs normal substitutions on cell content' do + input = <<-EOS +:show_title: Cool new show +|=== +|{show_title} |Coming soon... +|=== + EOS + output = render_embedded_string input + assert_xpath '//tbody/tr/td[1]/p[text()="Cool new show"]', output, 1 + assert_xpath %(//tbody/tr/td[2]/p[text()='Coming soon#{[8230].pack('U*')}']), output, 1 + end + + test 'table and col width not assigned when autowidth option is specified' do + input = <<-EOS +[options="autowidth"] +|======= +|A |B |C +|a |b |c +|1 |2 |3 +|======= + EOS + output = render_embedded_string input + assert_css 'table', output, 1 + assert_css 'table[style*="width"]', output, 0 + assert_css 'table colgroup col', output, 3 + assert_css 'table colgroup col[width]', output, 0 + end + + test 'first row sets number of columns when not specified' do + input = <<-EOS +|==== +|first |second |third |fourth + +|1 |2 |3 +|4 +|==== + EOS + output = render_embedded_string input + assert_css 'table', output, 1 + assert_css 'table > colgroup > col', output, 4 + assert_css 'table > tbody > tr', output, 2 + assert_css 'table > tbody > tr:nth-child(1) > td', output, 4 + assert_css 'table > tbody > tr:nth-child(2) > td', output, 4 + end + + test 'colspec attribute sets number of columns' do + input = <<-EOS +[cols="3*"] +|=== +|A |B |C |a |b |c |1 |2 |3 +|=== + EOS + output = render_embedded_string input + assert_css 'table', output, 1 + assert_css 'table > tbody > tr', output, 3 + end + + test 'table with explicit column count can have multiple rows on a single line' do + input = <<-EOS +[cols="3*"] +|=== +|one |two +|1 |2 |a |b +|=== + EOS + output = render_embedded_string input + assert_css 'table', output, 1 + assert_css 'table > colgroup > col', output, 3 + assert_css 'table > tbody > tr', output, 2 + end + + test 'table with explicit deprecated syntax column count can have multiple rows on a single line' do + input = <<-EOS +[cols="3"] +|=== +|one |two +|1 |2 |a |b +|=== + EOS + output = render_embedded_string input + assert_css 'table', output, 1 + assert_css 'table > colgroup > col', output, 3 + assert_css 'table > tbody > tr', output, 2 + end + + test 'table with header and footer' do + input = <<-EOS +[frame="topbot",options="header,footer"] +|=== +|Item |Quantity +|Item 1 |1 +|Item 2 |2 +|Item 3 |3 +|Total |6 +|=== + EOS + output = render_embedded_string input + assert_css 'table', output, 1 + assert_css 'table > colgroup > col', output, 2 + assert_css 'table > thead', output, 1 + assert_css 'table > thead > tr', output, 1 + assert_css 'table > thead > tr > th', output, 2 + assert_css 'table > tfoot', output, 1 + assert_css 'table > tfoot > tr', output, 1 + assert_css 'table > tfoot > tr > td', output, 2 + assert_css 'table > tbody', output, 1 + assert_css 'table > tbody > tr', output, 3 + end + + test 'styles not applied to header cells' do + input = <<-EOS +[cols="1h,1s,1e",options="header,footer"] +|==== +|Name |Occupation| Website +|Octocat |Social coding| http://github.com +|Name |Occupation| Website +|==== + EOS + output = render_embedded_string input + assert_css 'table', output, 1 + assert_css 'table > thead > tr > th', output, 3 + assert_css 'table > thead > tr > th > *', output, 0 + + assert_css 'table > tfoot > tr > td', output, 3 + assert_css 'table > tfoot > tr > td > p.header', output, 1 + assert_css 'table > tfoot > tr > td > p > strong', output, 1 + assert_css 'table > tfoot > tr > td > p > em', output, 1 + + assert_css 'table > tbody > tr > td', output, 3 + assert_css 'table > tbody > tr > td > p.header', output, 1 + assert_css 'table > tbody > tr > td > p > strong', output, 1 + assert_css 'table > tbody > tr > td > p > em > a', output, 1 + end + + test 'supports horizontal and vertical source data with blank lines and table header' do + input = <<-EOS +.Horizontal and vertical source data +[width="80%",cols="3,^2,^2,10",options="header"] +|=== +|Date |Duration |Avg HR |Notes + +|22-Aug-08 |10:24 | 157 | +Worked out MSHR (max sustainable heart rate) by going hard +for this interval. + +|22-Aug-08 |23:03 | 152 | +Back-to-back with previous interval. + +|24-Aug-08 |40:00 | 145 | +Moderately hard interspersed with 3x 3min intervals (2 min +hard + 1 min really hard taking the HR up to 160). + +I am getting in shape! + +|=== + EOS + output = render_embedded_string input + assert_css 'table', output, 1 + assert_css 'table[style~="width: 80%;"]', output, 1 + assert_xpath '/table/caption[@class="title"][text()="Horizontal and vertical source data"]', output, 1 + assert_css 'table > colgroup > col', output, 4 + assert_css 'table > colgroup > col:nth-child(1)[@style~="width: 17%;"]', output, 1 + assert_css 'table > colgroup > col:nth-child(2)[@style~="width: 11%;"]', output, 1 + assert_css 'table > colgroup > col:nth-child(3)[@style~="width: 11%;"]', output, 1 + assert_css 'table > colgroup > col:nth-child(4)[@style~="width: 58%;"]', output, 1 + assert_css 'table > thead', output, 1 + assert_css 'table > thead > tr', output, 1 + assert_css 'table > thead > tr > th', output, 4 + assert_css 'table > tbody > tr', output, 3 + assert_css 'table > tbody > tr:nth-child(1) > td', output, 4 + assert_css 'table > tbody > tr:nth-child(2) > td', output, 4 + assert_css 'table > tbody > tr:nth-child(3) > td', output, 4 + assert_xpath "/table/tbody/tr[1]/td[4]/p[text()='Worked out MSHR (max sustainable heart rate) by going hard\nfor this interval.']", output, 1 + assert_css 'table > tbody > tr:nth-child(3) > td:nth-child(4) > p', output, 2 + assert_xpath '/table/tbody/tr[3]/td[4]/p[2][text()="I am getting in shape!"]', output, 1 + end + + test 'spans, alignments and styles' do + input = <<-EOS +[cols="e,m,^,>s",width="25%"] +|=== +|1 >s|2 |3 |4 +^|5 2.2+^.^|6 .3+<.>m|7 +^|8 +|9 2+>|10 +|=== + EOS + output = render_embedded_string input + assert_css 'table', output, 1 + assert_css 'table > colgroup > col[style~="width: 25%;"]', output, 4 + assert_css 'table > tbody > tr', output, 4 + assert_css 'table > tbody > tr > td', output, 10 + assert_css 'table > tbody > tr:nth-child(1) > td', output, 4 + assert_css 'table > tbody > tr:nth-child(2) > td', output, 3 + assert_css 'table > tbody > tr:nth-child(3) > td', output, 1 + assert_css 'table > tbody > tr:nth-child(4) > td', output, 2 + + assert_css 'table tr:nth-child(1) > td:nth-child(1).halign-left.valign-top p em', output, 1 + assert_css 'table tr:nth-child(1) > td:nth-child(2).halign-right.valign-top p strong', output, 1 + assert_css 'table tr:nth-child(1) > td:nth-child(3).halign-center.valign-top p', output, 1 + assert_css 'table tr:nth-child(1) > td:nth-child(3).halign-center.valign-top p *', output, 0 + assert_css 'table tr:nth-child(1) > td:nth-child(4).halign-right.valign-top p strong', output, 1 + + assert_css 'table tr:nth-child(2) > td:nth-child(1).halign-center.valign-top p em', output, 1 + assert_css 'table tr:nth-child(2) > td:nth-child(2).halign-center.valign-middle[colspan="2"][rowspan="2"] p tt', output, 1 + assert_css 'table tr:nth-child(2) > td:nth-child(3).halign-left.valign-bottom[rowspan="3"] p tt', output, 1 + + assert_css 'table tr:nth-child(3) > td:nth-child(1).halign-center.valign-top p em', output, 1 + + assert_css 'table tr:nth-child(4) > td:nth-child(1).halign-left.valign-top p em', output, 1 + assert_css 'table tr:nth-child(4) > td:nth-child(2).halign-right.valign-top[colspan="2"] p tt', output, 1 + end + + test 'supports repeating cells' do + input = <<-EOS +|=== +3*|A +|1 3*|2 +|b |c +|=== + EOS + output = render_embedded_string input + assert_css 'table', output, 1 + assert_css 'table > colgroup > col', output, 3 + assert_css 'table > tbody > tr', output, 3 + assert_css 'table > tbody > tr:nth-child(1) > td', output, 3 + assert_css 'table > tbody > tr:nth-child(2) > td', output, 3 + assert_css 'table > tbody > tr:nth-child(3) > td', output, 3 + + assert_xpath '/table/tbody/tr[1]/td[1]/p[text()="A"]', output, 1 + assert_xpath '/table/tbody/tr[1]/td[2]/p[text()="A"]', output, 1 + assert_xpath '/table/tbody/tr[1]/td[3]/p[text()="A"]', output, 1 + + assert_xpath '/table/tbody/tr[2]/td[1]/p[text()="1"]', output, 1 + assert_xpath '/table/tbody/tr[2]/td[2]/p[text()="2"]', output, 1 + assert_xpath '/table/tbody/tr[2]/td[3]/p[text()="2"]', output, 1 + + assert_xpath '/table/tbody/tr[3]/td[1]/p[text()="2"]', output, 1 + assert_xpath '/table/tbody/tr[3]/td[2]/p[text()="b"]', output, 1 + assert_xpath '/table/tbody/tr[3]/td[3]/p[text()="c"]', output, 1 + end + + test 'paragraph, verse and literal content' do + input = <<-EOS +[cols=",^v,^l",options="header"] +|=== +|Paragraphs |Verse |Literal +3*|The discussion about what is good, +what is beautiful, what is noble, +what is pure, and what is true +could always go on. + +Why is that important? +Why would I like to do that? + +Because that's the only conversation worth having. + +And whether it goes on or not after I die, I don't know. +But, I do know that it is the conversation I want to have while I am still alive. + +Which means that to me the offer of certainty, +the offer of complete security, +the offer of an impermeable faith that can't give way +is an offer of something not worth having. + +I want to live my life taking the risk all the time +that I don't know anything like enough yet... +that I haven't understood enough... +that I can't know enough... +that I am always hungrily operating on the margins +of a potentially great harvest of future knowledge and wisdom. + +I wouldn't have it any other way. +|=== + EOS + output = render_embedded_string input + assert_css 'table', output, 1 + assert_css 'table > colgroup > col', output, 3 + assert_css 'table > thead', output, 1 + assert_css 'table > thead > tr', output, 1 + assert_css 'table > thead > tr > th', output, 3 + assert_css 'table > tbody', output, 1 + assert_css 'table > tbody > tr', output, 1 + assert_css 'table > tbody > tr > td', output, 3 + assert_css 'table > tbody > tr > td:nth-child(1).halign-left.valign-top > p.tableblock', output, 7 + assert_css 'table > tbody > tr > td:nth-child(2).halign-center.valign-top > div.verse', output, 1 + verse = xmlnodes_at_css 'table > tbody > tr > td:nth-child(2).halign-center.valign-top > div.verse', output, 1 + assert_equal 26, verse.text.lines.entries.size + assert_css 'table > tbody > tr > td:nth-child(3).halign-center.valign-top > div.literal > pre', output, 1 + literal = xmlnodes_at_css 'table > tbody > tr > td:nth-child(3).halign-center.valign-top > div.literal > pre', output, 1 + assert_equal 26, literal.text.lines.entries.size + end + + test 'asciidoc content' do + input = <<-EOS +[cols="1e,1,5a",frame="topbot",options="header"] +|=== +|Name |Backends |Description + +|badges |xhtml11, html5 | +Link badges ('XHTML 1.1' and 'CSS') in document footers. + +NOTE: The path names of images, icons and scripts are relative path +names to the output document not the source document. + +|[[X97]] docinfo, docinfo1, docinfo2 |All backends | +These three attributes control which document information +files will be included in the the header of the output file: + +docinfo:: Include `<filename>-docinfo.<ext>` +docinfo1:: Include `docinfo.<ext>` +docinfo2:: Include `docinfo.<ext>` and `<filename>-docinfo.<ext>` + +Where `<filename>` is the file name (sans extension) of the AsciiDoc +input file and `<ext>` is `.html` for HTML outputs or `.xml` for +DocBook outputs. If the input file is the standard input then the +output file name is used. +|=== + EOS + doc = document_from_string input + table = doc.blocks.first + assert !table.nil? + tbody = table.rows.body + assert_equal 2, tbody.size + body_cell_1_3 = tbody[0][2] + assert !body_cell_1_3.inner_document.nil? + assert body_cell_1_3.inner_document.nested + output = doc.render + + assert_css 'table > tbody > tr', output, 2 + assert_css 'table > tbody > tr:nth-child(1) > td:nth-child(3) div.admonitionblock', output, 1 + assert_css 'table > tbody > tr:nth-child(2) > td:nth-child(3) div.dlist', output, 1 + end + + test 'nested table' do + input = <<-EOS +[cols="1,2a"] +|=== +|Normal cell + +|Cell with nested table + +[cols="2,1"] +!=== +!Nested table cell 1 !Nested table cell 2 +!=== + +|=== + EOS + output = render_embedded_string input + assert_css 'table', output, 2 + assert_css 'table table', output, 1 + assert_css 'table table', output, 1 + assert_css 'table > tbody > tr > td:nth-child(2) table', output, 1 + assert_css 'table > tbody > tr > td:nth-child(2) table > tbody > tr > td', output, 2 + end + end + + context 'DSV' do + + test 'renders simple dsv table' do + input = <<-EOS +[width="75%",format="dsv"] +|=== +root:x:0:0:root:/root:/bin/bash +bin:x:1:1:bin:/bin:/sbin/nologin +mysql:x:27:27:MySQL\\:Server:/var/lib/mysql:/bin/bash +gdm:x:42:42::/var/lib/gdm:/sbin/nologin +sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin +nobody:x:99:99:Nobody:/:/sbin/nologin +|=== + EOS + output = render_embedded_string input + assert_css 'table', output, 1 + assert_css 'table > colgroup > col[style~="width: 14%;"]', output, 7 + assert_css 'table > tbody > tr', output, 6 + assert_xpath '//tr[4]/td[5]/p/text()', output, 0 + assert_xpath '//tr[3]/td[5]/p[text()="MySQL:Server"]', output, 1 + end + end + + context 'CSV' do + + test 'mixed unquoted records and quoted records with escaped quotes, commas and wrapped lines' do + input = <<-EOS +[format="csv",options="header"] +|=== +Year,Make,Model,Description,Price +1997,Ford,E350,"ac, abs, moon",3000.00 +1999,Chevy,"Venture ""Extended Edition""","",4900.00 +1999,Chevy,"Venture ""Extended Edition, Very Large""",,5000.00 +1996,Jeep,Grand Cherokee,"MUST SELL! +air, moon roof, loaded",4799.00 +|=== + EOS + output = render_embedded_string input + assert_css 'table', output, 1 + assert_css 'table > colgroup > col[style~="width: 20%;"]', output, 5 + assert_css 'table > thead > tr', output, 1 + assert_css 'table > tbody > tr', output, 4 + assert_xpath '((//tbody/tr)[1]/td)[4]/p[text()="ac, abs, moon"]', output, 1 + assert_xpath %(((//tbody/tr)[2]/td)[3]/p[text()='Venture "Extended Edition"']), output, 1 + assert_xpath '((//tbody/tr)[4]/td)[4]/p[text()="MUST SELL! air, moon roof, loaded"]', output, 1 + end + + test 'custom separator' do + input = <<-EOS +[format="csv", separator=";"] +|=== +a;b;c +1;2;3 +|=== + EOS + output = render_embedded_string input + assert_css 'table', output, 1 + assert_css 'table > colgroup > col', output, 3 + assert_css 'table > tbody > tr', output, 2 + assert_css 'table > tbody > tr:nth-child(1) > td', output, 3 + assert_css 'table > tbody > tr:nth-child(2) > td', output, 3 + end + end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index 7205d7e7..01c8d005 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -53,16 +53,53 @@ class Test::Unit::TestCase end end - def node_from_string(html, xpath = nil) - doc = (html =~ /\s*<!DOCTYPE/) ? Nokogiri::HTML::Document.parse(html) : Nokogiri::HTML::DocumentFragment.parse(html) - if xpath.nil? - doc - else - doc.xpath("#{xpath.sub('/', './')}").first + def xmlnodes_at_css(css, content, count = nil) + xmlnodes_at_path(:css, css, content) + end + + def xmlnodes_at_xpath(css, content, count = nil) + xmlnodes_at_path(:css, css, content) + end + + def xmlnodes_at_path(type, path, content, count = nil) + doc = xmldoc_from_string content + case type + when :xpath + results = doc.xpath("#{path.sub('/', './')}") + when :css + results = doc.css(path) end + count == 1 ? results.first : results + end + + def assert_css(css, content, count = nil) + assert_path(:css, css, content, count) end def assert_xpath(xpath, content, count = nil) + assert_path(:xpath, xpath, content, count) + end + + def assert_path(type, path, content, count = nil) + case type + when :xpath + type_name = 'XPath' + when :css + type_name = 'CSS' + end + + results = xmlnodes_at_path type, path, content + + if (count && results.length != count) + flunk "#{type_name} #{path} yielded #{results.length} elements rather than #{count} for:\n#{content}" + elsif (count.nil? && results.empty?) + flunk "#{type_name} #{path} not found in:\n#{content}" + else + assert true + end + end + + def xmldoc_from_string(content) match = content.match(/\s*<!DOCTYPE (.*)/) if !match doc = Nokogiri::HTML::DocumentFragment.parse(content) @@ -71,15 +108,6 @@ class Test::Unit::TestCase else doc = Nokogiri::XML::Document.parse(content) end - results = doc.xpath("#{xpath.sub('/', './')}") - - if (count && results.length != count) - flunk "XPath #{xpath} yielded #{results.length} elements rather than #{count} for:\n#{content}" - elsif (count.nil? && results.empty?) - flunk "XPath #{xpath} not found in:\n#{content}" - else - assert true - end end def document_from_string(src, opts = {}) |
