reportbuilder 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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