tchart 1.0.2
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.
- 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
|