plotrb 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,46 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe 'Mark' do
4
+
5
+ subject { ::Plotrb::Mark.rect }
6
+
7
+ describe '#initialize' do
8
+
9
+ context 'when type is group' do
10
+
11
+ subject { ::Plotrb::Mark.group }
12
+
13
+ it 'has additional scales, axes, and marks attribute' do
14
+ subject.attributes.should include(:scales, :axes, :marks)
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+
21
+ describe 'properties' do
22
+
23
+ it 'allows multiple properties' do
24
+ ::Plotrb::Kernel.stub(:find_data).with('some_data').and_return(true)
25
+ subject.from('some_data')
26
+ subject.enter
27
+ subject.exit
28
+ subject.properties.keys.should match_array([:enter, :exit])
29
+ end
30
+
31
+ end
32
+
33
+ describe '#from' do
34
+
35
+ it 'recognizes Data and Transform objects' do
36
+ foo = ::Plotrb::Transform.facet
37
+ bar = ::Plotrb::Transform.filter
38
+ ::Plotrb::Kernel.stub(:find_data).with('some_data').and_return(true)
39
+ subject.from('some_data', foo, bar)
40
+ subject.send(:process_from)
41
+ subject.from.should == {:data => 'some_data', :transform => [foo, bar]}
42
+ end
43
+
44
+ end
45
+
46
+ end
@@ -0,0 +1,187 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe 'Scale' do
4
+
5
+ subject { ::Plotrb::Scale.new }
6
+
7
+ describe '#name' do
8
+
9
+ it 'sets name of the scale' do
10
+ subject.name 'foo_scale'
11
+ subject.name.should == 'foo_scale'
12
+ end
13
+
14
+ it 'raises error if the name is not unique' do
15
+ subject.name 'foo'
16
+ ::Plotrb::Kernel.stub(:duplicate_scale?).and_return(true)
17
+ expect { subject.send(:process_name) }.to raise_error(ArgumentError)
18
+ end
19
+
20
+ end
21
+
22
+ describe '#type' do
23
+
24
+ it 'does not allow changing type once initialized' do
25
+ expect { subject.type(:other_type) }.to raise_error(ArgumentError)
26
+ end
27
+
28
+ end
29
+
30
+ describe '#domain' do
31
+
32
+ context 'when domain is a string reference to a data source' do
33
+
34
+ before(:each) do
35
+ ::Plotrb::Kernel.stub(:find_data).and_return(::Plotrb::Data.new)
36
+ end
37
+
38
+ it 'separates data source and data field' do
39
+ subject.from('some_data.some_field')
40
+ ::Plotrb::Data.any_instance.stub(:extra_fields).and_return([])
41
+ subject.send(:process_domain)
42
+ subject.domain.data.should == 'some_data'
43
+ subject.domain.field.should == 'data.some_field'
44
+ end
45
+
46
+ it 'defaults field to index if not provided' do
47
+ subject.from('some_data')
48
+ ::Plotrb::Data.any_instance.stub(:extra_fields).and_return([])
49
+ subject.send(:process_domain)
50
+ subject.domain.data.should == 'some_data'
51
+ subject.domain.field.should == 'index'
52
+ end
53
+
54
+ it 'deals with index field properly' do
55
+ subject.from('some_data.index')
56
+ ::Plotrb::Data.any_instance.stub(:extra_fields).and_return([])
57
+ subject.send(:process_domain)
58
+ subject.domain.data.should == 'some_data'
59
+ subject.domain.field.should == 'index'
60
+ end
61
+
62
+ it 'recognizes extra fields added by transform' do
63
+ subject.from('some_data.field')
64
+ ::Plotrb::Data.any_instance.stub(:extra_fields).and_return([:field])
65
+ subject.send(:process_domain)
66
+ subject.domain.data.should == 'some_data'
67
+ subject.domain.field.should == 'field'
68
+ end
69
+ end
70
+
71
+ context 'when domain is actual ordinal/categorical data' do
72
+
73
+ it 'sets domain directly' do
74
+ data_set = %w(foo bar baz qux)
75
+ subject.from(data_set)
76
+ subject.domain.should == data_set
77
+ end
78
+
79
+ end
80
+
81
+ context 'when domain is a quantitative range' do
82
+
83
+ it 'sets domain as a two-element array' do
84
+ subject.from([1,100])
85
+ subject.domain.should == [1,100]
86
+ end
87
+
88
+ end
89
+
90
+ end
91
+
92
+ describe '#range' do
93
+
94
+ context 'when range is numeric' do
95
+
96
+ it 'sets range as a two-element array' do
97
+ subject.to([1,100])
98
+ subject.send(:process_range)
99
+ subject.range.should == [1,100]
100
+ end
101
+
102
+ end
103
+
104
+ context 'when range is ordinal' do
105
+
106
+ it 'sets range directly' do
107
+ range_set = %w(foo bar baz qux)
108
+ subject.to(range_set)
109
+ subject.send(:process_range)
110
+ subject.range.should == range_set
111
+ end
112
+
113
+ end
114
+
115
+ context 'when range is special literal' do
116
+
117
+ it 'sets correct range literal' do
118
+ subject.to_more_colors
119
+ subject.send(:process_range)
120
+ subject.range.should == :category20
121
+ end
122
+
123
+ it 'does not set invalid range literal' do
124
+ expect { subject.to_foo_bar_range }.to raise_error(NoMethodError)
125
+ subject.range.should be_nil
126
+ end
127
+
128
+ end
129
+
130
+ end
131
+
132
+ describe '#exponent' do
133
+
134
+ it 'sets the exponent of scale transformation' do
135
+ subject.in_exponent(10)
136
+ subject.exponent.should == 10
137
+ end
138
+
139
+ end
140
+
141
+ describe '#nice' do
142
+
143
+ context 'when scale is time or utc' do
144
+
145
+ subject { ::Plotrb::Scale.time }
146
+
147
+ it 'sets valid nice literal' do
148
+ subject.in_seconds
149
+ subject.nice.should == :second
150
+ end
151
+
152
+ it 'does not set invalid nice literal' do
153
+ expect { subject.in_millennium }.to raise_error(NoMethodError)
154
+ subject.nice.should be_nil
155
+ end
156
+
157
+ end
158
+
159
+ context 'when scale is quantitative' do
160
+
161
+ subject { ::Plotrb::Scale.linear }
162
+
163
+ it 'sets nice to true' do
164
+ subject.nicely
165
+ subject.nice?.should be_true
166
+ end
167
+
168
+ end
169
+
170
+ end
171
+
172
+ describe '#method_missing' do
173
+
174
+ it 'calls nice if in_foo is called' do
175
+ subject.type = :time
176
+ subject.should_receive(:nice).with(:second)
177
+ subject.in_seconds
178
+ end
179
+
180
+ it 'calls range if to_foo is called' do
181
+ subject.should_receive(:range).with(:colors)
182
+ subject.to_colors
183
+ end
184
+
185
+ end
186
+
187
+ end
@@ -0,0 +1,61 @@
1
+ #--
2
+ # simple_spec.rb: specs for simple plot shortcuts
3
+ # Copyright (c) 2013 Colin J. Fuller and the Ruby Science Foundation
4
+ # All rights reserved.
5
+ #
6
+ # Redistribution and use in source and binary forms, with or without
7
+ # modification, are permitted provided that the following conditions
8
+ # are met:
9
+ # - Redistributions of source code must retain the above copyright
10
+ # notice, this list of conditions and the following disclaimer.
11
+ #
12
+ # - Redistributions in binary form must reproduce the above copyright
13
+ # notice, this list of conditions and the following disclaimer in the
14
+ # documentation and/or other materials provided with the
15
+ # distribution.
16
+ #
17
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21
+ # HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22
+ # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23
+ # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24
+ # OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25
+ # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
+ # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
27
+ # WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
+ # POSSIBILITY OF SUCH DAMAGE.
29
+ #++
30
+
31
+ require 'spec_helper'
32
+ require 'plotrb/simple'
33
+
34
+ describe Plotrb::Simple do
35
+
36
+ context "scatter plots" do
37
+ before :each do
38
+ @xdata = [0,1,2,3,4,5]
39
+ @ydata = [[0,1,4,9,16,25],[0,1,8,27,64,125]]
40
+ end
41
+
42
+ it "should correctly make a scatter plot with supplied options" do
43
+ Plotrb::Simple.scatter(@xdata, @ydata, markersize: 40, domain: [0,10], range: [0,125], color: ['red', 'blue'], width: 1000, height: 1000, symbol: ['triangle-up', 'triangle-down']).generate_spec.should eq '{"width":1000,"height":1000,"data":[{"name":"scatter","values":[{"x0":0,"y0":0,"y1":0},{"x0":1,"y0":1,"y1":1},{"x0":2,"y0":4,"y1":8},{"x0":3,"y0":9,"y1":27},{"x0":4,"y0":16,"y1":64},{"x0":5,"y0":25,"y1":125}]}],"scales":[{"name":"scatter_x","type":"linear","domain":[0,10],"range":"width"},{"name":"scatter_y","type":"linear","domain":[0,125],"range":"height"}],"marks":[{"type":"symbol","from":{"data":"scatter"},"properties":{"enter":{"size":{"value":40},"shape":{"value":"triangle-up"},"x":{"field":"data.x0","scale":"scatter_x"},"y":{"field":"data.y0","scale":"scatter_y"},"fill":{"value":"red"}}}},{"type":"symbol","from":{"data":"scatter"},"properties":{"enter":{"size":{"value":40},"shape":{"value":"triangle-down"},"x":{"field":"data.x0","scale":"scatter_x"},"y":{"field":"data.y1","scale":"scatter_y"},"fill":{"value":"blue"}}}}],"axes":[{"type":"x","scale":"scatter_x"},{"type":"y","scale":"scatter_y"}]}'
44
+ end
45
+
46
+ it "should correctly make a scatter plot with default options and multiple data series" do
47
+ Plotrb::Simple.scatter(@xdata, @ydata).generate_spec.should eq '{"width":640,"height":480,"data":[{"name":"scatter","values":[{"x0":0,"y0":0,"y1":0},{"x0":1,"y0":1,"y1":1},{"x0":2,"y0":4,"y1":8},{"x0":3,"y0":9,"y1":27},{"x0":4,"y0":16,"y1":64},{"x0":5,"y0":25,"y1":125}]}],"scales":[{"name":"scatter_x","type":"linear","domain":{"data":"scatter","field":"data.x0"},"range":"width"},{"name":"scatter_y","type":"linear","domain":{"data":"scatter","field":"data.y0"},"range":"height"}],"marks":[{"type":"symbol","from":{"data":"scatter"},"properties":{"enter":{"size":{"value":20},"shape":{"value":"circle"},"x":{"field":"data.x0","scale":"scatter_x"},"y":{"field":"data.y0","scale":"scatter_y"},"fill":{"value":"blue"}}}},{"type":"symbol","from":{"data":"scatter"},"properties":{"enter":{"size":{"value":20},"shape":{"value":"circle"},"x":{"field":"data.x0","scale":"scatter_x"},"y":{"field":"data.y1","scale":"scatter_y"},"fill":{"value":"blue"}}}}],"axes":[{"type":"x","scale":"scatter_x"},{"type":"y","scale":"scatter_y"}]}'
48
+ end
49
+
50
+ it "should correctly make a scatter plot with default options and a single data series" do
51
+ Plotrb::Simple.scatter(@xdata, [0,1,4,9,16,25]).generate_spec.should eq '{"width":640,"height":480,"data":[{"name":"scatter","values":[{"x0":0,"y0":0},{"x0":1,"y0":1},{"x0":2,"y0":4},{"x0":3,"y0":9},{"x0":4,"y0":16},{"x0":5,"y0":25}]}],"scales":[{"name":"scatter_x","type":"linear","domain":{"data":"scatter","field":"data.x0"},"range":"width"},{"name":"scatter_y","type":"linear","domain":{"data":"scatter","field":"data.y0"},"range":"height"}],"marks":[{"type":"symbol","from":{"data":"scatter"},"properties":{"enter":{"size":{"value":20},"shape":{"value":"circle"},"x":{"field":"data.x0","scale":"scatter_x"},"y":{"field":"data.y0","scale":"scatter_y"},"fill":{"value":"blue"}}}}],"axes":[{"type":"x","scale":"scatter_x"},{"type":"y","scale":"scatter_y"}]}'
52
+ end
53
+
54
+ it "should correctly make a scatter plot with default options and multiple x and y data series" do
55
+ @xdata = [[0,1,2,3,4,16], [10,11,12,13,14,15]]
56
+ Plotrb::Simple.scatter(@xdata, @ydata).generate_spec.should eq '{"width":640,"height":480,"data":[{"name":"scatter","values":[{"x0":0,"y0":0,"x1":10,"y1":0},{"x0":1,"y0":1,"x1":11,"y1":1},{"x0":2,"y0":4,"x1":12,"y1":8},{"x0":3,"y0":9,"x1":13,"y1":27},{"x0":4,"y0":16,"x1":14,"y1":64},{"x0":16,"y0":25,"x1":15,"y1":125}]}],"scales":[{"name":"scatter_x","type":"linear","domain":{"data":"scatter","field":"data.x0"},"range":"width"},{"name":"scatter_y","type":"linear","domain":{"data":"scatter","field":"data.y0"},"range":"height"}],"marks":[{"type":"symbol","from":{"data":"scatter"},"properties":{"enter":{"size":{"value":20},"shape":{"value":"circle"},"x":{"field":"data.x0","scale":"scatter_x"},"y":{"field":"data.y0","scale":"scatter_y"},"fill":{"value":"blue"}}}},{"type":"symbol","from":{"data":"scatter"},"properties":{"enter":{"size":{"value":20},"shape":{"value":"circle"},"x":{"field":"data.x1","scale":"scatter_x"},"y":{"field":"data.y1","scale":"scatter_y"},"fill":{"value":"blue"}}}}],"axes":[{"type":"x","scale":"scatter_x"},{"type":"y","scale":"scatter_y"}]}'
57
+ end
58
+ end
59
+ end
60
+
61
+
@@ -0,0 +1,248 @@
1
+ require_relative '../spec_helper'
2
+
3
+ describe 'Transform' do
4
+
5
+ describe '#initialize' do
6
+
7
+ subject { Plotrb::Transform }
8
+
9
+ it 'calls respective type method to initialize attributes' do
10
+ subject.any_instance.should_receive(:send).with(:foo)
11
+ subject.new(:foo)
12
+ end
13
+
14
+ it 'raises error if type is not recognized' do
15
+ expect { subject.new(:foo) }.to raise_error(NoMethodError)
16
+ end
17
+
18
+ end
19
+
20
+ describe '#array' do
21
+
22
+ subject { Plotrb::Transform.new(:array) }
23
+
24
+ it 'responds to #take' do
25
+ subject.take('foo', 'bar')
26
+ subject.send(:process_array_fields)
27
+ subject.fields.should match_array(['data.foo', 'data.bar'])
28
+ end
29
+
30
+ end
31
+
32
+ describe '#copy' do
33
+
34
+ subject { Plotrb::Transform.new(:copy) }
35
+
36
+ it 'responds to #take' do
37
+ subject.take('foo_field', 'bar_field').from('some_data').as('foo', 'bar')
38
+ subject.fields.should match_array(['foo_field', 'bar_field'])
39
+ end
40
+
41
+ it 'raises error if as and fields are of different size' do
42
+ subject.take('foo', 'bar').from('data').as('baz')
43
+ expect { subject.send(:process_copy_as) }.to raise_error(ArgumentError)
44
+ end
45
+
46
+ end
47
+
48
+ describe '#cross' do
49
+
50
+ subject { Plotrb::Transform.new(:cross) }
51
+
52
+ it 'raises error if the secondary data does not exist' do
53
+ subject.with('foo')
54
+ ::Plotrb::Kernel.stub(:find_data).and_return(nil)
55
+ expect { subject.send(:process_cross_with) }.to raise_error(ArgumentError)
56
+ end
57
+
58
+ end
59
+
60
+ describe '#facet' do
61
+
62
+ subject { Plotrb::Transform.new(:facet) }
63
+
64
+ it 'responds to #group_by' do
65
+ subject.group_by('foo', 'bar')
66
+ subject.send(:process_facet_keys)
67
+ subject.keys.should match_array(['data.foo', 'data.bar'])
68
+ end
69
+
70
+ end
71
+
72
+ describe '#filter' do
73
+
74
+ subject { Plotrb::Transform.new(:filter) }
75
+
76
+ it 'adds variable d if not present in the test expression' do
77
+ subject.test('x>10')
78
+ expect { subject.send(:process_filter_test) }.to raise_error(ArgumentError)
79
+ end
80
+
81
+ end
82
+
83
+ describe '#flatten' do
84
+
85
+ subject { Plotrb::Transform.new(:flatten) }
86
+
87
+ end
88
+
89
+ describe '#fold' do
90
+
91
+ subject { Plotrb::Transform.new(:fold) }
92
+
93
+ it 'responds to #into' do
94
+ subject.into('foo', 'bar')
95
+ subject.send(:process_fold_fields)
96
+ subject.fields.should match_array(['data.foo', 'data.bar'])
97
+ end
98
+
99
+ end
100
+
101
+ describe '#formula' do
102
+
103
+ subject { Plotrb::Transform.new(:formula) }
104
+
105
+ it 'responds to #apply and #into' do
106
+ subject.apply('some_expression').into('some_field')
107
+ subject.field.should == 'some_field'
108
+ subject.expr.should == 'some_expression'
109
+ end
110
+
111
+ end
112
+
113
+ describe '#slice' do
114
+
115
+ subject { Plotrb::Transform.new(:slice) }
116
+
117
+ it 'slices by a single value'
118
+
119
+ it 'slices by a range'
120
+
121
+ it 'slices by special positions'
122
+
123
+ it 'raises error otherwise'
124
+
125
+ end
126
+
127
+ describe '#sort' do
128
+
129
+ subject { Plotrb::Transform.new(:sort) }
130
+
131
+ it 'adds - in front for reverse sort'
132
+
133
+ end
134
+
135
+ describe '#stats' do
136
+
137
+ subject { Plotrb::Transform.new(:stats) }
138
+
139
+ it 'responds to #from, #include_median, and #store_stats' do
140
+ subject.from('foo').include_median.store_stats
141
+ subject.value.should == 'foo'
142
+ subject.median.should be_true
143
+ subject.assign.should be_true
144
+ end
145
+
146
+ end
147
+
148
+ describe '#truncate' do
149
+
150
+ subject { Plotrb::Transform.new(:truncate) }
151
+
152
+ it 'responds to #from, #to, and #max_length' do
153
+ subject.from('foo').to('bar').max_length(5)
154
+ subject.send(:process_truncate_value)
155
+ subject.value.should == 'data.foo'
156
+ subject.output.should == 'bar'
157
+ subject.limit.should == 5
158
+ end
159
+
160
+ it 'responds to #in_position' do
161
+ subject.in_front
162
+ subject.position.should == :front
163
+ end
164
+
165
+ end
166
+
167
+ describe '#unique' do
168
+
169
+ subject { Plotrb::Transform.new(:unique) }
170
+
171
+ it 'responds to #from and #to' do
172
+ subject.from('foo').to('bar')
173
+ subject.send(:process_unique_field)
174
+ subject.field.should == 'data.foo'
175
+ subject.as.should == 'bar'
176
+ end
177
+
178
+ end
179
+
180
+ describe '#window' do
181
+
182
+ subject { Plotrb::Transform.new(:window) }
183
+
184
+ end
185
+
186
+ describe '#zip' do
187
+
188
+ subject { Plotrb::Transform.new(:zip) }
189
+
190
+ it 'responds to #match and #against' do
191
+ subject.with('foo').as('bar').match('foo_field').against('bar_field')
192
+ subject.send(:process_zip_key)
193
+ subject.send(:process_zip_with_key)
194
+ subject.key.should == 'data.foo_field'
195
+ subject.with_key.should == 'data.bar_field'
196
+ end
197
+
198
+ end
199
+
200
+ describe '#force' do
201
+
202
+ subject { Plotrb::Transform.new(:force) }
203
+
204
+ end
205
+
206
+ describe '#geo' do
207
+
208
+ subject { Plotrb::Transform.new(:geo) }
209
+
210
+ end
211
+
212
+ describe '#geopath' do
213
+
214
+ subject { Plotrb::Transform.new(:geopath) }
215
+
216
+ end
217
+
218
+ describe '#link' do
219
+
220
+ subject { Plotrb::Transform.new(:link) }
221
+
222
+ end
223
+
224
+ describe '#pie' do
225
+
226
+ subject { Plotrb::Transform.new(:pie) }
227
+
228
+ end
229
+
230
+ describe '#stack' do
231
+
232
+ subject { Plotrb::Transform.new(:stack) }
233
+
234
+ end
235
+
236
+ describe '#treemap' do
237
+
238
+ subject { Plotrb::Transform.new(:treemap) }
239
+
240
+ end
241
+
242
+ describe '#wordcloud' do
243
+
244
+ subject { Plotrb::Transform.new(:wordcloud) }
245
+
246
+ end
247
+
248
+ end