tchart 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/tchart +5 -0
- data/lib/tchart.rb +27 -0
- data/lib/tchart/lang/tchart_error.rb +9 -0
- data/lib/tchart/model/bar.rb +24 -0
- data/lib/tchart/model/chart.rb +25 -0
- data/lib/tchart/model/command_line_args.rb +18 -0
- data/lib/tchart/model/coordinate.rb +29 -0
- data/lib/tchart/model/grid_line.rb +25 -0
- data/lib/tchart/model/label.rb +43 -0
- data/lib/tchart/model/layout.rb +85 -0
- data/lib/tchart/model/separator.rb +28 -0
- data/lib/tchart/model/settings.rb +68 -0
- data/lib/tchart/model/y_item.rb +44 -0
- data/lib/tchart/process/chart_builder.rb +63 -0
- data/lib/tchart/process/command_line_parser.rb +73 -0
- data/lib/tchart/process/data_parser.rb +76 -0
- data/lib/tchart/process/data_reader.rb +14 -0
- data/lib/tchart/process/items_parser.rb +156 -0
- data/lib/tchart/process/layout_builder.rb +106 -0
- data/lib/tchart/process/settings_parser.rb +63 -0
- data/lib/tchart/process/tex_builder.rb +85 -0
- data/lib/tchart/process/tex_writer.rb +13 -0
- data/lib/tchart/version.rb +3 -0
- data/test/integration_test.rb +82 -0
- data/test/tchart/model/bar_test.rb +17 -0
- data/test/tchart/model/coordinate_test.rb +10 -0
- data/test/tchart/model/grid_line_test.rb +17 -0
- data/test/tchart/model/label_test.rb +31 -0
- data/test/tchart/model/layout_test.rb +17 -0
- data/test/tchart/model/separator_test.rb +19 -0
- data/test/tchart/model/settings_test.rb +48 -0
- data/test/tchart/model/y_item_test.rb +24 -0
- data/test/tchart/process/chart_builder_test.rb +33 -0
- data/test/tchart/process/command_line_parser_test.rb +89 -0
- data/test/tchart/process/data_parser_test.rb +60 -0
- data/test/tchart/process/data_reader_test.rb +23 -0
- data/test/tchart/process/items_parser_test.rb +154 -0
- data/test/tchart/process/layout_builder_test.rb +189 -0
- data/test/tchart/process/settings_parser_test.rb +75 -0
- data/test/tchart/process/tex_builder_test.rb +120 -0
- data/test/tchart/process/tex_writer_test.rb +38 -0
- data/test/tchart_test.rb +47 -0
- metadata +154 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
module TChart
|
4
|
+
describe ChartBuilder, "build" do
|
5
|
+
|
6
|
+
before do
|
7
|
+
@layout = stub( 'layout',
|
8
|
+
x_axis_tick_dates: [Date.new(2001,1,1), Date.new(2002,1,1)],
|
9
|
+
x_axis_tick_x_coordinates: [0, 100],
|
10
|
+
x_axis_length: 100,
|
11
|
+
y_axis_length: 50,
|
12
|
+
x_axis_label_y_coordinate: -3,
|
13
|
+
x_axis_label_width: 10,
|
14
|
+
y_axis_tick_y_coordinates: [ 25 ] )
|
15
|
+
item = stub ; item.stubs(:build).returns [ Label.build_ylabel(xy(-10, 10), 20, "label"), Bar.new(xy(0, 25), xy(50, 25), "style") ]
|
16
|
+
@items = [ item ]
|
17
|
+
end
|
18
|
+
|
19
|
+
it "builds a chart" do
|
20
|
+
chart = ChartBuilder.build(@layout, @items)
|
21
|
+
chart.elements.length.must_equal 8
|
22
|
+
chart.elements[0].must_equal GridLine.new(xy(0, 50), xy(100, 50)) # top horizontal frame
|
23
|
+
chart.elements[1].must_equal GridLine.new(xy(0, 0), xy(100, 0)) # bottom horizontal frame
|
24
|
+
chart.elements[2].must_equal Label.build_xlabel(xy(0, -3), 10, "2001") # left x-axis label
|
25
|
+
chart.elements[3].must_equal GridLine.new(xy(0, 0), xy(0, 50)) # left vertical grid line
|
26
|
+
chart.elements[4].must_equal Label.build_xlabel(xy(100, -3), 10, "2002") # left x-axis label
|
27
|
+
chart.elements[5].must_equal GridLine.new(xy(100, 0), xy(100, 50)) # right vertical grid line
|
28
|
+
chart.elements[6].must_equal Label.build_ylabel(xy(-10, 10), 20, "label") # item y-axis label
|
29
|
+
chart.elements[7].must_equal Bar.new(xy(0, 25), xy(50, 25), "style") # item bar
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
module TChart
|
4
|
+
describe CommandLineParser, "parse" do
|
5
|
+
|
6
|
+
Usage = "Usage: tchart [ --version | --help | input-data-filename output-tikz-filename ]"
|
7
|
+
|
8
|
+
it "returns CommandLineArgs with appropriate attributes parsed from the command line" do
|
9
|
+
File.expects(:exists?).with('input_filename').returns(true)
|
10
|
+
File.expects(:file?).with('input_filename').returns(true)
|
11
|
+
File.expects(:exists?).with('output_filename').returns(false)
|
12
|
+
args, _ = CommandLineParser.parse( [ 'input_filename', 'output_filename' ] )
|
13
|
+
args.data_filename.must_equal 'input_filename'
|
14
|
+
args.tex_filename.must_equal 'output_filename'
|
15
|
+
end
|
16
|
+
|
17
|
+
it "returns an error if there are fewer than two arguments" do
|
18
|
+
_, errors = CommandLineParser.parse( [ 'input_filename' ] )
|
19
|
+
errors.must_include Usage
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns an error if there are more than two arguments" do
|
23
|
+
_, errors = CommandLineParser.parse( [ 'input_filename', 'output_filename', 'arg3' ] )
|
24
|
+
errors.must_include Usage
|
25
|
+
end
|
26
|
+
|
27
|
+
it "returns an error if the input and output file names are the same" do
|
28
|
+
File.expects(:exists?).with('input_filename').returns(true)
|
29
|
+
File.expects(:file?).with('input_filename').returns(true)
|
30
|
+
File.expects(:exists?).with('./input_filename').returns(true)
|
31
|
+
File.expects(:file?).with('./input_filename').returns(true)
|
32
|
+
_, errors = CommandLineParser.parse( [ 'input_filename', './input_filename' ] )
|
33
|
+
errors.must_include "Error: input \"input_filename\" and output \"./input_filename\" refer to the same file."
|
34
|
+
end
|
35
|
+
|
36
|
+
it "returns an error if the input data file does not exist" do
|
37
|
+
File.expects(:exists?).with('input_filename').returns(false)
|
38
|
+
_, errors = CommandLineParser.parse( [ 'input_filename', 'output_filename' ] )
|
39
|
+
errors.must_include "Error: input data file \"input_filename\" not found."
|
40
|
+
end
|
41
|
+
|
42
|
+
it "returns an error if the input data file is not a file" do
|
43
|
+
File.expects(:exists?).with('input_filename').returns(true)
|
44
|
+
File.expects(:file?).with('input_filename').returns(false)
|
45
|
+
_, errors = CommandLineParser.parse( [ 'input_filename', 'output_filename' ] )
|
46
|
+
errors.must_include "Error: input data file \"input_filename\" is not a file."
|
47
|
+
end
|
48
|
+
|
49
|
+
it "returns an error if the output data file exists and is not a file" do
|
50
|
+
File.expects(:exists?).with('input_filename').returns(true)
|
51
|
+
File.expects(:file?).with('input_filename').returns(true)
|
52
|
+
File.expects(:exists?).with('output_filename').returns(true)
|
53
|
+
File.expects(:file?).with('output_filename').returns(false)
|
54
|
+
_, errors = CommandLineParser.parse( [ 'input_filename', 'output_filename' ] )
|
55
|
+
errors.must_include "Error: existing output data file \"output_filename\" is not a file."
|
56
|
+
end
|
57
|
+
|
58
|
+
it "returns an error containing the version if the -v option is specified" do
|
59
|
+
_, errors = CommandLineParser.parse( [ "-v" ] )
|
60
|
+
errors.must_include TChart::Version
|
61
|
+
end
|
62
|
+
|
63
|
+
it "returns an error containing the version if the --version option is specified" do
|
64
|
+
_, errors = CommandLineParser.parse( [ "--version" ] )
|
65
|
+
errors.must_include TChart::Version
|
66
|
+
end
|
67
|
+
|
68
|
+
it "other arguments are ignored if -v is specified" do
|
69
|
+
_, errors = CommandLineParser.parse( [ "-v", "input_filename", "output_filename" ] )
|
70
|
+
errors.must_include TChart::Version
|
71
|
+
end
|
72
|
+
|
73
|
+
it "returns an error containing usage if the -h option is specified" do
|
74
|
+
_, errors = CommandLineParser.parse( [ "-h" ] )
|
75
|
+
errors.must_include Usage
|
76
|
+
end
|
77
|
+
|
78
|
+
it "returns an error containing usage if the --help option is specified" do
|
79
|
+
_, errors = CommandLineParser.parse( [ "--help" ] )
|
80
|
+
errors.must_include Usage
|
81
|
+
end
|
82
|
+
|
83
|
+
it "returns an error if an unknown option is specified" do
|
84
|
+
_, errors = CommandLineParser.parse( [ "-a" ] )
|
85
|
+
errors.must_include Usage
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
module TChart
|
4
|
+
describe DataParser do
|
5
|
+
|
6
|
+
it "reads all lines from the data source" do
|
7
|
+
data = StringIO.new("1\n2\n3\n")
|
8
|
+
DataParser.parse('filename.txt', data)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "ignores blank lines" do
|
12
|
+
data = StringIO.new("1\n \n3\n")
|
13
|
+
_, items, _ = DataParser.parse('filename.txt', data)
|
14
|
+
items.map { |item| item.description }.must_equal(['1', '3'])
|
15
|
+
end
|
16
|
+
|
17
|
+
it "ignores empty lines" do
|
18
|
+
data = StringIO.new("1\n\n3\n")
|
19
|
+
_, items, _ = DataParser.parse('filename.txt', data)
|
20
|
+
items.map { |item| item.description }.must_equal(['1', '3'])
|
21
|
+
end
|
22
|
+
|
23
|
+
it "ignores comment lines" do
|
24
|
+
data = StringIO.new("1\n# comment\n3\n")
|
25
|
+
_, items, _ = DataParser.parse('filename.txt', data)
|
26
|
+
items.map { |item| item.description }.must_equal(['1', '3'])
|
27
|
+
end
|
28
|
+
|
29
|
+
it "ignores trailing comments" do
|
30
|
+
data = StringIO.new("1\n2 # comment\n3\n")
|
31
|
+
_, items, _ = DataParser.parse('filename.txt', data)
|
32
|
+
items.map { |item| item.description }.must_equal(['1', '2', '3'])
|
33
|
+
end
|
34
|
+
|
35
|
+
it "does not treat escaped hashes (#) as comments" do
|
36
|
+
data = StringIO.new("C\\#\n")
|
37
|
+
_, items, _ = DataParser.parse('filename.txt', data)
|
38
|
+
items[0].description.must_equal 'C#'
|
39
|
+
end
|
40
|
+
|
41
|
+
it "include the data source name and line number in error messages" do
|
42
|
+
data = StringIO.new("unknown_setting_name = 42\n")
|
43
|
+
_, _, errors = DataParser.parse('filename.txt', data)
|
44
|
+
errors.find {|item| item =~ /^filename.txt, 1:/}.wont_be_nil
|
45
|
+
end
|
46
|
+
|
47
|
+
it "returns a 'no items found' error if no items were found in the data and no other errors were found" do
|
48
|
+
data = StringIO.new("# no chart items\n")
|
49
|
+
_, _, errors = DataParser.parse('filename.txt', data)
|
50
|
+
errors.must_equal [ "filename.txt: no items found" ]
|
51
|
+
end
|
52
|
+
|
53
|
+
it "does not return a 'no items found' error if no items were found in the data but other errors were found" do
|
54
|
+
data = StringIO.new("unknown_setting = 123\n")
|
55
|
+
_, _, errors = DataParser.parse('filename.txt', data)
|
56
|
+
errors.wont_include [ "filename.txt: no items found" ]
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
module TChart
|
5
|
+
describe DataReader, "read" do
|
6
|
+
|
7
|
+
before do
|
8
|
+
@filename = "_DataReader_read_test.txt"
|
9
|
+
@settings, @items, @errors = stub, stub, stub
|
10
|
+
end
|
11
|
+
|
12
|
+
after do
|
13
|
+
File.delete(@filename) if File.exists?(@filename)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "returns settings, items, and errors" do
|
17
|
+
DataParser.stubs(:parse).returns [ @settings, @items, @errors ]
|
18
|
+
File.open(@filename, 'w') { |f| f.puts("C\tlang\t2001.1-2001.11\nchart_width=50\n") }
|
19
|
+
DataReader.read(@filename).must_equal [ @settings, @items, @errors ]
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
module TChart
|
4
|
+
describe ItemsParser, "parse" do
|
5
|
+
|
6
|
+
before do
|
7
|
+
@parser = ItemsParser.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it "parses chart items" do
|
11
|
+
@parser.parse("Description | Style | 2000.4.14-2001.2.22\n")
|
12
|
+
@parser.items[0].description.must_equal 'Description'
|
13
|
+
@parser.items[0].bar_style.must_equal 'Style'
|
14
|
+
@parser.items[0].date_ranges.must_equal [ Date.new(2000,4,14)..Date.new(2001,2,22) ]
|
15
|
+
end
|
16
|
+
|
17
|
+
it "raises an error if the name is missing" do
|
18
|
+
error = ->{ @parser.parse("|Style|2001\n") }.must_raise TChartError
|
19
|
+
error.message.must_equal "description is missing"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "raises an error if dates where supplied but the style is missing" do
|
23
|
+
error = ->{ @parser.parse("Description||2001\n") }.must_raise TChartError
|
24
|
+
error.message.must_equal "style is missing"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "allows escaped separator characters" do
|
28
|
+
@parser.parse("Description1\\|\\|Description2|Style|2000\n")
|
29
|
+
@parser.items[0].description.must_equal 'Description1||Description2'
|
30
|
+
end
|
31
|
+
|
32
|
+
it "allows escaped escape characters" do
|
33
|
+
@parser.parse("Description1\\\\Description2|Style|2000\n")
|
34
|
+
@parser.items[0].description.must_equal 'Description1\Description2'
|
35
|
+
end
|
36
|
+
|
37
|
+
it "allows separator lines" do
|
38
|
+
@parser.parse("---\n")
|
39
|
+
@parser.items[0].must_be_instance_of Separator
|
40
|
+
end
|
41
|
+
|
42
|
+
it "allows chart items with no date ranges" do
|
43
|
+
@parser.parse("Description | Style\n")
|
44
|
+
@parser.items[0].description.must_equal 'Description'
|
45
|
+
@parser.items[0].bar_style.must_equal 'Style'
|
46
|
+
@parser.items[0].date_ranges.must_equal []
|
47
|
+
end
|
48
|
+
|
49
|
+
it "allows chart items with no style and no date ranges" do
|
50
|
+
@parser.parse("Description\n")
|
51
|
+
@parser.items[0].description.must_equal 'Description'
|
52
|
+
@parser.items[0].bar_style.must_equal nil
|
53
|
+
@parser.items[0].date_ranges.must_equal []
|
54
|
+
end
|
55
|
+
|
56
|
+
it "allows chart items with empty style and empty date ranges" do
|
57
|
+
@parser.parse("Description||\n")
|
58
|
+
@parser.items[0].description.must_equal 'Description'
|
59
|
+
@parser.items[0].bar_style.must_equal nil
|
60
|
+
@parser.items[0].date_ranges.must_equal []
|
61
|
+
end
|
62
|
+
|
63
|
+
it "allows many date ranges" do
|
64
|
+
@parser.parse("Description|Style|2000|2001|2002\n")
|
65
|
+
@parser.items[0].date_ranges.length.must_equal 3
|
66
|
+
end
|
67
|
+
|
68
|
+
it "strips leading and trailing spaces from the description" do
|
69
|
+
@parser.parse(" \t Description \t |Style\n")
|
70
|
+
@parser.items[0].description.must_equal 'Description'
|
71
|
+
end
|
72
|
+
|
73
|
+
it "strips leading and trailing spaces from the style" do
|
74
|
+
@parser.parse("Description| \t Style \t |2000\n")
|
75
|
+
@parser.items[0].bar_style.must_equal 'Style'
|
76
|
+
end
|
77
|
+
|
78
|
+
it "strips leading and trailing spaces from the dates" do
|
79
|
+
@parser.parse("Description|Style| \t 2000 \t | \t 2001 \t \n")
|
80
|
+
@parser.items[0].date_ranges.must_equal [ Date.new(2000,1,1)..Date.new(2000,12,31), Date.new(2001,1,1)..Date.new(2001,12,31) ]
|
81
|
+
end
|
82
|
+
|
83
|
+
it "converts a range consisting of just a year to 1st January thru 31st December of that year" do
|
84
|
+
@parser.parse("Description|Style|2000\n")
|
85
|
+
@parser.items[0].date_ranges.must_equal [ Date.new(2000,1,1)..Date.new(2000,12,31) ]
|
86
|
+
end
|
87
|
+
|
88
|
+
it "converts a range start consisting of just a year to 1st January of the year" do
|
89
|
+
@parser.parse("Description|Style|2000-2001.2.22\n")
|
90
|
+
@parser.items[0].date_ranges.must_equal [ Date.new(2000,1,1)..Date.new(2001,2,22) ]
|
91
|
+
end
|
92
|
+
|
93
|
+
it "converts a range start consisting of a year and a month to the 1st of the month" do
|
94
|
+
@parser.parse("Description|Style|2000.4-2001.2.22\n")
|
95
|
+
@parser.items[0].date_ranges.must_equal [ Date.new(2000,4,1)..Date.new(2001,2,22) ]
|
96
|
+
end
|
97
|
+
|
98
|
+
it "converts a range end consisting of just a year to 31st December of the year" do
|
99
|
+
@parser.parse("Description|Style|2000.4.14-2001\n")
|
100
|
+
@parser.items[0].date_ranges.must_equal [ Date.new(2000,4,14)..Date.new(2001,12,31) ]
|
101
|
+
end
|
102
|
+
|
103
|
+
it "converts a range end consisting of a year and a month to the last day of the month" do
|
104
|
+
@parser.parse("Description|Style|2000.4.14-2001.2\n")
|
105
|
+
@parser.items[0].date_ranges.must_equal [ Date.new(2000,4,14)..Date.new(2001,2,28) ]
|
106
|
+
end
|
107
|
+
|
108
|
+
it "allows whitespace around the dash (-) in a date range" do
|
109
|
+
@parser.parse("Description|Style|2000.4.14 \t - \t 2001.2.22\n")
|
110
|
+
@parser.items[0].date_ranges.must_equal [ Date.new(2000,4,14)..Date.new(2001,2,22) ]
|
111
|
+
end
|
112
|
+
|
113
|
+
it "raises an error if a date cannot be parsed" do
|
114
|
+
error = ->{ @parser.parse("Description|Style|2000.-2001\n") }.must_raise TChartError
|
115
|
+
error.message.must_equal "bad date range \"2000.-2001\"; expecting 2000.4.17-2001.7.21 | 2002.4-2003, etc."
|
116
|
+
end
|
117
|
+
|
118
|
+
it "raises an error if start date in a range is invalid" do
|
119
|
+
error = ->{ @parser.parse("Description|Style|2000.4.34-2001.2.22\n") }.must_raise TChartError
|
120
|
+
error.message.must_equal "2000.4.34: invalid date"
|
121
|
+
end
|
122
|
+
|
123
|
+
it "raises an error if end date in a range is invalid" do
|
124
|
+
error = ->{ @parser.parse("Description|Style|2000.4.14-2001.2.32\n") }.must_raise TChartError
|
125
|
+
error.message.must_equal "2001.2.32: invalid date"
|
126
|
+
end
|
127
|
+
|
128
|
+
it "allows ranges to be out of order" do
|
129
|
+
@parser.parse("Description|Style|2001|2000\n")
|
130
|
+
@parser.items[0].date_ranges.must_equal [ Date.new(2001,1,1)..Date.new(2001,12,31), Date.new(2000,1,1)..Date.new(2000,12,31) ]
|
131
|
+
end
|
132
|
+
|
133
|
+
it "allows ranges to be back-to-back" do
|
134
|
+
@parser.parse("Description|Style|2000|2001\n")
|
135
|
+
@parser.items[0].date_ranges.must_equal [ Date.new(2000,1,1)..Date.new(2000,12,31), Date.new(2001,1,1)..Date.new(2001,12,31) ]
|
136
|
+
end
|
137
|
+
|
138
|
+
it "raises an error if ranges overlap" do
|
139
|
+
error = ->{ @parser.parse("Description|Style|2000-2001|2002-2004|2003-2005|2006-2007\n") }.must_raise TChartError
|
140
|
+
error.message.must_equal "date range 2002.1.1-2004.12.31 overlaps 2003.1.1-2005.12.31"
|
141
|
+
end
|
142
|
+
|
143
|
+
it "raises an error if a range end date is before a range start date" do
|
144
|
+
error = ->{ @parser.parse("Description|Style|2001.2.22-2000.4.14\n") }.must_raise TChartError
|
145
|
+
error.message.must_equal "date range end 2000.4.14 before start 2001.2.22"
|
146
|
+
end
|
147
|
+
|
148
|
+
it "raises an error if two sets of dates are not separated by a pipe" do
|
149
|
+
error = ->{ @parser.parse("Description|Style|2001-2002 2003-2004\n") }.must_raise TChartError
|
150
|
+
error.message.must_equal "bad date range \"2001-2002 2003-2004\"; expecting 2000.4.17-2001.7.21 | 2002.4-2003, etc."
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
end
|
@@ -0,0 +1,189 @@
|
|
1
|
+
require_relative '../../test_helper'
|
2
|
+
|
3
|
+
module TChart
|
4
|
+
|
5
|
+
describe LayoutBuilder, "build" do
|
6
|
+
|
7
|
+
include TestHelper
|
8
|
+
|
9
|
+
before do
|
10
|
+
@settings = make_settings
|
11
|
+
@items = make_items_with_ranges('2000.11.1-2005.3.21', '2002.4.17-2009.3.30')
|
12
|
+
@errors = stub
|
13
|
+
end
|
14
|
+
|
15
|
+
it "returns a layout and errors" do
|
16
|
+
LayoutBuilder.stubs(:check_layout).returns @errors
|
17
|
+
layout, errors = LayoutBuilder.build(@settings, @items)
|
18
|
+
layout.wont_be_nil
|
19
|
+
errors.must_be_same_as @errors
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
describe LayoutBuilder, "check_layout" do
|
26
|
+
|
27
|
+
before do
|
28
|
+
@layout = stub
|
29
|
+
end
|
30
|
+
|
31
|
+
it "returns an error if the plot area is not wide enough" do
|
32
|
+
@layout.stubs(:x_axis_length).returns 0
|
33
|
+
errors = LayoutBuilder.check_layout(@layout)
|
34
|
+
errors.find {|item| item =~ /plot area is too narrow/}.wont_be_nil
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
describe LayoutBuilder, "x_axis_tick_dates" do
|
41
|
+
|
42
|
+
include TestHelper
|
43
|
+
|
44
|
+
before do
|
45
|
+
@settings = make_settings
|
46
|
+
@this_year = Date.today.year
|
47
|
+
end
|
48
|
+
|
49
|
+
it "uses 1st January to 31st December when chart items is empty" do
|
50
|
+
items = []
|
51
|
+
layout, _ = LayoutBuilder.build(@settings, items)
|
52
|
+
layout.x_axis_tick_dates.must_equal make_tick_dates(@this_year, @this_year + 1, 1)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "sets 1st January to 31st December when none of the chart items have date ranges" do
|
56
|
+
items = [ stub( date_ranges: [] ) ]
|
57
|
+
layout, _ = LayoutBuilder.build(@settings, items)
|
58
|
+
layout.x_axis_tick_dates.must_equal make_tick_dates(@this_year, @this_year + 1, 1)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "sets the correct dates when the items date range is less than 10 years" do
|
62
|
+
items = make_items_with_ranges '2000.3.17-2004.10.4'
|
63
|
+
layout, _ = LayoutBuilder.build(@settings, items)
|
64
|
+
layout.x_axis_tick_dates.must_equal make_tick_dates(2000, 2005, 1)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "sets the correct dates when the items date range is 10 years" do
|
68
|
+
items = make_items_with_ranges '2000.3.17-2009.10.4'
|
69
|
+
layout, _ = LayoutBuilder.build(@settings, items)
|
70
|
+
layout.x_axis_tick_dates.must_equal make_tick_dates(2000, 2010, 1)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "sets the correct dates when the items date range is 11 years" do
|
74
|
+
items = make_items_with_ranges '2000.3.17-2010.10.4'
|
75
|
+
layout, _ = LayoutBuilder.build(@settings, items)
|
76
|
+
layout.x_axis_tick_dates.must_equal make_tick_dates(2000, 2015, 5)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "sets the correct dates when the items date range is less than 50 years" do
|
80
|
+
items = make_items_with_ranges '2000.3.17-2044.10.4'
|
81
|
+
layout, _ = LayoutBuilder.build(@settings, items)
|
82
|
+
layout.x_axis_tick_dates.must_equal make_tick_dates(2000, 2045, 5)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "sets the correct dates when the items date range is 50 years" do
|
86
|
+
items = make_items_with_ranges '2000.3.17-2049.10.4'
|
87
|
+
layout, _ = LayoutBuilder.build(@settings, items)
|
88
|
+
layout.x_axis_tick_dates.must_equal make_tick_dates(2000, 2050, 5)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "sets the correct dates when the items date range is less than 60 years" do
|
92
|
+
items = make_items_with_ranges '2000.3.17-2054.10.4'
|
93
|
+
layout, _ = LayoutBuilder.build(@settings, items)
|
94
|
+
layout.x_axis_tick_dates.must_equal make_tick_dates(2000, 2060, 10)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "sets the correct dates when the items date range is 60 years" do
|
98
|
+
items = make_items_with_ranges '2000.3.17-2059.10.4'
|
99
|
+
layout, _ = LayoutBuilder.build(@settings, items)
|
100
|
+
layout.x_axis_tick_dates.must_equal make_tick_dates(2000, 2060, 10)
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
|
106
|
+
describe LayoutBuilder, "x_axis_tick_x_coordinates" do
|
107
|
+
|
108
|
+
include TestHelper
|
109
|
+
|
110
|
+
before do
|
111
|
+
@settings = make_settings
|
112
|
+
@items = make_items_with_ranges('2000.11.1-2005.3.21', '2002.4.17-2009.3.30')
|
113
|
+
end
|
114
|
+
|
115
|
+
it "sets an array of x coordinates" do
|
116
|
+
layout, _ = LayoutBuilder.build(@settings, @items)
|
117
|
+
layout.x_axis_tick_x_coordinates.must_equal (0..100).step(10.0).to_a
|
118
|
+
end
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
|
123
|
+
describe LayoutBuilder, "x_axis_length" do
|
124
|
+
|
125
|
+
include TestHelper
|
126
|
+
|
127
|
+
before do
|
128
|
+
@settings = make_settings
|
129
|
+
@items = make_items_with_ranges('2000.11.1-2005.3.21', '2002.4.17-2009.3.30')
|
130
|
+
end
|
131
|
+
|
132
|
+
it "sets the correct length" do
|
133
|
+
layout, _ = LayoutBuilder.build(@settings, @items)
|
134
|
+
layout.x_axis_length.must_equal @settings.chart_width - @settings.x_axis_label_width - @settings.y_axis_label_width
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
describe LayoutBuilder, "y_axis_length" do
|
141
|
+
|
142
|
+
include TestHelper
|
143
|
+
|
144
|
+
before do
|
145
|
+
@settings = make_settings
|
146
|
+
@items = make_items_with_ranges('2000.11.1-2005.3.21', '2002.4.17-2009.3.30')
|
147
|
+
end
|
148
|
+
|
149
|
+
it "sets the correct length" do
|
150
|
+
layout, _ = LayoutBuilder.build(@settings, @items)
|
151
|
+
layout.y_axis_length.must_equal @settings.line_height * (@items.length + 1)
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
|
156
|
+
|
157
|
+
describe LayoutBuilder, "y_axis_label_x_coordinate" do
|
158
|
+
|
159
|
+
include TestHelper
|
160
|
+
|
161
|
+
before do
|
162
|
+
@settings = make_settings
|
163
|
+
@items = make_items_with_ranges('2000.11.1-2005.3.21', '2002.4.17-2009.3.30')
|
164
|
+
end
|
165
|
+
|
166
|
+
it "sets the correct value" do
|
167
|
+
layout, _ = LayoutBuilder.build(@settings, @items)
|
168
|
+
layout.y_axis_label_x_coordinate.must_equal 0 - ((@settings.y_axis_label_width / 2.0) + (@settings.x_axis_label_width / 2.0))
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
|
174
|
+
describe Layout, "y_axis_tick_y_coordinates" do
|
175
|
+
|
176
|
+
include TestHelper
|
177
|
+
|
178
|
+
before do
|
179
|
+
@settings = make_settings
|
180
|
+
@items = make_items_with_ranges('2000.11.1-2005.3.21', '2002.4.17-2009.3.30')
|
181
|
+
end
|
182
|
+
|
183
|
+
it "returns the y coordinates of all items" do
|
184
|
+
layout, _ = LayoutBuilder.build(@settings, @items)
|
185
|
+
layout.y_axis_tick_y_coordinates.must_equal [8, 4]
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
end
|