ruport 0.2.9 → 0.3.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/ACKNOWLEDGEMENTS +33 -0
  2. data/AUTHORS +13 -1
  3. data/CHANGELOG +76 -1
  4. data/README +208 -89
  5. data/Rakefile +12 -8
  6. data/TODO +14 -122
  7. data/lib/ruport.rb +58 -0
  8. data/lib/ruport/config.rb +114 -0
  9. data/lib/ruport/data_row.rb +144 -0
  10. data/lib/ruport/data_set.rb +221 -0
  11. data/lib/ruport/format.rb +116 -0
  12. data/lib/ruport/format/builder.rb +29 -5
  13. data/lib/ruport/format/document.rb +77 -0
  14. data/lib/ruport/format/open_node.rb +36 -0
  15. data/lib/ruport/parser.rb +202 -0
  16. data/lib/ruport/query.rb +208 -0
  17. data/lib/ruport/query/sql_split.rb +33 -0
  18. data/lib/ruport/report.rb +116 -0
  19. data/lib/ruport/report/mailer.rb +17 -15
  20. data/test/{addressbook.csv → samples/addressbook.csv} +0 -0
  21. data/test/samples/car_ads.txt +505 -0
  22. data/test/{data.csv → samples/data.csv} +0 -0
  23. data/test/samples/document.xml +22 -0
  24. data/test/samples/five_lines.txt +5 -0
  25. data/test/samples/five_paragraphs.txt +9 -0
  26. data/test/samples/ross_report.txt +58530 -0
  27. data/test/samples/ruport_test.sql +8 -0
  28. data/test/samples/stonecodeblog.sql +279 -0
  29. data/test/{test.sql → samples/test.sql} +2 -1
  30. data/test/{test.yaml → samples/test.yaml} +0 -0
  31. data/test/tc_builder.rb +7 -4
  32. data/test/tc_config.rb +41 -0
  33. data/test/tc_data_row.rb +16 -26
  34. data/test/tc_data_set.rb +60 -41
  35. data/test/tc_database.rb +25 -0
  36. data/test/tc_document.rb +42 -0
  37. data/test/tc_element.rb +18 -0
  38. data/test/tc_page.rb +42 -0
  39. data/test/tc_query.rb +55 -0
  40. data/test/tc_reading.rb +60 -0
  41. data/test/tc_report.rb +31 -0
  42. data/test/tc_section.rb +45 -0
  43. data/test/tc_sql_split.rb +18 -0
  44. data/test/tc_state.rb +142 -0
  45. data/test/ts_all.rb +6 -3
  46. data/test/ts_format.rb +5 -0
  47. data/test/ts_parser.rb +10 -0
  48. metadata +102 -60
  49. data/bin/ruport +0 -104
  50. data/lib/ruport/format/chart.rb +0 -1
  51. data/lib/ruport/report/data_row.rb +0 -79
  52. data/lib/ruport/report/data_set.rb +0 -153
  53. data/lib/ruport/report/engine.rb +0 -201
  54. data/lib/ruport/report/fake_db.rb +0 -54
  55. data/lib/ruport/report/fake_engine.rb +0 -26
  56. data/lib/ruport/report/fake_mailer.rb +0 -23
  57. data/lib/ruport/report/sql.rb +0 -95
  58. data/lib/ruportlib.rb +0 -11
  59. data/test/tc_engine.rb +0 -102
  60. data/test/tc_mailer.rb +0 -21
