plotrb 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.
@@ -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