smart_chart 0.0.1
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/.document +5 -0
- data/.gitignore +5 -0
- data/LICENSE +20 -0
- data/README.rdoc +187 -0
- data/Rakefile +56 -0
- data/lib/smart_chart/base_chart.rb +428 -0
- data/lib/smart_chart/charts/bar.rb +20 -0
- data/lib/smart_chart/charts/line.rb +22 -0
- data/lib/smart_chart/charts/map.rb +163 -0
- data/lib/smart_chart/charts/meter.rb +13 -0
- data/lib/smart_chart/charts/pie.rb +32 -0
- data/lib/smart_chart/charts/qr_code.rb +85 -0
- data/lib/smart_chart/charts/radar.rb +14 -0
- data/lib/smart_chart/charts/scatter.rb +21 -0
- data/lib/smart_chart/charts/venn.rb +13 -0
- data/lib/smart_chart/data_set.rb +15 -0
- data/lib/smart_chart/encoder.rb +226 -0
- data/lib/smart_chart/exceptions.rb +43 -0
- data/lib/smart_chart/features/axis_lines.rb +29 -0
- data/lib/smart_chart/features/grid_lines.rb +47 -0
- data/lib/smart_chart/features/labels.rb +23 -0
- data/lib/smart_chart/multiple_data_set_chart.rb +128 -0
- data/lib/smart_chart/single_data_set_chart.rb +56 -0
- data/lib/smart_chart.rb +30 -0
- data/test/smart_charts_test.rb +400 -0
- data/test/test_helper.rb +42 -0
- metadata +82 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
module SmartChart
|
2
|
+
module GridLines
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval do
|
6
|
+
attr_accessor :grid
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
private # ---------------------------------------------------------------
|
12
|
+
|
13
|
+
##
|
14
|
+
# Grid lines parameter.
|
15
|
+
#
|
16
|
+
def chg
|
17
|
+
return nil unless (grid.is_a?(Hash) and (grid[:x] or grid[:y]))
|
18
|
+
style = line_style_to_array(grid)
|
19
|
+
[ x_grid_property(:every) || 0,
|
20
|
+
y_grid_property(:every) || 0,
|
21
|
+
style[1],
|
22
|
+
style[2],
|
23
|
+
x_grid_property(:offset) || 0,
|
24
|
+
y_grid_property(:offset) || 0
|
25
|
+
].join(",")
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# Compute x-grid :every or :offset (as a string).
|
30
|
+
#
|
31
|
+
def x_grid_property(property)
|
32
|
+
return nil unless grid.is_a?(Hash)
|
33
|
+
return nil unless (grid[:x].is_a?(Hash) and s = grid[:x][property])
|
34
|
+
SmartChart.decimal_string(s.to_f * 100 / data_values_count.to_f)
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# Compute y-grid :every or :offset (as a string).
|
39
|
+
#
|
40
|
+
def y_grid_property(property)
|
41
|
+
return nil unless grid.is_a?(Hash)
|
42
|
+
return nil unless (grid[:y].is_a?(Hash) and s = grid[:y][property])
|
43
|
+
range = y_max - y_min
|
44
|
+
SmartChart.decimal_string(s.to_f * 100 / range.to_f)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SmartChart
|
2
|
+
module Labels
|
3
|
+
|
4
|
+
def self.included(base)
|
5
|
+
base.class_eval do
|
6
|
+
attr_accessor :labels
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
private # ---------------------------------------------------------------
|
12
|
+
|
13
|
+
##
|
14
|
+
# Labels parameter.
|
15
|
+
#
|
16
|
+
def chdl
|
17
|
+
unless bare_data_set?
|
18
|
+
labels = data.map{ |d| d.is_a?(Hash) ? d[:label] : nil }
|
19
|
+
labels.compact.size > 0 ? labels.join("|") : nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
module SmartChart
|
2
|
+
class MultipleDataSetChart < BaseChart
|
3
|
+
include Labels
|
4
|
+
include AxisLines
|
5
|
+
|
6
|
+
private # ---------------------------------------------------------------
|
7
|
+
|
8
|
+
##
|
9
|
+
# Extract an array of arrays (data sets) from the +data+ attribute.
|
10
|
+
#
|
11
|
+
def data_values
|
12
|
+
if bare_data_set?
|
13
|
+
[data]
|
14
|
+
else
|
15
|
+
data.map{ |set| set.is_a?(Hash) ? set[:values] : set }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
##
|
20
|
+
# Array of all possible query string parameters.
|
21
|
+
#
|
22
|
+
def query_string_params
|
23
|
+
super + [:chls]
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# Line style parameter.
|
28
|
+
#
|
29
|
+
def chls
|
30
|
+
validate_data_format
|
31
|
+
return nil if bare_data_set?
|
32
|
+
lines = data.map do |set|
|
33
|
+
if set.is_a?(Hash)
|
34
|
+
line_style_to_array(set)
|
35
|
+
else
|
36
|
+
[1, 1, 0]
|
37
|
+
end
|
38
|
+
end
|
39
|
+
# only return non-nil if styles other than default are given
|
40
|
+
if lines.map{ |l| l == [1,1,0] ? nil : 1 }.compact.size > 0
|
41
|
+
lines.map{ |s| s.join(",") }.join("|")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
# Translate a line style to a three-element array:
|
47
|
+
#
|
48
|
+
# [thickness, solid, blank]
|
49
|
+
#
|
50
|
+
# Takes a hash or a symbol (shortcut for a pre-defined look).
|
51
|
+
#
|
52
|
+
def line_style_to_array(data)
|
53
|
+
return [1, 1, 0] if data.nil?
|
54
|
+
thickness = data[:thickness] || 1
|
55
|
+
style = data[:style]
|
56
|
+
style_arr = style.is_a?(Hash) ? [style[:solid], style[:blank]] :
|
57
|
+
line_style_definition(style, thickness)
|
58
|
+
[thickness] + style_arr
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# Translate a symbol into a line style: a two-element array (solid line
|
63
|
+
# length, blank line length). Takes a style name and line thickness.
|
64
|
+
#
|
65
|
+
def line_style_definition(symbol, thickness = 1)
|
66
|
+
self.class.line_styles(thickness)[symbol] || [1, 0]
|
67
|
+
end
|
68
|
+
|
69
|
+
##
|
70
|
+
# Get a hash of line style definitions.
|
71
|
+
#
|
72
|
+
def self.line_styles(thickness = 1)
|
73
|
+
{
|
74
|
+
:solid => [thickness * 1, thickness * 0],
|
75
|
+
:dotted => [thickness * 1, thickness * 1],
|
76
|
+
:short => [thickness * 2, thickness * 4],
|
77
|
+
:dashed => [thickness * 4, thickness * 4],
|
78
|
+
:long => [thickness * 6, thickness * 4]
|
79
|
+
}
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# Array of validations to be run on the chart.
|
84
|
+
#
|
85
|
+
def validations
|
86
|
+
[:line_style_names] + super
|
87
|
+
end
|
88
|
+
|
89
|
+
##
|
90
|
+
# Raise an exception unless the provided data is given as an array.
|
91
|
+
#
|
92
|
+
def validate_data_format
|
93
|
+
unless data.is_a?(Array)
|
94
|
+
raise DataFormatError, "Data set(s) should be given as an array"
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
##
|
99
|
+
# Make sure colors are valid hex codes.
|
100
|
+
#
|
101
|
+
def validate_colors
|
102
|
+
super
|
103
|
+
data.each do |d|
|
104
|
+
if d.is_a?(Hash) and c = d[:color]
|
105
|
+
validate_color(c)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def validate_line_style_names
|
111
|
+
data.each do |d|
|
112
|
+
if d.is_a?(Hash) and d.is_a?(Hash)
|
113
|
+
if (style = d[:style]).is_a?(Symbol)
|
114
|
+
unless self.class.line_styles.keys.include?(style)
|
115
|
+
raise LineStyleNameError,
|
116
|
+
"Line style name '#{style}' is not valid. " +
|
117
|
+
"Try one of: #{self.class.line_styles.keys.join(', ')}"
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
|
126
|
+
class LineStyleNameError < ValidationError #:nodoc:
|
127
|
+
end
|
128
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
module SmartChart
|
2
|
+
class SingleDataSetChart < BaseChart
|
3
|
+
|
4
|
+
# colors to be used
|
5
|
+
attr_accessor :colors
|
6
|
+
|
7
|
+
|
8
|
+
private # ---------------------------------------------------------------
|
9
|
+
|
10
|
+
##
|
11
|
+
# Data to be encoded.
|
12
|
+
#
|
13
|
+
def data_values
|
14
|
+
d = data.is_a?(Hash) ? data.to_a : data
|
15
|
+
[d.inject([]){ |values,i| values << i[1] }]
|
16
|
+
end
|
17
|
+
|
18
|
+
##
|
19
|
+
# Texts of labels.
|
20
|
+
#
|
21
|
+
def labels
|
22
|
+
d = data.is_a?(Hash) ? data.to_a : data
|
23
|
+
d.inject([]){ |values,i| values << i[0] }
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# Raise an exception unless the provided data is given as an array.
|
28
|
+
#
|
29
|
+
def validate_data_format
|
30
|
+
unless data.is_a?(Hash)
|
31
|
+
raise DataFormatError, "Data should be given as a hash"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Make sure colors are valid hex codes.
|
37
|
+
#
|
38
|
+
def validate_colors
|
39
|
+
super
|
40
|
+
return if colors.nil?
|
41
|
+
colors.each{ |c| validate_color(c) }
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Labels parameter.
|
46
|
+
#
|
47
|
+
def chdl
|
48
|
+
data.is_a?(Array) ? nil : data.keys.join("|")
|
49
|
+
end
|
50
|
+
|
51
|
+
# chco
|
52
|
+
def chco
|
53
|
+
colors.join(',') unless colors.nil?
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/smart_chart.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# external dependencies
|
2
|
+
require 'cgi'
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), "smart_chart"))
|
5
|
+
|
6
|
+
# common code
|
7
|
+
require 'encoder'
|
8
|
+
require 'exceptions'
|
9
|
+
|
10
|
+
# features
|
11
|
+
require 'features/axis_lines'
|
12
|
+
require 'features/grid_lines'
|
13
|
+
require 'features/labels'
|
14
|
+
|
15
|
+
# chart parents
|
16
|
+
require 'base_chart'
|
17
|
+
require 'single_data_set_chart'
|
18
|
+
require 'multiple_data_set_chart'
|
19
|
+
|
20
|
+
# chart types
|
21
|
+
require 'charts/bar'
|
22
|
+
require 'charts/line'
|
23
|
+
require 'charts/map'
|
24
|
+
require 'charts/meter'
|
25
|
+
require 'charts/pie'
|
26
|
+
require 'charts/qr_code'
|
27
|
+
require 'charts/radar'
|
28
|
+
require 'charts/scatter'
|
29
|
+
require 'charts/venn'
|
30
|
+
|
@@ -0,0 +1,400 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class SmartChartTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
# --- labels --------------------------------------------------------------
|
6
|
+
|
7
|
+
def test_line_graph_labels
|
8
|
+
c = line_graph(:data => [{
|
9
|
+
:values => [1,2,3],
|
10
|
+
:label => "One"
|
11
|
+
},{
|
12
|
+
:values => [4,5,6],
|
13
|
+
:label => "Two"
|
14
|
+
}])
|
15
|
+
assert_equal "One|Two", c.send(:chdl)
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
# --- background color ----------------------------------------------------
|
20
|
+
|
21
|
+
def test_line_graph_background_color
|
22
|
+
c = line_graph(:background => "000000")
|
23
|
+
assert_equal "bg,s,000000", c.send(:chf)
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
# --- margins -------------------------------------------------------------
|
28
|
+
|
29
|
+
def test_margins
|
30
|
+
c = line_graph(
|
31
|
+
:margins => {
|
32
|
+
:top => 10,
|
33
|
+
:bottom => 15,
|
34
|
+
:left => 5,
|
35
|
+
:right => 25
|
36
|
+
}
|
37
|
+
)
|
38
|
+
assert_equal "5,25,10,15", c.send(:chma).to_s
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
# --- legend --------------------------------------------------------------
|
43
|
+
|
44
|
+
def test_legend_dimensions
|
45
|
+
c = line_graph(
|
46
|
+
:legend => {
|
47
|
+
:width => 50,
|
48
|
+
:height => 20
|
49
|
+
}
|
50
|
+
)
|
51
|
+
assert_equal "0,0,0,0|50,20", c.send(:chma).to_s
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
# --- line styles ---------------------------------------------------------
|
56
|
+
|
57
|
+
def test_line_styles
|
58
|
+
c = line_graph(
|
59
|
+
:data => [{
|
60
|
+
:values => [1,2,3],
|
61
|
+
:thickness => 4,
|
62
|
+
:style => {:solid => 3, :blank => 2}
|
63
|
+
},{
|
64
|
+
:values => [3,1,2],
|
65
|
+
:thickness => 2,
|
66
|
+
:style => {:solid => 1, :blank => 3}
|
67
|
+
}]
|
68
|
+
)
|
69
|
+
# handle multiple data sets correctly
|
70
|
+
assert_equal "4,3,2|2,1,3", c.send(:chls).to_s
|
71
|
+
|
72
|
+
# apply default line style automatically
|
73
|
+
c.data[1][:thickness] = nil
|
74
|
+
c.data[1][:style] = nil
|
75
|
+
assert_equal "4,3,2|1,1,0", c.send(:chls).to_s
|
76
|
+
|
77
|
+
# apply line style by name
|
78
|
+
c.data[0][:style] = :dotted
|
79
|
+
assert_equal "4,4,4|1,1,0", c.send(:chls).to_s
|
80
|
+
|
81
|
+
# raise exception on invalid style name
|
82
|
+
assert_raise(SmartChart::LineStyleNameError) do
|
83
|
+
c.data[0][:style] = :asdf
|
84
|
+
c.validate!
|
85
|
+
end
|
86
|
+
|
87
|
+
# omit chls parameter if no styles specified
|
88
|
+
c.data[0][:thickness] = nil
|
89
|
+
assert_equal "", c.send(:chls).to_s
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
# --- grid lines ----------------------------------------------------------
|
94
|
+
|
95
|
+
def test_grid_lines
|
96
|
+
c = line_graph(
|
97
|
+
:data => [0, 2, 3, 4, 5, 6, 7, 8],
|
98
|
+
:grid => {
|
99
|
+
:x => {:every => 2, :offset => 1},
|
100
|
+
:y => {:every => 4, :offset => 2},
|
101
|
+
:color => "AABBCC",
|
102
|
+
:style => :dotted
|
103
|
+
}
|
104
|
+
)
|
105
|
+
assert_equal "25,50,1,1,12.5,25", c.send(:chg).to_s
|
106
|
+
|
107
|
+
# test x/y-step decimal points
|
108
|
+
c.data = [0, 2, 3, 4, 5, 6]
|
109
|
+
assert_equal "33.333,66.667,1,1,16.667,33.333", c.send(:chg).to_s
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
# --- axis lines ----------------------------------------------------------
|
114
|
+
|
115
|
+
def test_axis_lines
|
116
|
+
c = line_graph(
|
117
|
+
:data => [0, 2, 3, 4, 5, 6, 7, 8],
|
118
|
+
:axis => {
|
119
|
+
:color => "AABBCC",
|
120
|
+
:style => :dotted
|
121
|
+
}
|
122
|
+
)
|
123
|
+
assert_nil c.send(:chxt)
|
124
|
+
assert_equal "???", c.send(:chxs).to_s
|
125
|
+
|
126
|
+
# test axis side specification
|
127
|
+
c.axis[:sides] = [:left, :bottom, :right]
|
128
|
+
assert_equal "???", c.send(:chxt).to_s
|
129
|
+
|
130
|
+
# test no axis specification
|
131
|
+
c.axis[:sides] = []
|
132
|
+
assert_equal "ls", c.send(:cht).to_s
|
133
|
+
assert_nil c.send(:chxt)
|
134
|
+
assert_nil c.send(:chxs)
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
# --- pie -----------------------------------------------------------------
|
139
|
+
|
140
|
+
def test_pie_chart_rotation
|
141
|
+
c = pie_chart(:rotate => 45)
|
142
|
+
assert_equal "5.498", c.send(:chp)
|
143
|
+
|
144
|
+
# 90-degree rotation is Google default
|
145
|
+
c.rotate = -90
|
146
|
+
assert_equal "3.142", c.send(:chp)
|
147
|
+
|
148
|
+
# 90-degree rotation is Google default
|
149
|
+
c.rotate = 90
|
150
|
+
assert_nil c.send(:chp)
|
151
|
+
end
|
152
|
+
|
153
|
+
|
154
|
+
# --- qr code ------------------------------------------------------------
|
155
|
+
|
156
|
+
def test_qr_code
|
157
|
+
c = SmartChart::QRCode.new(
|
158
|
+
:width => 200, :height => 200,
|
159
|
+
:data => "some data",
|
160
|
+
:encoding => :iso88591)
|
161
|
+
assert_equal "some data", c.send(:chl)
|
162
|
+
assert_equal "ISO-8859-1", c.send(:choe)
|
163
|
+
assert_nil c.send(:chld)
|
164
|
+
|
165
|
+
# omit default margin
|
166
|
+
c.margin = 4
|
167
|
+
assert_nil c.send(:chld)
|
168
|
+
|
169
|
+
# print non-default margin
|
170
|
+
c.margin = 6
|
171
|
+
assert_equal "L|6", c.send(:chld)
|
172
|
+
|
173
|
+
# print non-default margin
|
174
|
+
c.ec_level = :m
|
175
|
+
assert_equal "M|6", c.send(:chld)
|
176
|
+
|
177
|
+
# don't print default margin
|
178
|
+
c.margin = 4
|
179
|
+
assert_equal "M", c.send(:chld)
|
180
|
+
end
|
181
|
+
|
182
|
+
|
183
|
+
# --- line graph ----------------------------------------------------------
|
184
|
+
|
185
|
+
def test_line_graph
|
186
|
+
c = line_graph(
|
187
|
+
:data => [{
|
188
|
+
:values => [2,1,3,4,5,9],
|
189
|
+
:color => '552255'
|
190
|
+
},{
|
191
|
+
:values => [1,6,4,8,7,5],
|
192
|
+
:color => '225522'
|
193
|
+
}]
|
194
|
+
)
|
195
|
+
assert_equal "s:HAPWe9,AmW1te", c.send(:chd).to_s
|
196
|
+
assert_equal "552255,225522", c.send(:chco)
|
197
|
+
end
|
198
|
+
|
199
|
+
|
200
|
+
# --- map -----------------------------------------------------------------
|
201
|
+
|
202
|
+
def test_map_data_point_colors
|
203
|
+
c = map_chart(:colors => %w[111111 222222 333333])
|
204
|
+
assert_equal "FFFFFF,111111,222222,333333", c.send(:chco)
|
205
|
+
end
|
206
|
+
|
207
|
+
def test_map_data_and_labels
|
208
|
+
c = map_chart(:data => [
|
209
|
+
[:CA, 81],
|
210
|
+
[:US, 49],
|
211
|
+
[:AU, 96],
|
212
|
+
[:RU, 45],
|
213
|
+
[:MX, 14]
|
214
|
+
])
|
215
|
+
assert_equal "s:xa9XA", c.send(:chd).to_s
|
216
|
+
assert_equal "CAUSAURUMX", c.send(:chld).to_s
|
217
|
+
end
|
218
|
+
|
219
|
+
def test_map_with_one_data_point
|
220
|
+
c = map_chart(:data => {:US => 7})
|
221
|
+
assert_nothing_raised {c.validate!}
|
222
|
+
end
|
223
|
+
|
224
|
+
def test_map_foreground_color
|
225
|
+
c = map_chart(:colors => %w[111111 222222 333333], :foreground => "BBBBBB")
|
226
|
+
assert_equal "BBBBBB,111111,222222,333333", c.send(:chco)
|
227
|
+
end
|
228
|
+
|
229
|
+
def test_map_background_color
|
230
|
+
c = map_chart(:background => "000000")
|
231
|
+
assert_equal "bg,s,000000", c.send(:chf)
|
232
|
+
end
|
233
|
+
|
234
|
+
def test_region_validation
|
235
|
+
invalids = ['middle east', 'china', 'USA']
|
236
|
+
valids = ['africa', 'europe']
|
237
|
+
code = lambda{ |region|
|
238
|
+
map_chart(:region => region).validate!
|
239
|
+
}
|
240
|
+
invalids.each do |i|
|
241
|
+
assert_raise(SmartChart::DataFormatError) { code.call(i) }
|
242
|
+
end
|
243
|
+
valids.each do |v|
|
244
|
+
assert_nothing_raised { code.call(v) }
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
def test_country_code_validation
|
249
|
+
invalids = ['USA', 'SW']
|
250
|
+
valids = ['US', 'CN', :CA]
|
251
|
+
code = lambda{ |c|
|
252
|
+
map_chart(:data => {:MX => 1, c => 2}).validate!
|
253
|
+
}
|
254
|
+
invalids.each do |i|
|
255
|
+
assert_raise(SmartChart::DataFormatError) { code.call(i) }
|
256
|
+
end
|
257
|
+
valids.each do |v|
|
258
|
+
assert_nothing_raised { code.call(v) }
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
def test_state_code_validation
|
263
|
+
invalids = ['JJ', 'DC']
|
264
|
+
valids = ['AL', 'MS', :GA]
|
265
|
+
code = lambda{ |s|
|
266
|
+
map_chart(:region => :usa, :data => {:NY => 1, s => 2}).validate!
|
267
|
+
}
|
268
|
+
invalids.each do |i|
|
269
|
+
assert_raise(SmartChart::DataFormatError) { code.call(i) }
|
270
|
+
end
|
271
|
+
valids.each do |v|
|
272
|
+
assert_nothing_raised { code.call(v) }
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
|
277
|
+
# --- encoding ------------------------------------------------------------
|
278
|
+
|
279
|
+
def test_simple_encoding
|
280
|
+
[
|
281
|
+
[[0, 10], nil, nil, 's:A9'],
|
282
|
+
[[0, 10], 0, 61, 's:AK'],
|
283
|
+
[[0, 11], 0, 61, 's:AL'],
|
284
|
+
[[0, 10, 26, 27], nil, nil, 's:AW69'],
|
285
|
+
[[0, 10, nil, 27], nil, nil, 's:AW_9']
|
286
|
+
|
287
|
+
].each do |data,min,max,encoding|
|
288
|
+
assert_equal encoding,
|
289
|
+
SmartChart::Encoder::Simple.new([data], min, max).to_s
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def test_text_encoding
|
294
|
+
[
|
295
|
+
[[0, 10], nil, nil, 't:0,100'],
|
296
|
+
[[0, 10], 0, 100, 't:0,10'],
|
297
|
+
[[0, 11], 0, 100, 't:0,11'],
|
298
|
+
[[0, 10, 26, 27], nil, nil, 't:0,37,96,100'],
|
299
|
+
[[0, 10, nil, 27], nil, nil, 't:0,37,-1,100']
|
300
|
+
|
301
|
+
].each do |data,min,max,encoding|
|
302
|
+
assert_equal encoding,
|
303
|
+
SmartChart::Encoder::Text.new([data], min, max).to_s
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
def test_extended_encoding
|
308
|
+
[
|
309
|
+
[[0, 10], nil, nil, 'e:AA..'],
|
310
|
+
[[0, 10], 0, 4095, 'e:AAAK'],
|
311
|
+
[[0, 11], 0, 4095, 'e:AAAL'],
|
312
|
+
[[0, 10, 26, 27], nil, nil, 'e:AAXs9n..'],
|
313
|
+
[[0, 10, nil, 27], nil, nil, 'e:AAXs__..']
|
314
|
+
|
315
|
+
].each do |data,min,max,encoding|
|
316
|
+
assert_equal encoding,
|
317
|
+
SmartChart::Encoder::Extended.new([data], min, max).to_s
|
318
|
+
end
|
319
|
+
end
|
320
|
+
|
321
|
+
def test_encoding_multiple_data_sets
|
322
|
+
assert_equal "s:ANbo,GUhv",
|
323
|
+
SmartChart::Encoder::Simple.new([[1,3,5,7], [2,4,6,8]], 1, 10).to_s
|
324
|
+
end
|
325
|
+
|
326
|
+
def test_mixed_data_set_formats
|
327
|
+
c = SmartChart::Line.new(
|
328
|
+
:width => 400,
|
329
|
+
:height => 200,
|
330
|
+
:data => [ [2,1,3,4,5,9], {:values => [1,6,4,8,7,5]} ]
|
331
|
+
)
|
332
|
+
assert_equal "s:HAPWe9,AmW1te", c.send(:chd).to_s
|
333
|
+
end
|
334
|
+
|
335
|
+
def test_encoding_with_y_min_and_max
|
336
|
+
c = line_graph(
|
337
|
+
:y_min => -20,
|
338
|
+
:y_max => 10,
|
339
|
+
:data => [2,1,3,4,5,9]
|
340
|
+
)
|
341
|
+
assert_equal "s:squwy6", c.send(:chd).to_s
|
342
|
+
end
|
343
|
+
|
344
|
+
|
345
|
+
# --- validation ----------------------------------------------------------
|
346
|
+
|
347
|
+
def test_required_attributes_validation
|
348
|
+
assert_raise SmartChart::MissingRequiredAttributeError do
|
349
|
+
SmartChart::Map.new(:width => 500, :height => 50).validate!
|
350
|
+
end
|
351
|
+
assert_raise SmartChart::MissingRequiredAttributeError do
|
352
|
+
SmartChart::Map.new(:data => []).validate!
|
353
|
+
end
|
354
|
+
end
|
355
|
+
|
356
|
+
def test_map_width_validation
|
357
|
+
assert_raise SmartChart::DimensionsError do
|
358
|
+
map_chart(:width => 500).validate!
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
def test_map_height_validation
|
363
|
+
assert_raise SmartChart::DimensionsError do
|
364
|
+
map_chart(:height => 300).validate!
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
def test_dimensions_validation
|
369
|
+
assert_raise SmartChart::DimensionsError do
|
370
|
+
line_graph(:width => 800, :height => 600).validate!
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
def test_color_validation
|
375
|
+
valids = %w[fcfcfc FCFCFC 123456 a1b2c3]
|
376
|
+
invalids = %w[fcf 012 12345q 1234567]
|
377
|
+
code = lambda{ |color|
|
378
|
+
line_graph(:data => [{
|
379
|
+
:values => [1,2,3],
|
380
|
+
:color => color
|
381
|
+
}]
|
382
|
+
).validate!
|
383
|
+
}
|
384
|
+
invalids.each do |color|
|
385
|
+
assert_raise(SmartChart::ColorFormatError) { code.call(color) }
|
386
|
+
end
|
387
|
+
valids.each do |color|
|
388
|
+
assert_nothing_raised { code.call(color) }
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
|
393
|
+
# --- exceptions ----------------------------------------------------------
|
394
|
+
|
395
|
+
def test_chart_attribute_error
|
396
|
+
assert_raise SmartChart::NoAttributeError do
|
397
|
+
line_graph(:asdf => "hi")
|
398
|
+
end
|
399
|
+
end
|
400
|
+
end
|