@@ -0,0 +1,25 @@
1
+ require "test/unit"
2
+ require "ruportlib"
3
+
4
+ class TestSqlSplit < Test::Unit::TestCase
5
+ def teardown
6
+ FileUtils.rm '/tmp/compare.sql' if File.exist?( '/tmp/compare.sql' )
7
+ end
8
+
9
+ def test_stonecodeblog_sql
10
+ user = 'test'
11
+ password = 'password'
12
+ dbh = DBI.connect( "dbi:Mysql:test:localhost", user, password )
13
+ dbh.do 'drop database if exists stonecodeblog'
14
+ orig_sql = 'test/samples/stonecodeblog.sql'
15
+ sql = File.read orig_sql
16
+ split = Ruport::Report::SqlSplit.new sql
17
+ split.each do |sql| dbh.do( sql ); end
18
+ tmp_sql = '/tmp/compare.sql'
19
+ md_command =
20
+ "mysqldump -u#{ user } -p#{ password } --databases stonecodeblog"
21
+ `#{ md_command } > #{ tmp_sql }`
22
+ diff = `diff #{ orig_sql } #{ tmp_sql }`
23
+ assert( diff == '', diff[0..500] )
24
+ end
25
+ end
@@ -0,0 +1,42 @@
1
+ require "test/unit"
2
+ require "ruport"
3
+
4
+ class TestDocument < Test::Unit::TestCase
5
+
6
+ include Ruport
7
+
8
+ def setup
9
+ @empty_doc = Format::Document.new :test_doc1
10
+ many_pages = [:p1,:p2,:p3,:p4].map { |p| Format::Page.new(p) }
11
+ @populated_doc = Format::Document.new :test_doc2, :pages => many_pages
12
+ end
13
+
14
+ def test_basics
15
+ assert_equal(:test_doc1,@empty_doc.name)
16
+ assert_equal(:test_doc2,@populated_doc.name)
17
+ assert_equal([],@empty_doc.pages)
18
+ assert_equal([:p1,:p2,:p3,:p4],@populated_doc.pages.map { |p| p.name })
19
+ end
20
+
21
+ def test_each
22
+ page_names = [:p1,:p2,:p3,:p4]
23
+
24
+ @populated_doc.each { |p| assert_equal(page_names.shift,p.name) }
25
+ assert_equal([],page_names)
26
+
27
+ @populated_doc.pages << Format::Page.new(:p5)
28
+ page_names = [:p1,:p2,:p3,:p4,:p5]
29
+
30
+ @populated_doc.each { |p| assert_equal(page_names.shift,p.name) }
31
+ assert_equal([],page_names)
32
+ end
33
+
34
+ def test_add_page
35
+ @empty_doc.add_page :p1
36
+ @populated_doc.add_page :p5, :some_trait => "cool"
37
+ assert(@empty_doc.find { |p| p.name.eql?(:p1) })
38
+ assert(@populated_doc.find { |p| p.name.eql?(:p5) and
39
+ p.some_trait.eql?("cool") })
40
+ end
41
+
42
+ end
@@ -0,0 +1,18 @@
1
+ require "test/unit"
2
+ require "ruport"
3
+
4
+ class TestElement < Test::Unit::TestCase
5
+ include Ruport
6
+ def setup
7
+ @empty_element = Format::Element.new :test_element
8
+ @populated_element = Format::Element.new :test_element2,
9
+ :content => "Hello, Element!"
10
+ end
11
+
12
+ def test_basics
13
+ assert_equal(:test_element, @empty_element.name)
14
+ assert_equal(:test_element2, @populated_element.name)
15
+ assert_equal("Hello, Element!", @populated_element.content)
16
+ end
17
+
18
+ end
data/test/tc_page.rb ADDED
@@ -0,0 +1,42 @@
1
+ require "test/unit"
2
+ require "ruport"
3
+
4
+ class TestPage < Test::Unit::TestCase
5
+ include Ruport
6
+ def setup
7
+ @empty_page = Format::Page.new :test_page1
8
+ sections = { :s1 => Format::Section.new(:s1), :s2 => Format::Section.new(:s2) }
9
+ @populated_page = Format::Page.new :test_page2,
10
+ :sections => sections
11
+ end
12
+
13
+ def test_basics
14
+ assert_equal(:test_page1, @empty_page.name)
15
+ assert_equal(:test_page2, @populated_page.name)
16
+ assert_equal([],[:s1,:s2]-@populated_page.map { |s| s.name })
17
+ assert_equal({},@empty_page.sections)
18
+ end
19
+
20
+ def test_each
21
+ section_names = [:s1,:s2]
22
+ @populated_page.each { |s| section_names -= [s.name] }
23
+ assert_equal([],section_names)
24
+ @populated_page << Format::Section.new(:s3)
25
+ section_names = [:s1,:s2,:s3]
26
+ @populated_page.each { |s| section_names -= [s.name] }
27
+ assert_equal([],section_names)
28
+ end
29
+
30
+ def test_add_function
31
+ @populated_page.add_section :s3
32
+ @populated_page.add_section :s4, :content => "Hello from Section!"
33
+ assert(@populated_page.find { |s| s.name.eql?(:s3) })
34
+ assert(@populated_page.find { |s| s.name.eql?(:s4) and
35
+ s.content.eql?("Hello from Section!")} )
36
+
37
+ end
38
+ def test_brackets
39
+ assert_equal(:s1,@populated_page[:s1].name)
40
+ assert_equal(:s2,@populated_page[:s2].name)
41
+ end
42
+ end
data/test/tc_query.rb ADDED
@@ -0,0 +1,55 @@
1
+ require "test/unit"
2
+ require "ruport"
3
+ class TestQuery < Test::Unit::TestCase
4
+
5
+
6
+ def setup
7
+ Ruport::Config.source :default,
8
+ :dsn => "ruport:test", :user => "greg", :password => "apple"
9
+
10
+ Ruport::Config.source :alternate,
11
+ :dsn => "ruport:test2", :user => "sandal", :password => "harmonix"
12
+
13
+ @query1 = Ruport::Query.new "select * from foo", :cache_enabled => true
14
+ @query1.cached_data = [[1,2,3],[4,5,6],[7,8,9]]
15
+ end
16
+
17
+
18
+ def test_result
19
+ assert_nothing_raised { @query1.result }
20
+ assert_equal([[1,2,3],[4,5,6],[7,8,9]],@query1.result)
21
+ end
22
+
23
+ def test_each
24
+ data = [[1,2,3],[4,5,6],[7,8,9]]
25
+ @query1.each do |r|
26
+ assert_equal(data.shift,r)
27
+ end
28
+ data = [1,4,7]
29
+ @query1.each do |r|
30
+ assert_equal(data.shift,r.first)
31
+ end
32
+ assert_raise (LocalJumpError) { @query1.each }
33
+ end
34
+
35
+ def test_select_source
36
+
37
+ assert_equal( "ruport:test", @query1.instance_eval("@dsn") )
38
+ assert_equal( "greg", @query1.instance_eval("@user") )
39
+ assert_equal( "apple", @query1.instance_eval("@password") )
40
+
41
+ @query1.select_source :alternate
42
+
43
+ assert_equal( "ruport:test2", @query1.instance_eval("@dsn") )
44
+ assert_equal( "sandal", @query1.instance_eval("@user") )
45
+ assert_equal( "harmonix", @query1.instance_eval("@password") )
46
+
47
+ @query1.select_source :default
48
+
49
+ assert_equal( "ruport:test", @query1.instance_eval("@dsn") )
50
+ assert_equal( "greg", @query1.instance_eval("@user") )
51
+ assert_equal( "apple", @query1.instance_eval("@password") )
52
+
53
+ end
54
+
55
+ end
@@ -0,0 +1,60 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ # tc_reading.rb
4
+ #
5
+ # Created by James Edward Gray II on 2005-08-14.
6
+ # Copyright 2005 Gray Productions. All rights reserved.
7
+
8
+ require "test/unit"
9
+
10
+ require "ruport/parser"
11
+
12
+ class TestReading < Test::Unit::TestCase
13
+ def test_line_by_line_read
14
+ path = File.join(File.dirname(__FILE__), "samples/five_lines.txt")
15
+ lines = File.readlines(path)
16
+ test = self
17
+
18
+ Ruport::Parser.new(path) do
19
+ read { |line| test.assert_equal(lines.shift, line) }
20
+ end
21
+ end
22
+
23
+ def test_paragraph_read
24
+ path = File.join(File.dirname(__FILE__), "samples/five_paragraphs.txt")
25
+ paragraphs = File.readlines(path, "")
26
+ test = self
27
+
28
+ Ruport::Parser.new(path, "") do
29
+ read { |paragraph| test.assert_equal(paragraphs.shift, paragraph) }
30
+ end
31
+ end
32
+
33
+ def test_restricted_reading
34
+ path = File.join(File.dirname(__FILE__), "samples/five_lines.txt")
35
+ numbers = %w{two three}
36
+ test = self
37
+
38
+ Ruport::Parser.new(path) do
39
+ read(/ (t\w+)\./) do |number|
40
+ test.assert_equal("This is line #{numbers.first}.\n", @read)
41
+ test.assert_equal(numbers.shift, number)
42
+ end
43
+ end
44
+ end
45
+
46
+ def test_data_saving_and_retrieving
47
+ path = File.join(File.dirname(__FILE__), "samples/five_lines.txt")
48
+
49
+ data = Ruport::Parser.new( path ) do
50
+ read(/ (o\w+)\./) { |number| @number = number }
51
+ read { |line| (@lines ||= Array.new) << line }
52
+ end
53
+
54
+ assert_equal("one", data[:number])
55
+ assert_equal("one", data.number)
56
+ assert_equal(path, data.path)
57
+ assert_equal(5, data.lines.size)
58
+ assert_equal(File.readlines(path), data.lines)
59
+ end
60
+ end
data/test/tc_report.rb ADDED
@@ -0,0 +1,31 @@
1
+ #tc_report.rb
2
+ #
3
+ # Created by Gregory Thomas Brown on 2005-08-09
4
+ # Copyright 2005 (Gregory Brown) All rights reserved.
5
+
6
+ require "test/unit"
7
+ require "ruport"
8
+ class TestReport < Test::Unit::TestCase
9
+ include Ruport
10
+
11
+ def setup
12
+ @report = Report.new
13
+ end
14
+
15
+ def test_render
16
+ result = @report.render "<%= 2 + 3%>",
17
+ :filters => [:erb]
18
+ assert_equal("5",result)
19
+
20
+ if defined? RedCloth
21
+ result = @report.render '"foo":http://foo.com',
22
+ :filters => [:red_cloth]
23
+
24
+ assert_equal('<p><a href="http://foo.com">foo</a></p>',result)
25
+ result = @report.render %{"<%= 2 + 3%>":http://foo.com },
26
+ :filters => [:erb, :red_cloth]
27
+ assert_equal('<p><a href="http://foo.com">5</a></p>',result)
28
+ end
29
+ end
30
+
31
+ end
@@ -0,0 +1,45 @@
1
+ require "test/unit"
2
+ require "ruport"
3
+
4
+ class TestSection < Test::Unit::TestCase
5
+ include Ruport
6
+ def setup
7
+ elements = { :e1 => Format::Element.new(:e1),
8
+ :e2 => Format::Element.new(:e2) }
9
+ @empty_section = Format::Section.new :test_section1
10
+ @populated_section = Format::Section.new :test_section2,
11
+ :elements => elements
12
+
13
+ end
14
+
15
+ def test_basics
16
+ assert_equal( :test_section1, @empty_section.name )
17
+ assert_equal( :test_section2, @populated_section.name )
18
+ assert_equal( [], [:e1,:e2]-@populated_section.map { |e| e.name } )
19
+ end
20
+
21
+ def test_each
22
+ element_names = [:e1,:e2]
23
+ @populated_section.each { |e| element_names -= [e.name] }
24
+ assert_equal([],element_names)
25
+
26
+ element_names = [:e1, :e2, :e3]
27
+ @populated_section << Format::Element.new(:e3)
28
+ @populated_section.each { |e| element_names -= [e.name] }
29
+ assert_equal([],element_names)
30
+ end
31
+
32
+ def test_add_element
33
+ @empty_section.add_element :e1
34
+ @empty_section.add_element :e2, :content => "Hello from Element!"
35
+ assert(@empty_section[:e1])
36
+ assert(@empty_section[:e2])
37
+ assert_equal("Hello from Element!",@empty_section[:e2].content)
38
+ end
39
+
40
+ def test_brackets
41
+ assert_equal(:e1,@populated_section[:e1].name)
42
+ assert_equal(:e2,@populated_section[:e2].name)
43
+ end
44
+
45
+ end
@@ -0,0 +1,18 @@
1
+ require "test/unit"
2
+ require "ruport"
3
+ class TestSqlSplit < Test::Unit::TestCase
4
+ include Ruport
5
+
6
+ def test_sql_split1
7
+ sql = File.read 'test/samples/ruport_test.sql'
8
+ split = Query::SqlSplit.new sql
9
+ assert_equal( 'SELECT * FROM ruport_test', split.last )
10
+ end
11
+
12
+ def test_sql_split2
13
+ sql = "SELECT * FROM ruport_test"
14
+ split = Query::SqlSplit.new sql
15
+ assert_equal( 1, split.size )
16
+ assert_equal( sql, split.first )
17
+ end
18
+ end
data/test/tc_state.rb ADDED
@@ -0,0 +1,142 @@
1
+ #!/usr/local/bin/ruby -w
2
+
3
+ # tc_state.rb
4
+ #
5
+ # Created by James Edward Gray II on 2005-08-14.
6
+ # Copyright 2005 Gray Productions. All rights reserved.
7
+
8
+ require "test/unit"
9
+
10
+ require "ruport/parser"
11
+
12
+ class TestState < Test::Unit::TestCase
13
+ def test_single_skips
14
+ path = File.join(File.dirname(__FILE__), "samples/five_lines.txt")
15
+ lines = File.readlines(path).values_at(0..2, 4)
16
+ test = self
17
+
18
+ Ruport::Parser.new(path) do
19
+ skip(?u)
20
+
21
+ read { |line| test.assert_equal(lines.shift, line) }
22
+ end
23
+ end
24
+
25
+ def test_skipping_range
26
+ path = File.join(File.dirname(__FILE__), "samples/five_lines.txt")
27
+ lines = File.readlines(path).values_at(0, 3..4)
28
+ test = self
29
+
30
+ Ruport::Parser.new(path) do
31
+ start_skipping_at("two")
32
+ stop_skipping_at("three")
33
+
34
+ read { |line| test.assert_equal(lines.shift, line) }
35
+ end
36
+ end
37
+
38
+ def test_searching_skipped
39
+ path = File.join(File.dirname(__FILE__), "samples/five_lines.txt")
40
+
41
+ data = Ruport::Parser.new(path) do
42
+ @state = :skip
43
+ stop_skipping_at("four")
44
+ find_in_skipped(/ou/) { |line| @found_in_skip = line }
45
+
46
+ read { |line| (@lines ||= Array.new) << line }
47
+ end
48
+
49
+ assert_equal("This is line four.\n", data.found_in_skip)
50
+ assert_equal(["This is line five.\n"], data.lines)
51
+ end
52
+
53
+ def test_stop
54
+ path = File.join(File.dirname(__FILE__), "samples/five_lines.txt")
55
+
56
+ data = Ruport::Parser.new(path) do
57
+ stop_at("three")
58
+
59
+ read { |line| @last_line = line }
60
+ end
61
+
62
+ assert_equal("This is line two.\n", data.last_line)
63
+
64
+ data = Ruport::Parser.new(path) do
65
+ read do |line|
66
+ @last_line = line
67
+
68
+ @state = :stop if @read.index("three")
69
+ end
70
+ end
71
+
72
+ assert_equal("This is line three.\n", data.last_line)
73
+ end
74
+
75
+ def test_pre_and_post
76
+ path = File.join(File.dirname(__FILE__), "samples/five_lines.txt")
77
+
78
+ data = Ruport::Parser.new(path) do
79
+ @pre = @post = 0
80
+
81
+ pre do
82
+ @pre += 1
83
+ @post = 0
84
+ end
85
+ read { |line| (@lines ||= Array.new) << line }
86
+ read(/\w+\./) { |number| (@numbers ||= Array.new) << number }
87
+ post { @post += 1 }
88
+ end
89
+
90
+ assert_equal(5, data.pre)
91
+ assert_equal(1, data.post)
92
+ end
93
+
94
+ def test_complex
95
+ path = File.join(File.dirname(__FILE__), "samples/ross_report.txt")
96
+ test = self
97
+
98
+ Ruport::Parser.new(path) do
99
+ @state = :skip
100
+ start_skipping_at("\f")
101
+ stop_skipping_at(/\A-[- ]+-\Z/)
102
+ skip(/\A\s*\Z/)
103
+ skip(/--\Z/)
104
+
105
+ find_in_skipped(/((?:Period|Week)\s+\d.+?)\s*\Z/) do |period|
106
+ test.assert_equal("Period 02/2002", period)
107
+ end
108
+
109
+ stop_at("*** Selection Criteria ***")
110
+
111
+ read do |line|
112
+ test.assert_match(/\A\s+(?:Sales|Cust|SA)|\A[-\w]+\s+/, line)
113
+ end
114
+ end
115
+
116
+ path = File.join(File.dirname(__FILE__), "samples/car_ads.txt")
117
+
118
+ data = Ruport::Parser.new(path, "") do
119
+ @state = :skip
120
+ stop_skipping_at("Save Ad")
121
+ skip(/\A\s*\Z/)
122
+
123
+ pre { @price = @miles = nil }
124
+ read(/\$([\d,]+\d)/) { |price| @price = price.delete(",").to_i }
125
+ read(/([\d,]*\d)\s*m/) { |miles| @miles = miles.delete(",").to_i }
126
+
127
+ read do |ad|
128
+ if @price and @price < 20_000 and @miles and @miles < 40_000
129
+ (@ads ||= Array.new) << ad.strip
130
+ end
131
+ end
132
+ end
133
+
134
+ assert_equal([<<END_AD.strip], data.ads)
135
+ 2003 Chrysler Town & Country LX
136
+ $16,990, green, 21,488 mi, air, pw, power locks, ps, power mirrors,
137
+ dual air bags, keyless entry, intermittent wipers, rear defroster, alloy,
138
+ pb, abs, cruise, am/fm stereo, CD, cassette, tinted glass
139
+ VIN:2C4GP44363R153238, Stock No:C153238, CALL DAN PERKINS AT 1-800-432-6326
140
+ END_AD
141
+ end
142
+ end