reportbuilder 0.1.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/History.txt ADDED
@@ -0,0 +1,6 @@
1
+ === 1.0.0 / 2009-08-12
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
data/Manifest.txt ADDED
@@ -0,0 +1,20 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ bin/reportbuilder
6
+ data/reportbuilder.css
7
+ data/reportbuilder.js
8
+ lib/reportbuilder/generator.rb
9
+ lib/reportbuilder/generator/html.rb
10
+ lib/reportbuilder/generator/text.rb
11
+ lib/reportbuilder.rb
12
+ lib/reportbuilder/section.rb
13
+ lib/reportbuilder/table.rb
14
+ lib/reportbuilder/table/htmlgenerator.rb
15
+ lib/reportbuilder/table/textgenerator.rb
16
+ test/test_html.rb
17
+ test/test_reportbuilder.rb
18
+ test/test_section.rb
19
+ test/test_table.rb
20
+
data/README.txt ADDED
@@ -0,0 +1,34 @@
1
+ = reportbuilder
2
+
3
+ * http://ruby-statsample.rubyforge.org/reportbuilder
4
+
5
+ == DESCRIPTION:
6
+
7
+ Report Abstract Interface. Creates text, html and pdf output, based on a common framework
8
+
9
+ == FEATURES
10
+
11
+ * One interface, multiple outputs
12
+
13
+ == SYNOPSIS:
14
+
15
+ rb=ReportBuilder.new
16
+ rb.add("This is a text")
17
+ table=rb.table(%w{id name})
18
+ table.add_row([1,"Nombre"])
19
+ table.add_hr
20
+ rb.add(table)
21
+ puts rb.to_text
22
+ puts rb.to_html
23
+ puts rb.to_pdf
24
+
25
+ == REQUIREMENTS:
26
+
27
+
28
+ == INSTALL:
29
+
30
+ sudo gem install reportbuilder
31
+
32
+ == LICENSE:
33
+
34
+ GPL-2
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/ruby
2
+ # -*- ruby -*-
3
+ $:.unshift(File.dirname(__FILE__)+"/lib")
4
+ require 'rubygems'
5
+ require 'hoe'
6
+ require 'reportbuilder'
7
+
8
+ Hoe.spec 'reportbuilder' do
9
+ self.version=ReportBuilder::VERSION
10
+ self.rubyforge_name = 'ruby-statsample'
11
+ self.developer('Claudio Bustos', 'clbustos_at_gmail.com')
12
+ self.url = "http://rubyforge.org/projects/ruby-statsample/"
13
+
14
+ end
15
+
16
+ # vim: syntax=ruby
data/bin/reportbuilder ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ abort "you need to write me"
File without changes
File without changes
@@ -0,0 +1,99 @@
1
+ require 'fileutils'
2
+ class ReportBuilder
3
+ class Generator
4
+
5
+ class Html < Generator
6
+ PREFIX="html"
7
+ attr_reader :toc
8
+ def initialize(builder)
9
+ super
10
+ @body=""
11
+ @toc=[]
12
+ @table_n=1
13
+ @entry_n=1
14
+ @list_tables=[]
15
+ @headers=[]
16
+ @footers=[]
17
+ end
18
+ def parse
19
+ parse_cycle(@builder)
20
+ end
21
+ def out
22
+ out="<html><head><title>#{@builder.name}</title>"
23
+ out << @headers.join("\n")
24
+ out << "</head><body>\n"
25
+ out << "<h1>#{@builder.name}</h1>"
26
+ if (@list_tables.size>0)
27
+ out << "<div class='tot'><div class='title'>List of tables</div><ul>"
28
+ @list_tables.each {|anchor,name|
29
+ out << "<li><a href='#"+anchor+"'>#{name}</a></li>"
30
+ }
31
+ out << "</ul></div>\n"
32
+ end
33
+ if(@toc.size>0)
34
+ out << "<div class='toc'><div class='title'>List of contents</div></div>"
35
+ actual_level=0
36
+ @toc.each do |anchor,name,level|
37
+ if actual_level!=level
38
+ if actual_level > level
39
+ (actual_level-level).times { out << "</ul>\n"}
40
+ else
41
+ (level-actual_level).times { out << "<ul>\n"}
42
+ end
43
+ end
44
+ out << "<li><a href='##{anchor}'>#{name}</a></li>\n"
45
+ actual_level=level
46
+ end
47
+ actual_level.times { out << "</ul>\n"}
48
+ out << "</div>\n"
49
+ end
50
+ out << @body
51
+ out << @footers.join("\n")
52
+ out << "</body></html>"
53
+ end
54
+ def add_js(js)
55
+ if(File.exists? js)
56
+ if(!File.exists? @builder.dir+"/js/"+File.basename(js))
57
+ FileUtils.mkdir @builder.dir+"/js"
58
+ FileUtils.cp js,@builder.dir+"/js/"+File.basename(js)
59
+ end
60
+ @headers.push("<script type='text/javascript' src='js/#{File.basename(js)}'></script>")
61
+ end
62
+ end
63
+
64
+ def add_css(css)
65
+ if(File.exists? css)
66
+ if(!File.exists? @builder.dir+"/css/"+File.basename(css))
67
+ FileUtils.mkdir @builder.dir+"/css"
68
+ FileUtils.cp css,@builder.dir+"/css/"+File.basename(css)
69
+ end
70
+ @headers.push("<link rel='stylesheet' type='text/css' href='css/#{File.basename(css)}' />")
71
+ end
72
+ end
73
+
74
+
75
+ def add_text(t)
76
+ ws=(" "*parse_level*2)
77
+ @body << ws << "<pre>#{t}</pre>\n"
78
+ end
79
+ def add_raw(t)
80
+ ws=(" "*parse_level*2)
81
+ @body << ws << t << "\n"
82
+ end
83
+ def add_toc_entry(name)
84
+ anchor="toc_#{@entry_n}"
85
+ @entry_n+=1
86
+ @toc.push([anchor, name, parse_level])
87
+ anchor
88
+ end
89
+ # Add an entry for a table
90
+ # Returns the name of the anchor
91
+ def add_table_entry(name)
92
+ anchor="table_#{@table_n}"
93
+ @table_n+=1
94
+ @list_tables.push([anchor,name])
95
+ anchor
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,25 @@
1
+ class ReportBuilder
2
+ class Generator
3
+ class Text < Generator
4
+ PREFIX="text"
5
+ attr_reader :toc
6
+ attr_reader :out
7
+ def initialize(builder)
8
+ super
9
+ @out=""
10
+ end
11
+ def parse
12
+ @out="Report: #{@builder.name}\n"
13
+ parse_cycle(@builder)
14
+ @out << "\n"
15
+ end
16
+ def add_text(t)
17
+ ws=" "*parse_level*2
18
+ @out << ws << t << "\n"
19
+ end
20
+ def add_text_raw(t)
21
+ @out << t
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,40 @@
1
+ class ReportBuilder
2
+ # Abstract class for generators.
3
+ # A generator is a class which control the output for a builder.
4
+ # On parse_cycle()....
5
+ #
6
+ class Generator
7
+ #PREFIX="none"
8
+ attr_reader :parse_level
9
+ # builder is a ReportBuilder object
10
+ def initialize(builder)
11
+ @builder=builder
12
+ @parse_level=0
13
+ end
14
+ # parse each element of the parameters
15
+ def parse_cycle(container)
16
+ @parse_level+=1
17
+ container.elements.each do |element|
18
+ method=("to_rb_"+self.class::PREFIX).intern
19
+ if element.respond_to? method
20
+ element.send(method, self)
21
+ else
22
+ add_text(element.to_s)
23
+ end
24
+ end
25
+ @parse_level-=1
26
+ end
27
+ def add_text(t)
28
+ raise "Implement this"
29
+ end
30
+ end
31
+ class ElementGenerator
32
+ def initialize(generator,element)
33
+ @element=element
34
+ @generator=generator
35
+ end
36
+ end
37
+ end
38
+
39
+ require 'reportbuilder/generator/text'
40
+ require 'reportbuilder/generator/html'
@@ -0,0 +1,48 @@
1
+ # Creates a Section
2
+ class ReportBuilder::Section
3
+ @@n=1
4
+ attr_reader :parent, :elements, :name
5
+ def initialize(name=nil)
6
+ if name.nil?
7
+ @name="Section #{@nn}"
8
+ @nn+=1
9
+ else
10
+ @name=name
11
+ end
12
+ @parent = nil
13
+ @elements = []
14
+ end
15
+ def parent=(sect)
16
+ if sect.is_a? ReportBuilder::Section
17
+ @parent=sect
18
+ else
19
+ raise ArgumentError("Parent should be a Section")
20
+ end
21
+ end
22
+
23
+ def to_rb_text(generator)
24
+ generator.add_text(("="*generator.parse_level)+" "+name)
25
+ generator.parse_cycle(self)
26
+ end
27
+
28
+ def to_rb_html(generator)
29
+ htag="h#{generator.parse_level+1}"
30
+ anchor=generator.add_toc_entry(name)
31
+ generator.add_raw "<div class='section'><#{htag}>#{name}</#{htag}><a name='#{anchor}'></a>"
32
+ generator.parse_cycle(self)
33
+ generator.add_raw "</div>"
34
+ end
35
+
36
+ def add(*elements)
37
+ elements.each do |element|
38
+ if element.is_a? ReportBuilder::Section
39
+ element.parent=self
40
+ end
41
+ if element.respond_to?(:to_reportbuilder)
42
+ @elements.push(element.to_reportbuilder)
43
+ else
44
+ @elements.push(element)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,50 @@
1
+ class ReportBuilder
2
+ class Table
3
+ class HtmlGenerator < ElementGenerator
4
+ def generate()
5
+ t=@element
6
+ anchor=@generator.add_table_entry(t.name)
7
+ out="<a name='#{anchor}'></a><table>"
8
+ @rowspans=[]
9
+ if t.header.size>0
10
+ out+="<thead>"+parse_row(t,t.header,"th")+"</thead>\n"
11
+ end
12
+ out+="<tbody>\n"
13
+ next_class=""
14
+ t.rows.each{|row|
15
+ if row==:hr
16
+ next_class="top"
17
+ else
18
+ class_tag=(next_class=="")?"":" class ='#{next_class}' "
19
+ out+="<tr#{class_tag}>"+parse_row(t,row)+"</tr>\n"
20
+ next_class=""
21
+ end
22
+ }
23
+ out+="</tbody>\n</table>\n"
24
+ @generator.add_raw(out)
25
+ end
26
+ def parse_row(t,row,tag="td")
27
+ row_ary=[]
28
+ colspan_i=0
29
+ row.each_index do |i|
30
+ if !@rowspans[i].nil? and @rowspans[i]>0
31
+ @rowspans[i]-=1
32
+ elsif colspan_i>0
33
+ colspan_i-=1
34
+ elsif row[i].is_a? Table::Colspan
35
+ row_ary.push(sprintf("<%s colspan=\"%d\">%s</%s>",tag, row[i].cols, row[i].data,tag))
36
+ colspan_i=row[i].cols-1
37
+ elsif row[i].nil?
38
+ row_ary.push("<#{tag}></#{tag}>")
39
+ elsif row[i].is_a? Table::Rowspan
40
+ row_ary.push(sprintf("<%s rowspan=\"%d\">%s</%s>", tag, row[i].rows, row[i].data, tag))
41
+ @rowspans[i]=row[i].rows-1
42
+ else
43
+ row_ary.push("<#{tag}>#{row[i]}</#{tag}>")
44
+ end
45
+ end
46
+ row_ary.join("")
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,53 @@
1
+ class ReportBuilder
2
+ class Table
3
+ class TextGenerator < ElementGenerator
4
+
5
+ def generate()
6
+ t=@element
7
+ t.calculate_widths
8
+ total_width=t.total_width
9
+ out=""
10
+ if t.header.size>0
11
+ out+=parse_hr(total_width)+"\n"
12
+ out+=parse_row(t,t.header)+"\n"
13
+ out+=parse_hr(total_width)+"\n"
14
+ end
15
+ t.rows.each do |row|
16
+ if row==:hr
17
+ out+=parse_hr(total_width)+"\n"
18
+ else
19
+ out+=parse_row(t,row)+"\n"
20
+ end
21
+ end
22
+ out+=parse_hr(total_width)+"\n"
23
+ @generator.add_text(out)
24
+ end
25
+ # Parse a row
26
+ def parse_row(t,row)
27
+ row_ary=[]
28
+ colspan_i=0
29
+ row.each_index do |i|
30
+ if colspan_i>0
31
+ colspan_i-=1
32
+ elsif row[i].is_a? ReportBuilder::Table::Colspan
33
+ size = (i...(i+row[i].cols)).inject(0) {|a,v| a+t.max_cols[v]+3}
34
+ size-=3
35
+ row_ary.push(row[i].data.to_s+" "*(size - row[i].data.size))
36
+ colspan_i=row[i].cols-1
37
+ elsif row[i].nil?
38
+ row_ary.push(" "*t.max_cols[i])
39
+ else
40
+ size=row[i].to_s.size
41
+ #puts sprintf("%i : %s (%d-%d)",i,row[i].to_s,@max_cols[i], size)
42
+ row_ary.push(row[i].to_s+" "*(t.max_cols[i] - size))
43
+ end
44
+ end
45
+ "| "+row_ary.join(" | ")+" |"
46
+ end
47
+ # Parse a horizontal rule
48
+ def parse_hr(l)
49
+ "-"*l
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,137 @@
1
+ class ReportBuilder
2
+ # Creates a table.
3
+ # Use:
4
+ # table=ReportBuilder::Table.new(:header =>["id","city","name","code1","code2"])
5
+ # table.add_row([1, Table.rowspan("New York",3), "Ringo", Table.colspan("no code",2),nil])
6
+ # table.add_row([2, nil,"John", "ab-1","ab-2"])
7
+ # table.add_row([3, nil,"Paul", "ab-3"])
8
+ # table.add_hr
9
+ # table.add_row([4, "London","George", Table.colspan("ab-4",2),nil])
10
+ # puts table
11
+ # ==>
12
+ # -----------------------------------------
13
+ # | id | city | name | code1 | code2 |
14
+ # -----------------------------------------
15
+ # | 1 | New York | Ringo | no code |
16
+ # | 2 | | John | ab-1 | ab-2 |
17
+ # | 3 | | Paul | ab-3 | |
18
+ # -----------------------------------------
19
+ # | 4 | London |George | ab-4 |
20
+ # -----------------------------------------
21
+ class Table
22
+ @@n=1
23
+ # :nodoc:
24
+ DEFAULT_OPTIONS={
25
+ :header => [],
26
+ :name => nil
27
+ }
28
+ # Array of headers
29
+ attr_accessor :header, :name
30
+ # Size for each column
31
+ attr_reader :max_cols
32
+ # Array of rows
33
+ attr_reader :rows
34
+ # Create a new table.
35
+ # Options: :name, :header
36
+ # Use:
37
+ # table=ReportBuilder::Table.new(:header =>["var1","var2"])
38
+ def initialize(opts=Hash.new)
39
+ opts=DEFAULT_OPTIONS.merge opts
40
+ if opts[:name].nil?
41
+ @name= "Table #{@@n}"
42
+ @@n+=1
43
+ else
44
+ @name=opts[:name]
45
+ end
46
+ @header=opts[:header]
47
+ @rows=[]
48
+ @max_cols=[]
49
+ end
50
+ # Adds a row
51
+ # table.add_row(%w{1 2})
52
+ def add_row(row)
53
+ @rows.push(row)
54
+ end
55
+ # Adds a horizontal rule
56
+ # table.add_hr
57
+ def add_hr
58
+ @rows.push(:hr)
59
+ end
60
+ # Adds a rowspan on a cell
61
+ # table.add_row(["a",table.rowspan("b",2)])
62
+ def rowspan(data,n)
63
+ Rowspan.new(data,n)
64
+ end
65
+ # Adds a colspan on a cell
66
+ # table.add_row(["a",table.colspan("b",2)])
67
+
68
+ def colspan(data,n)
69
+ Colspan.new(data,n)
70
+ end
71
+ def calculate_widths # :nodoc:
72
+ @max_cols=[]
73
+ rows_cal=[header]+@rows
74
+ rows_cal.each{|row|
75
+ next if row==:hr
76
+ row.each_index{|i|
77
+ if row[i].nil?
78
+ next
79
+ elsif row[i].is_a? Colspan
80
+ size_total=row[i].data.to_s.size
81
+ size_per_column=(size_total / row[i].cols)+1
82
+ for mi in i...i+row[i].cols
83
+ @max_cols[mi] = size_per_column if @max_cols[mi].nil? or @max_cols[mi]<size_per_column
84
+ end
85
+ elsif row[i].is_a? Rowspan
86
+ size=row[i].data.to_s.size
87
+ @max_cols[i]= size if @max_cols[i].nil? or @max_cols[i] < size
88
+ else
89
+
90
+ size=row[i].to_s.size
91
+ @max_cols[i]= size if @max_cols[i].nil? or @max_cols[i] < size
92
+ end
93
+ }
94
+ }
95
+ end
96
+ def to_rb_text(generator)
97
+ require 'reportbuilder/table/textgenerator'
98
+ table_generator=ReportBuilder::Table::TextGenerator.new( generator, self)
99
+ table_generator.generate
100
+ end
101
+ def to_rb_html(generator)
102
+ require 'reportbuilder/table/htmlgenerator'
103
+ table_generator=ReportBuilder::Table::HtmlGenerator.new(generator, self)
104
+ table_generator.generate
105
+ end
106
+
107
+ def total_width # :nodoc:
108
+ @max_cols.inject(0){|a,v| a+(v+3)}+1
109
+ end
110
+ ######################
111
+ # INTERNAL CLASSES #
112
+ ######################
113
+
114
+ class Rowspan # :nodoc:
115
+ attr_accessor :data, :rows
116
+ def initialize(data,rows)
117
+ @data=data
118
+ @rows=rows
119
+ end
120
+ def to_s
121
+ @data.to_s
122
+ end
123
+ end
124
+
125
+ class Colspan # :nodoc:
126
+ attr_accessor :data, :cols
127
+ def initialize(data,cols)
128
+ @data=data
129
+ @cols=cols
130
+ end
131
+ def to_s
132
+ @data.to_s
133
+ end
134
+ end
135
+ end
136
+ end
137
+
@@ -0,0 +1,58 @@
1
+ require 'reportbuilder/table'
2
+ require 'reportbuilder/section'
3
+ require 'reportbuilder/generator'
4
+
5
+ class ReportBuilder
6
+ attr_reader :elements
7
+ attr_reader :name
8
+ attr_reader :dir
9
+ VERSION = '0.1.0'
10
+ # Create a new Report
11
+ def initialize(name=nil,dir=nil)
12
+ name||="Report "+Time.new.to_s
13
+ dir||=Dir.pwd
14
+ @dir=dir
15
+ @name=name
16
+ @elements=Array.new
17
+ end
18
+ # Add an element to the report.
19
+ # If parameters is an object which respond to :to_reportbuilder,
20
+ # this method will called.
21
+ # Otherwise, the element itself will be added
22
+ def add(*elements)
23
+ elements.each do |element|
24
+ if element.respond_to?(:to_reportbuilder)
25
+ @elements.push(element.to_reportbuilder)
26
+ else
27
+ @elements.push(element)
28
+ end
29
+ end
30
+ end
31
+ # Returns a Section
32
+ def section(name)
33
+ Section.new(name)
34
+ end
35
+ # Returns a Table
36
+ def table(h=[])
37
+ Table.new(h)
38
+ end
39
+ # Returns an Html output
40
+ def to_html
41
+ gen=Generator::Html.new(self)
42
+ gen.parse
43
+ gen.out
44
+ end
45
+ def save_html(file)
46
+ gen=Generator::Html.new(self)
47
+ gen.parse
48
+ File.open(@dir+"/"+file,"wb") {|fp|
49
+ fp.write(gen.out)
50
+ }
51
+ end
52
+ # Returns a Text output
53
+ def to_s
54
+ gen=Generator::Text.new(self)
55
+ gen.parse
56
+ gen.out
57
+ end
58
+ end
data/test/test_html.rb ADDED
@@ -0,0 +1,47 @@
1
+ require "test/unit"
2
+ $:.unshift(File.dirname(__FILE__)+"/../lib")
3
+ require "reportbuilder"
4
+ require 'fileutils'
5
+ require 'tmpdir'
6
+ class TestReportbuilderHtml < Test::Unit::TestCase
7
+ def setup
8
+ @tmpdir=Dir::mktmpdir
9
+ @rp=ReportBuilder.new("Test Html", @tmpdir)
10
+ @datadir=File.dirname(__FILE__)+"/../data"
11
+ end
12
+ def teardown
13
+ FileUtils.remove_entry_secure @tmpdir
14
+ end
15
+ def test_include_js
16
+ mock_element = ""
17
+ eval(" class << mock_element
18
+ def to_rb_html(generator)
19
+ generator.add_js('"+@datadir+"/reportbuilder.js')
20
+ end
21
+ end ")
22
+ @rp.add(mock_element)
23
+ assert_match(/script.+js\/reportbuilder.js/, @rp.to_html)
24
+ assert(File.exists? @tmpdir+"/js/reportbuilder.js")
25
+ end
26
+ def test_save_html
27
+ exp=@rp.to_html
28
+ @rp.save_html("test.html")
29
+ obt=""
30
+ File.open(@tmpdir+"/test.html","r") {|fp|
31
+ obt=fp.readlines(nil)[0]
32
+ }
33
+ assert_equal(exp,obt)
34
+ end
35
+ def test_include_css
36
+ mock_element = ""
37
+ eval(" class << mock_element
38
+ def to_rb_html(generator)
39
+ generator.add_css('"+@datadir+"/reportbuilder.css')
40
+ end
41
+ end ")
42
+ @rp.add(mock_element)
43
+ assert_match(/link rel='stylesheet'.+css\/reportbuilder.css/, @rp.to_html)
44
+ assert(File.exists? @tmpdir+"/css/reportbuilder.css")
45
+ end
46
+
47
+ end
@@ -0,0 +1,22 @@
1
+ require "test/unit"
2
+ $:.unshift(File.dirname(__FILE__)+"/../lib")
3
+ require "reportbuilder"
4
+
5
+ class TestReportbuilder < Test::Unit::TestCase
6
+ # adding basic object
7
+ def test_basic_generators
8
+ # basic_classes = Array,String,Integer, Float,Time,Hash
9
+ ary=[1,2,3]
10
+ str="1,2,3"
11
+ int=1
12
+ flt=1.0
13
+ rat=1.quo(2)
14
+ tim=Time.new
15
+ has={'a'=>1,'b'=>2}
16
+ rb=ReportBuilder.new
17
+ rb.add(ary,str,int,flt,rat,tim,has)
18
+ assert_nothing_raised do
19
+ rb.to_s
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,56 @@
1
+ require "test/unit"
2
+ $:.unshift(File.dirname(__FILE__)+"/../lib")
3
+ require "reportbuilder"
4
+
5
+ class TestReportbuilderSection < Test::Unit::TestCase
6
+ def setup
7
+ @rp=ReportBuilder.new("Test Report")
8
+ s1=@rp.section("Section 1")
9
+ @rp.add s1
10
+ s1.add("Texto 1")
11
+ s1.add(2)
12
+ s11=@rp.section("Section 1.1")
13
+ s1.add s11
14
+ s1.add("Texto 1.1")
15
+ s2=@rp.section("Section 2")
16
+ @rp.add s2
17
+ end
18
+ def test_section_text
19
+ expected= <<-HERE
20
+ Report: Test Report
21
+ = Section 1
22
+ Texto 1
23
+ 2
24
+ == Section 1.1
25
+ Texto 1.1
26
+ = Section 2
27
+
28
+ HERE
29
+ assert_equal(expected, @rp.to_s)
30
+ end
31
+ def test_section_html
32
+ expected= <<-HERE
33
+ <html><head><title>Test Report</title></head><body>
34
+ <h1>Test Report</h1><div class='toc'><div class='title'>List of contents</div></div><ul>
35
+ <li><a href='#toc_1'>Section 1</a></li>
36
+ <ul>
37
+ <li><a href='#toc_2'>Section 1.1</a></li>
38
+ </ul>
39
+ <li><a href='#toc_3'>Section 2</a></li>
40
+ </ul>
41
+ </div>
42
+ <div class='section'><h2>Section 1</h2><a name='toc_1'></a>
43
+ <pre>Texto 1</pre>
44
+ <pre>2</pre>
45
+ <div class='section'><h3>Section 1.1</h3><a name='toc_2'></a>
46
+ </div>
47
+ <pre>Texto 1.1</pre>
48
+ </div>
49
+ <div class='section'><h2>Section 2</h2><a name='toc_3'></a>
50
+ </div>
51
+ </body></html>
52
+ HERE
53
+ assert_equal(expected.gsub(/\s/,""), @rp.to_html.gsub(/\s/,""))
54
+ end
55
+
56
+ end
@@ -0,0 +1,87 @@
1
+ require "test/unit"
2
+ $:.unshift(File.dirname(__FILE__)+"/../lib")
3
+ require "reportbuilder"
4
+ require "reportbuilder/table/htmlgenerator"
5
+ require "reportbuilder/table/textgenerator"
6
+
7
+ class TestReportbuilderTable < Test::Unit::TestCase
8
+ def setup
9
+ super
10
+ table=ReportBuilder::Table.new(:header=>%w{a bb ccc dddd eeee fff gggg hh i})
11
+ table.add_row(["a","b","c","d","e","f","g","h","i"])
12
+ table.add_row([table.colspan("a",2),nil,"c",table.rowspan("d",2),"e","f","g","h","i"])
13
+ table.add_row([table.colspan("a",3),nil,nil,nil,"e","f","g","h","i"])
14
+ table.add_row([table.colspan("a",4),nil,nil,nil,"e","f","g","h","i"])
15
+ table.add_row([table.colspan("a",5),nil,nil,nil,nil,table.colspan("f",3),nil,nil,"i"])
16
+ table.add_row([table.colspan("a",6),nil,nil,nil,nil,nil,"g","h","i"])
17
+ @table=table
18
+
19
+ @mock_generator = ""
20
+ class << @mock_generator
21
+ def add_raw(t)
22
+ replace(t)
23
+ end
24
+ def add_text(t)
25
+ replace(t)
26
+ end
27
+ def add_table_entry(t)
28
+ "MOCK"
29
+ end
30
+ end
31
+
32
+ end
33
+ def test_table_text
34
+
35
+ tg=ReportBuilder::Table::TextGenerator.new(@mock_generator,@table)
36
+ tg.generate
37
+ expected= <<HEREDOC
38
+ ----------------------------------------------------
39
+ | a | bb | ccc | dddd | eeee | fff | gggg | hh | i |
40
+ ----------------------------------------------------
41
+ | a | b | c | d | e | f | g | h | i |
42
+ | a | c | d | e | f | g | h | i |
43
+ | a | | e | f | g | h | i |
44
+ | a | e | f | g | h | i |
45
+ | a | f | i |
46
+ | a | g | h | i |
47
+ ----------------------------------------------------
48
+ HEREDOC
49
+
50
+ assert_equal(expected,@mock_generator)
51
+
52
+ end
53
+ def test_table_html
54
+
55
+ tg=ReportBuilder::Table::HtmlGenerator.new(@mock_generator,@table)
56
+ tg.generate
57
+ expected= <<HEREDOC
58
+ <a name='MOCK'> </a>
59
+ <table>
60
+ <thead>
61
+ <th>a</th><th>bb</th><th>ccc</th>
62
+ <th>dddd</th><th>eeee</th>
63
+ <th>fff</th><th>gggg</th><th>hh</th><th>i</th>
64
+ </thead>
65
+ <tbody>
66
+ <tr><td>a</td><td>b</td><td>c</td><td>d</td><td>e</td>
67
+ <td>f</td><td>g</td><td>h</td><td>i</td></tr>
68
+
69
+ <tr><td colspan="2">a</td><td>c</td><td rowspan="2">d</td><td>e</td>
70
+ <td>f</td><td>g</td><td>h</td><td>i</td></tr>
71
+
72
+ <tr><td colspan="3">a</td><td>e</td>
73
+ <td>f</td><td>g</td><td>h</td><td>i</td></tr>
74
+
75
+ <tr><td colspan="4">a</td><td>e</td>
76
+ <td>f</td><td>g</td><td>h</td><td>i</td></tr>
77
+
78
+ <tr><td colspan="5">a</td><td colspan="3">f</td><td>i</td></tr>
79
+
80
+ <tr><td colspan="6">a</td><td>g</td><td>h</td><td>i</td></tr>
81
+ </tbody>
82
+ </table>
83
+ HEREDOC
84
+
85
+ assert_equal(expected.gsub(/\s/m,""), @mock_generator.gsub(/\s/m,""))
86
+ end
87
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: reportbuilder
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Claudio Bustos
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-08 00:00:00 -03:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: hoe
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.3.3
24
+ version:
25
+ description: Report Abstract Interface. Creates text, html and pdf output, based on a common framework
26
+ email:
27
+ - clbustos_at_gmail.com
28
+ executables:
29
+ - reportbuilder
30
+ extensions: []
31
+
32
+ extra_rdoc_files:
33
+ - History.txt
34
+ - Manifest.txt
35
+ - README.txt
36
+ files:
37
+ - History.txt
38
+ - Manifest.txt
39
+ - README.txt
40
+ - Rakefile
41
+ - bin/reportbuilder
42
+ - data/reportbuilder.css
43
+ - data/reportbuilder.js
44
+ - lib/reportbuilder/generator.rb
45
+ - lib/reportbuilder/generator/html.rb
46
+ - lib/reportbuilder/generator/text.rb
47
+ - lib/reportbuilder.rb
48
+ - lib/reportbuilder/section.rb
49
+ - lib/reportbuilder/table.rb
50
+ - lib/reportbuilder/table/htmlgenerator.rb
51
+ - lib/reportbuilder/table/textgenerator.rb
52
+ - test/test_html.rb
53
+ - test/test_reportbuilder.rb
54
+ - test/test_section.rb
55
+ - test/test_table.rb
56
+ has_rdoc: true
57
+ homepage: http://rubyforge.org/projects/ruby-statsample/
58
+ licenses: []
59
+
60
+ post_install_message:
61
+ rdoc_options:
62
+ - --main
63
+ - README.txt
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: "0"
71
+ version:
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: "0"
77
+ version:
78
+ requirements: []
79
+
80
+ rubyforge_project: ruby-statsample
81
+ rubygems_version: 1.3.5
82
+ signing_key:
83
+ specification_version: 3
84
+ summary: Report Abstract Interface
85
+ test_files:
86
+ - test/test_section.rb
87
+ - test/test_table.rb
88
+ - test/test_html.rb
89
+ - test/test_reportbuilder.rb