opal-d3 0.0.20170205

Sign up to get free protection for your applications and to get access to all the features.
Files changed (130) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/Gemfile +3 -0
  4. data/README.md +7 -0
  5. data/Rakefile +31 -0
  6. data/d3.js +16393 -0
  7. data/demo/Gemfile +4 -0
  8. data/demo/README.md +7 -0
  9. data/demo/app/data/elections_2016.rb +10 -0
  10. data/demo/app/data/harry_potter.rb +19 -0
  11. data/demo/app/data/iphones.rb +29 -0
  12. data/demo/app/data/london_population.rb +26 -0
  13. data/demo/app/data/man_vs_horse.rb +55 -0
  14. data/demo/app/data/mtg_modern_colors.rb +96 -0
  15. data/demo/app/data/mtg_modern_creatures.rb +116 -0
  16. data/demo/app/data/olympics_2016_medals.rb +100 -0
  17. data/demo/app/data/paradox.rb +60 -0
  18. data/demo/app/data/polish_pms.rb +28 -0
  19. data/demo/app/data/star_trek_voyager.rb +183 -0
  20. data/demo/app/data/weather_in_london.rb +381 -0
  21. data/demo/app/elections_2016.rb +19 -0
  22. data/demo/app/harry_potter.rb +35 -0
  23. data/demo/app/iphones.rb +47 -0
  24. data/demo/app/london_population.rb +46 -0
  25. data/demo/app/london_population_area.rb +42 -0
  26. data/demo/app/man_vs_horse.rb +53 -0
  27. data/demo/app/mtg_modern_colors.rb +49 -0
  28. data/demo/app/mtg_modern_creatures.rb +63 -0
  29. data/demo/app/olympics_2016_medals.rb +54 -0
  30. data/demo/app/paradox.rb +57 -0
  31. data/demo/app/polish_pms.rb +53 -0
  32. data/demo/app/star_trek_voyager.rb +39 -0
  33. data/demo/app/weather_in_london.rb +62 -0
  34. data/demo/assets/d3.js +16393 -0
  35. data/demo/assets/style.css +0 -0
  36. data/demo/config.ru +39 -0
  37. data/demo/views/index.erb +21 -0
  38. data/demo/views/visualization.erb +29 -0
  39. data/lib/opal/d3/arc.rb +21 -0
  40. data/lib/opal/d3/area.rb +49 -0
  41. data/lib/opal/d3/axis.rb +77 -0
  42. data/lib/opal/d3/band_scale.rb +29 -0
  43. data/lib/opal/d3/collections.rb +10 -0
  44. data/lib/opal/d3/color.rb +78 -0
  45. data/lib/opal/d3/continuous_scale.rb +64 -0
  46. data/lib/opal/d3/creator.rb +11 -0
  47. data/lib/opal/d3/curve.rb +74 -0
  48. data/lib/opal/d3/dsv.rb +103 -0
  49. data/lib/opal/d3/ease.rb +319 -0
  50. data/lib/opal/d3/format.rb +97 -0
  51. data/lib/opal/d3/histograms.rb +44 -0
  52. data/lib/opal/d3/interpolate.rb +125 -0
  53. data/lib/opal/d3/line.rb +29 -0
  54. data/lib/opal/d3/map.rb +52 -0
  55. data/lib/opal/d3/misc.rb +15 -0
  56. data/lib/opal/d3/native.rb +84 -0
  57. data/lib/opal/d3/nest.rb +100 -0
  58. data/lib/opal/d3/ordinal_scale.rb +56 -0
  59. data/lib/opal/d3/path.rb +22 -0
  60. data/lib/opal/d3/pie.rb +23 -0
  61. data/lib/opal/d3/point_scale.rb +26 -0
  62. data/lib/opal/d3/polygon.rb +16 -0
  63. data/lib/opal/d3/quadtree.rb +95 -0
  64. data/lib/opal/d3/quantile_scale.rb +21 -0
  65. data/lib/opal/d3/quantize_scale.rb +23 -0
  66. data/lib/opal/d3/radial_area.rb +49 -0
  67. data/lib/opal/d3/radial_line.rb +29 -0
  68. data/lib/opal/d3/random.rb +12 -0
  69. data/lib/opal/d3/search.rb +28 -0
  70. data/lib/opal/d3/selection.rb +149 -0
  71. data/lib/opal/d3/sequential_scale.rb +96 -0
  72. data/lib/opal/d3/set.rb +33 -0
  73. data/lib/opal/d3/stack.rb +11 -0
  74. data/lib/opal/d3/statistics.rb +81 -0
  75. data/lib/opal/d3/symbol.rb +70 -0
  76. data/lib/opal/d3/threshold_scale.rb +23 -0
  77. data/lib/opal/d3/time_format.rb +48 -0
  78. data/lib/opal/d3/time_interval.rb +81 -0
  79. data/lib/opal/d3/transformations.rb +13 -0
  80. data/lib/opal/d3/version.rb +5 -0
  81. data/lib/opal/d3.rb +62 -0
  82. data/lib/opal-d3.rb +9 -0
  83. data/opal-d3.gemspec +20 -0
  84. data/spec/arc_spec.rb +86 -0
  85. data/spec/area_spec.rb +102 -0
  86. data/spec/axis_spec.rb +174 -0
  87. data/spec/band_scale_spec.rb +73 -0
  88. data/spec/color_spec.rb +74 -0
  89. data/spec/continuous_scale_spec.rb +217 -0
  90. data/spec/coverage_spec.rb +23 -0
  91. data/spec/creator_spec.rb +15 -0
  92. data/spec/curve_spec.rb +214 -0
  93. data/spec/dsv_spec.rb +194 -0
  94. data/spec/ease_spec.rb +370 -0
  95. data/spec/format_spec.rb +87 -0
  96. data/spec/histograms_spec.rb +61 -0
  97. data/spec/html/d3.js +16393 -0
  98. data/spec/html/index.html.erb +12 -0
  99. data/spec/interpolate_spec.rb +152 -0
  100. data/spec/line_spec.rb +58 -0
  101. data/spec/map_spec.rb +80 -0
  102. data/spec/misc_spec.rb +19 -0
  103. data/spec/nest_spec.rb +89 -0
  104. data/spec/objects_spec.rb +22 -0
  105. data/spec/ordinal_scale_spec.rb +59 -0
  106. data/spec/path_spec.rb +65 -0
  107. data/spec/pie_spec.rb +114 -0
  108. data/spec/point_scale_spec.rb +58 -0
  109. data/spec/polygon_spec.rb +51 -0
  110. data/spec/quadtree_spec.rb +128 -0
  111. data/spec/quantile_scale_spec.rb +24 -0
  112. data/spec/quantize_scale_spec.rb +40 -0
  113. data/spec/radial_area_spec.rb +127 -0
  114. data/spec/radial_line_spec.rb +54 -0
  115. data/spec/random_spec.rb +34 -0
  116. data/spec/search_spec.rb +69 -0
  117. data/spec/selection_data_spec.rb +71 -0
  118. data/spec/selection_manipulation_spec.rb +179 -0
  119. data/spec/selection_spec.rb +214 -0
  120. data/spec/sequential_scale_spec.rb +90 -0
  121. data/spec/set_spec.rb +57 -0
  122. data/spec/spec_helper.rb +2 -0
  123. data/spec/stack_spec.rb +23 -0
  124. data/spec/statistics_spec.rb +65 -0
  125. data/spec/symbol_spec.rb +121 -0
  126. data/spec/threshold_scale_spec.rb +28 -0
  127. data/spec/time_format_spec.rb +99 -0
  128. data/spec/time_interval_spec.rb +304 -0
  129. data/spec/transformations_spec.rb +51 -0
  130. metadata +258 -0
@@ -0,0 +1,217 @@
1
+ require "time"
2
+
3
+ describe "d3 - continuous scale" do
4
+ describe "linear" do
5
+ it "d3.scale_linear" do
6
+ expect(D3.scale_linear).to be_instance_of(D3::ContinuousScale)
7
+ end
8
+
9
+ it "basics" do
10
+ x = D3.scale_linear.domain([10, 130]).range([0, 960])
11
+ expect(x.domain).to eq([10, 130])
12
+ expect(x.range).to eq([0, 960])
13
+ expect(x.(20)).to eq(80)
14
+ expect(x.(50)).to eq(320)
15
+ expect(x.(-10)).to eq(-160)
16
+ expect(x.invert(-160)).to eq(-10)
17
+ end
18
+
19
+ it "range_round" do
20
+ x = D3.scale_linear.domain([0,6]).range([0, 100])
21
+ y = D3.scale_linear.domain([0,6]).range_round([0, 100])
22
+ expect(x.(4)).to eq(66.66666666666666)
23
+ expect(y.(4)).to eq(67)
24
+ end
25
+
26
+ describe "interpolate" do
27
+ let(:x) { D3.scale_linear.domain([0,6]).range([0, 100]) }
28
+ let(:xf) { x.copy.interpolate{|a,b| proc{|t| (a + (b-a)*t).floor }}}
29
+ let(:xc) { x.copy.interpolate{|a,b| proc{|t| (a + (b-a)*t).ceil }}}
30
+ let(:xr) { x.copy.interpolate(&D3.interpolate_round) }
31
+ it "floor" do
32
+ expect(xf.(4)).to eq(66)
33
+ end
34
+ it "ceil" do
35
+ expect(xc.(4)).to eq(67)
36
+ end
37
+ it "round" do
38
+ expect(xr.(4)).to eq(67)
39
+ end
40
+ it "get interpolator" do
41
+ expect(x.interpolate.(0,10).(0.34)).to eq(3.4000000000000004)
42
+ expect(xr.interpolate.(0,10).(0.34)).to eq(3)
43
+ end
44
+ end
45
+
46
+ it ".clamp" do
47
+ x = D3.scale_linear.domain([10, 130]).range([0, 960])
48
+ expect(x.clamp).to eq(false)
49
+ x.clamp(true)
50
+ expect(x.clamp).to eq(true)
51
+ expect(x.(-10)).to eq(0)
52
+ expect(x.invert(-160)).to eq(10)
53
+ end
54
+
55
+ it ".nice / .copy" do
56
+ x = D3.scale_linear.domain([7, 127]).range([3, 955])
57
+ xn = x.copy.nice
58
+ expect(xn.domain).to eq([0, 130])
59
+ expect(xn.range).to eq([3, 955])
60
+
61
+ xc = x.copy
62
+ x5 = x.nice(5)
63
+ expect(x5.domain).to eq([0, 140])
64
+ expect(x5.range).to eq([3, 955])
65
+ expect(xc.domain).to eq([7, 127])
66
+ expect(xc.range).to eq([3, 955])
67
+ expect(x.domain).to eq(x5.domain)
68
+ expect(x.range).to eq(x5.range)
69
+ end
70
+
71
+ it "color" do
72
+ color = D3.scale_linear.domain([10, 100]).range(["brown", "steelblue"])
73
+ expect(color.(20)).to eq("rgb(154, 52, 57)")
74
+ expect(color.(50)).to eq("rgb(123, 81, 103)")
75
+ end
76
+
77
+ it "color piecewise" do
78
+ color = D3.scale_linear.domain([-1, 0, 1]).range(["red", "white", "green"])
79
+ expect(color.(-1)).to eq("rgb(255, 0, 0)")
80
+ expect(color.(-0.5)).to eq("rgb(255, 128, 128)")
81
+ expect(color.(0)).to eq("rgb(255, 255, 255)")
82
+ expect(color.(+0.5)).to eq("rgb(128, 192, 128)")
83
+ expect(color.(1)).to eq("rgb(0, 128, 0)")
84
+ end
85
+
86
+ it ".ticks / .tick_format" do
87
+ x = D3.scale_linear.domain([-1, 1]).range([0, 960])
88
+ expect(x.ticks(5)).to eq([-1, -0.5, 0, 0.5, 1])
89
+ expect(x.ticks.map{|v| v.round(2)}).to eq([-1, -0.8, -0.6, -0.4, -0.2, 0, 0.2, 0.4, 0.6, 0.8, 1])
90
+ tick_format = x.tick_format(5, "+%")
91
+ expect(x.ticks(5).map(&tick_format)).to eq(["-100%", "-50%", "+0%", "+50%", "+100%"])
92
+ end
93
+ end
94
+
95
+ describe "pow" do
96
+ it "d3.scale_pow" do
97
+ expect(D3.scale_pow).to be_instance_of(D3::PowScale)
98
+ expect(D3.scale_pow.exponent).to eq(1)
99
+ end
100
+
101
+ it "basics" do
102
+ x = D3.scale_pow.exponent(2).domain([0, 10]).range([0, 10000])
103
+ expect(x.(5)).to eq(2500)
104
+ expect(x.invert(4900)).to eq(7)
105
+ end
106
+ end
107
+
108
+ describe "sqrt" do
109
+ it "d3.scale_sqrt" do
110
+ expect(D3.scale_sqrt).to be_instance_of(D3::PowScale)
111
+ expect(D3.scale_sqrt.exponent).to eq(0.5)
112
+ end
113
+ end
114
+
115
+ describe "log" do
116
+ it 'd3.scale_log' do
117
+ expect(D3.scale_log).to be_instance_of(D3::LogScale)
118
+ expect(D3.scale_log.base).to eq(10)
119
+ end
120
+
121
+ it "basics" do
122
+ x = D3.scale_log.base(2).domain([1, 1024]).range([0, 100])
123
+ expect(x.(256)).to eq(80)
124
+ expect(x.invert(50)).to eq(32)
125
+ end
126
+ end
127
+
128
+ describe "identity" do
129
+ it 'd3.scale_log' do
130
+ expect(D3.scale_identity).to be_instance_of(D3::ContinuousScale)
131
+ end
132
+
133
+ it "basics" do
134
+ x = D3.scale_identity.domain([10,20])
135
+ expect(x.(16)).to eq(16)
136
+ expect(x.invert(12)).to eq(12)
137
+ expect(x.domain).to eq([10,20])
138
+ expect(x.range).to eq([10,20])
139
+ end
140
+ end
141
+
142
+ # Sadly this can't be tested totally properly due to ridiculous mess
143
+ # javascript timezone management is
144
+ describe "time" do
145
+ let(:x) { D3.scale_time.domain([Time.parse("Jan 01 1990 00:00:00"), Time.parse(Time.parse("Jan 01 1998 00:00:00"))]).range([0,100]) }
146
+ let(:y) { D3.scale_utc.domain([Time.parse("Jan 01 1990 00:00:00"), Time.parse(Time.parse("Jan 01 1998 00:00:00"))]).range([0,100]) }
147
+ it "d3.scale_time" do
148
+ expect(D3.scale_time).to be_instance_of(D3::ContinuousScale)
149
+ end
150
+
151
+ it "d3.scale_utc" do
152
+ expect(D3.scale_utc).to be_instance_of(D3::ContinuousScale)
153
+ end
154
+
155
+ it "basics" do
156
+ expect(x.(Time.parse("Jul 01 1995 00:00:00")).round(1)).to eq(68.7)
157
+ end
158
+
159
+ it "invert" do
160
+ expect(x.invert(75).to_s).to eq("1996-01-01 12:00:00 -0000")
161
+ end
162
+
163
+ it "ticks" do
164
+ expect(x.ticks(4).map(&:to_s)).to eq([
165
+ "1990-01-01 00:00:00 -0000",
166
+ "1992-01-01 00:00:00 -0000",
167
+ "1994-01-01 00:00:00 -0000",
168
+ "1996-01-01 00:00:00 -0000",
169
+ "1998-01-01 00:00:00 -0000",
170
+ ])
171
+ end
172
+
173
+ it "ticks interval" do
174
+ expect(x.ticks(D3.time_month.every(8)).map{|d| d.to_s.split[0]}).to eq([
175
+ "1990-01-01",
176
+ "1990-09-01",
177
+ "1991-01-01",
178
+ "1991-09-01",
179
+ "1992-01-01",
180
+ "1992-09-01",
181
+ "1993-01-01",
182
+ "1993-09-01",
183
+ "1994-01-01",
184
+ "1994-09-01",
185
+ "1995-01-01",
186
+ "1995-09-01",
187
+ "1996-01-01",
188
+ "1996-09-01",
189
+ "1997-01-01",
190
+ "1997-09-01",
191
+ "1998-01-01",
192
+ ])
193
+ end
194
+
195
+ it "utc ticks interval" do
196
+ expect(y.ticks(D3.utc_month.every(8)).map{|d| d.to_s.split[0]}).to eq([
197
+ "1990-01-01",
198
+ "1990-09-01",
199
+ "1991-01-01",
200
+ "1991-09-01",
201
+ "1992-01-01",
202
+ "1992-09-01",
203
+ "1993-01-01",
204
+ "1993-09-01",
205
+ "1994-01-01",
206
+ "1994-09-01",
207
+ "1995-01-01",
208
+ "1995-09-01",
209
+ "1996-01-01",
210
+ "1996-09-01",
211
+ "1997-01-01",
212
+ "1997-09-01",
213
+ "1998-01-01",
214
+ ])
215
+ end
216
+ end
217
+ end
@@ -0,0 +1,23 @@
1
+ describe "D3 coverage" do
2
+ # Test code is here because opal-repl doesn't support aggregate_failures mode
3
+ native_methods = `Opal.hash(window.d3)`.keys.sort
4
+ nice_methods = native_methods.map{|m| m.gsub(/([a-z])(?=[A-Z0-9])/, "\\1_").downcase }
5
+
6
+ it "everything is covered" do
7
+ working_methods = nice_methods.select{|m| D3.respond_to?(m) }
8
+ expect(working_methods.size).to eq(nice_methods.size)
9
+ end
10
+
11
+ # DETAILED
12
+ # format conflict with base ruby
13
+
14
+ # nice_methods.each do |method|
15
+ # it method do
16
+ # if D3.respond_to?(method)
17
+ # # OK
18
+ # else
19
+ # skip "not implemented yet"
20
+ # end
21
+ # end
22
+ # end
23
+ end
@@ -0,0 +1,15 @@
1
+ describe "d3 - creator" do
2
+ after(:each) do
3
+ D3.select("#test-area").html("")
4
+ end
5
+ let(:root) { D3.select("#test-area") }
6
+ let(:html) { root.html }
7
+
8
+ it "d3.creator" do
9
+ expect(D3.creator("div")).to be_instance_of(D3::Creator)
10
+ D3.select("div").append(D3.creator("span"))
11
+ expect(html).to eq(
12
+ "<span></span>"
13
+ )
14
+ end
15
+ end
@@ -0,0 +1,214 @@
1
+ describe "d3 - curve" do
2
+ let(:curve) { D3.send(name) }
3
+ # 5 x-x
4
+ # / \
5
+ # 4 x | x
6
+ # \ /
7
+ # 3 x
8
+ # 0 1 2 3 4
9
+ let(:data) { [[0, 4], [1, 5], [2, 5], [3, 3], [4, 4]] }
10
+ let(:line) { D3.line.curve(curve).(data) }
11
+ let(:rounded) { line.gsub(/\d+\.\d+/){$&.to_f.round(2)} }
12
+ describe "curve_basis" do
13
+ let(:name){ :curve_basis }
14
+ it do
15
+ expect(curve).to be_instance_of(D3::Curve)
16
+ expect(rounded).to eq("M0,4L0.17,4.17C0.33,4.33,0.67,4.67,1,4.83C1.33,5,1.67,5,2,4.67C2.33,4.33,2.67,3.67,3,3.5C3.33,3.33,3.67,3.67,3.83,3.83L4,4")
17
+ end
18
+ end
19
+
20
+ describe "curve_basis_closed" do
21
+ let(:name){ :curve_basis_closed }
22
+ it do
23
+ expect(curve).to be_instance_of(D3::Curve)
24
+ expect(rounded).to eq("M1,4.83C1.33,5,1.67,5,2,4.67C2.33,4.33,2.67,3.67,3,3.5C3.33,3.33,3.67,3.67,3.17,3.83C2.67,4,1.33,4,0.83,4.17C0.33,4.33,0.67,4.67,1,4.83")
25
+ end
26
+ end
27
+
28
+ describe "curve_basis_open" do
29
+ let(:name){ :curve_basis_open }
30
+ it do
31
+ expect(curve).to be_instance_of(D3::Curve)
32
+ expect(rounded).to eq("M1,4.83C1.33,5,1.67,5,2,4.67C2.33,4.33,2.67,3.67,3,3.5")
33
+ end
34
+ end
35
+
36
+ describe "curve_bundle" do
37
+ let(:name){ :curve_bundle }
38
+ it do
39
+ expect(curve).to be_instance_of(D3::CurveBundle)
40
+ expect(rounded).to eq("M0,4L0.17,4.14C0.33,4.28,0.67,4.57,1,4.71C1.33,4.85,1.67,4.85,2,4.57C2.33,4.28,2.67,3.72,3,3.58C3.33,3.43,3.67,3.72,3.83,3.86L4,4")
41
+ end
42
+
43
+ describe ".beta" do
44
+ let(:curve) { D3.curve_bundle.beta(0.5) }
45
+ it do
46
+ expect(curve).to be_instance_of(D3::CurveBundle)
47
+ expect(rounded).to eq("M0,4L0.17,4.08C0.33,4.17,0.67,4.33,1,4.42C1.33,4.5,1.67,4.5,2,4.33C2.33,4.17,2.67,3.83,3,3.75C3.33,3.67,3.67,3.83,3.83,3.92L4,4")
48
+ end
49
+ end
50
+ end
51
+
52
+ describe "curve_cardinal" do
53
+ let(:name){ :curve_cardinal }
54
+ it do
55
+ expect(curve).to be_instance_of(D3::CurveCardinal)
56
+ expect(rounded).to eq("M0,4C0,4,0.67,4.83,1,5C1.33,5.17,1.67,5.33,2,5C2.33,4.67,2.67,3.17,3,3C3.33,2.83,4,4,4,4")
57
+ end
58
+ describe ".tension" do
59
+ let(:curve) { D3.curve_cardinal.tension(0.5) }
60
+ it do
61
+ expect(curve).to be_instance_of(D3::CurveCardinal)
62
+ expect(rounded).to eq("M0,4C0,4,0.83,4.92,1,5C1.17,5.08,1.83,5.17,2,5C2.17,4.83,2.83,3.08,3,3C3.17,2.92,4,4,4,4")
63
+ end
64
+ end
65
+ end
66
+
67
+ describe "curve_cardinal_closed" do
68
+ let(:name){ :curve_cardinal_closed }
69
+ it do
70
+ expect(curve).to be_instance_of(D3::CurveCardinal)
71
+ expect(rounded).to eq("M1,5C1.33,5.17,1.67,5.33,2,5C2.33,4.67,2.67,3.17,3,3C3.33,2.83,4.5,3.83,4,4C3.5,4.17,0.5,3.83,0,4C-0.5,4.17,0.67,4.83,1,5")
72
+ end
73
+ describe ".tension" do
74
+ let(:curve) { D3.curve_cardinal_closed.tension(0.5) }
75
+ it do
76
+ expect(curve).to be_instance_of(D3::CurveCardinal)
77
+ expect(rounded).to eq("M1,5C1.17,5.08,1.83,5.17,2,5C2.17,4.83,2.83,3.08,3,3C3.17,2.92,4.25,3.92,4,4C3.75,4.08,0.25,3.92,0,4C-0.25,4.08,0.83,4.92,1,5")
78
+ end
79
+ end
80
+ end
81
+
82
+ describe "curve_cardinal_open" do
83
+ let(:name){ :curve_cardinal_open }
84
+ it do
85
+ expect(curve).to be_instance_of(D3::CurveCardinal)
86
+ expect(rounded).to eq("M1,5C1.33,5.17,1.67,5.33,2,5C2.33,4.67,2.67,3.17,3,3")
87
+ end
88
+ describe ".tension" do
89
+ let(:curve) { D3.curve_cardinal_open.tension(0.5) }
90
+ it do
91
+ expect(curve).to be_instance_of(D3::CurveCardinal)
92
+ expect(rounded).to eq("M1,5C1.17,5.08,1.83,5.17,2,5C2.17,4.83,2.83,3.08,3,3")
93
+ end
94
+ end
95
+ end
96
+
97
+ describe "curve_catmull_rom" do
98
+ let(:name){ :curve_catmull_rom }
99
+ it do
100
+ expect(curve).to be_instance_of(D3::CurveCatmullRom)
101
+ expect(rounded).to eq("M0,4C0,4,0.63,4.85,1,5C1.31,5.13,1.71,5.18,2,5C2.43,4.73,2.62,3.06,3,3C3.3,2.95,4,4,4,4")
102
+ end
103
+ describe ".alpha" do
104
+ let(:curve) { D3.curve_catmull_rom.alpha(0.75) }
105
+ it do
106
+ expect(curve).to be_instance_of(D3::CurveCatmullRom)
107
+ expect(rounded).to eq("M0,4C0,4,0.61,4.85,1,5C1.3,5.11,1.72,5.13,2,5C2.51,4.76,2.59,3,3,3C3.29,3,4,4,4,4")
108
+ end
109
+ end
110
+ end
111
+
112
+ describe "curve_catmull_rom_closed" do
113
+ let(:name){ :curve_catmull_rom_closed }
114
+ it do
115
+ expect(curve).to be_instance_of(D3::CurveCatmullRom)
116
+ expect(rounded).to eq("M1,5C1.31,5.13,1.71,5.18,2,5C2.43,4.73,2.62,3.06,3,3C3.3,2.95,4.09,3.79,4,4C3.85,4.35,0.15,3.65,0,4C-0.09,4.21,0.63,4.85,1,5")
117
+ end
118
+ describe ".alpha" do
119
+ let(:curve) { D3.curve_catmull_rom_closed.alpha(0.75) }
120
+ it do
121
+ expect(curve).to be_instance_of(D3::CurveCatmullRom)
122
+ expect(rounded).to eq("M1,5C1.3,5.11,1.72,5.13,2,5C2.51,4.76,2.59,3,3,3C3.29,3,3.96,3.77,4,4C4.08,4.5,-0.08,3.5,0,4C0.04,4.23,0.61,4.85,1,5")
123
+ end
124
+ end
125
+ end
126
+
127
+ describe "curve_catmull_rom_open" do
128
+ let(:name){ :curve_catmull_rom_open }
129
+ it do
130
+ expect(curve).to be_instance_of(D3::CurveCatmullRom)
131
+ expect(rounded).to eq("M1,5C1.31,5.13,1.71,5.18,2,5C2.43,4.73,2.62,3.06,3,3")
132
+ end
133
+ describe ".alpha" do
134
+ let(:curve) { D3.curve_catmull_rom_open.alpha(0.75) }
135
+ it do
136
+ expect(curve).to be_instance_of(D3::CurveCatmullRom)
137
+ expect(rounded).to eq("M1,5C1.3,5.11,1.72,5.13,2,5C2.51,4.76,2.59,3,3,3")
138
+ end
139
+ end
140
+ end
141
+
142
+ describe "curve_linear" do
143
+ let(:name){ :curve_linear }
144
+ it do
145
+ expect(curve).to be_instance_of(D3::Curve)
146
+ expect(rounded).to eq("M0,4L1,5L2,5L3,3L4,4")
147
+ end
148
+ end
149
+
150
+ describe "curve_linear_closed" do
151
+ let(:name){ :curve_linear_closed }
152
+ it do
153
+ expect(curve).to be_instance_of(D3::Curve)
154
+ expect(rounded).to eq("M0,4L1,5L2,5L3,3L4,4Z")
155
+ end
156
+ end
157
+
158
+ describe "curve_monotone_x" do
159
+ let(:name){ :curve_monotone_x }
160
+ it do
161
+ expect(curve).to be_instance_of(D3::Curve)
162
+ expect(rounded).to eq("M0,4C0.33,4.5,0.67,5,1,5C1.33,5,1.67,5,2,5C2.33,5,2.67,3,3,3C3.33,3,3.67,3.5,4,4")
163
+ end
164
+ end
165
+
166
+ describe "curve_monotone_y" do
167
+ let(:name){ :curve_monotone_y }
168
+ it do
169
+ expect(curve).to be_instance_of(D3::Curve)
170
+ expect(rounded).to eq("M0,4C0.17,4.33,0.33,4.67,1,5C1,5,2,5,2,5C2.67,4.33,3,3.67,3,3C3,3.33,3.5,3.67,4,4")
171
+ end
172
+ end
173
+
174
+ describe "curve_natural" do
175
+ let(:name){ :curve_natural }
176
+ it do
177
+ expect(curve).to be_instance_of(D3::Curve)
178
+ expect(rounded).to eq("M0,4C0.33,4.36,0.67,4.71,1,5C1.33,5.29,1.67,5.5,2,5C2.33,4.5,2.67,3.29,3,3C3.33,2.71,3.67,3.36,4,4")
179
+ end
180
+ end
181
+
182
+ describe "curve_step" do
183
+ let(:name){ :curve_step }
184
+ it do
185
+ expect(curve).to be_instance_of(D3::Curve)
186
+ expect(rounded).to eq("M0,4L0.5,4L0.5,5L1.5,5L1.5,5L2.5,5L2.5,3L3.5,3L3.5,4L4,4")
187
+ end
188
+ end
189
+
190
+ describe "curve_step_after" do
191
+ let(:name){ :curve_step_after }
192
+ it do
193
+ expect(curve).to be_instance_of(D3::Curve)
194
+ expect(rounded).to eq("M0,4L1,4L1,5L2,5L2,5L3,5L3,3L4,3L4,4")
195
+ end
196
+ end
197
+
198
+ describe "curve_step_before" do
199
+ let(:name){ :curve_step_before }
200
+ it do
201
+ expect(curve).to be_instance_of(D3::Curve)
202
+ expect(rounded).to eq("M0,4L0,5L1,5L1,5L2,5L2,3L3,3L3,4L4,4")
203
+ end
204
+ end
205
+
206
+ end
207
+
208
+ __END__
209
+
210
+ curve.areaStart - start a new area segment.
211
+ curve.areaEnd - end the current area segment.
212
+ curve.lineStart - start a new line segment.
213
+ curve.lineEnd - end the current line segment.
214
+ curve.point - add a point to the current line segment.
data/spec/dsv_spec.rb ADDED
@@ -0,0 +1,194 @@
1
+ describe "d3 - dsv" do
2
+ let(:csv_example) do
3
+ "Year,Make,Model,Length\n"+
4
+ "1997,Ford,E350,2.34\n"+
5
+ "2000,Mercury,Cougar,2.38\n"
6
+ end
7
+ let(:tsv_example) do
8
+ "Year\tMake\tModel\tLength\n"+
9
+ "1997\tFord\tE350\t2.34\n"+
10
+ "2000\tMercury\tCougar\t2.38\n"
11
+ end
12
+ let(:dsv_example) do
13
+ "Year;Make;Model;Length\n"+
14
+ "1997;Ford;E350;2.34\n"+
15
+ "2000;Mercury;Cougar;2.38\n"
16
+ end
17
+ let(:rows_example) {
18
+ [
19
+ ["Year", "Make", "Model", "Length"],
20
+ ["1997", "Ford", "E350", "2.34"],
21
+ ["2000", "Mercury", "Cougar", "2.38"],
22
+ ]
23
+ }
24
+ let(:objs_example) {
25
+ [
26
+ {"Year"=>"1997", "Make"=>"Ford", "Model"=>"E350", "Length"=>"2.34"},
27
+ {"Year"=>"2000", "Make"=>"Mercury", "Model"=>"Cougar", "Length"=>"2.38"},
28
+ ]
29
+ }
30
+ let(:csv_format) { D3.dsv_format(",") }
31
+ let(:tsv_format) { D3.dsv_format("\t") }
32
+ let(:dsv_format) { D3.dsv_format(";") }
33
+ let(:format_row) { proc{|(y,f,m,l)|
34
+ ["converted", (Integer(y) rescue y), f, m, (Float(l) rescue l)]
35
+ }}
36
+ let(:filter_row) { proc{|d|
37
+ format_row.(d) if d[0] == "2000" or d[0] == "1997"
38
+ }}
39
+ let(:format_obj) { proc{|o|
40
+ {y: o["Year"].to_i, f:o["Make"], m:o["Model"], l:o["Length"].to_f}
41
+ }}
42
+ let(:filter_obj) { proc{|o|
43
+ format_obj.(o) if o["Year"] == "2000"
44
+ }}
45
+
46
+ it "d3.dsv_format" do
47
+ expect(D3.dsv_format(";")).to be_instance_of(D3::DsvFormat)
48
+ end
49
+
50
+ it "dsv_format.parse_rows" do
51
+ expect(dsv_format.parse_rows(dsv_example)).to eq(rows_example)
52
+ expect(dsv_format.parse_rows(dsv_example, format_row)).to eq(
53
+ dsv_format.parse_rows(dsv_example, &format_row)
54
+ )
55
+ expect(dsv_format.parse_rows(dsv_example, format_row)).to eq([
56
+ ["converted", "Year", "Make", "Model", "Length"],
57
+ ["converted", 1997, "Ford", "E350", 2.34],
58
+ ["converted", 2000, "Mercury", "Cougar", 2.38],
59
+ ])
60
+ expect(dsv_format.parse_rows(dsv_example, filter_row)).to eq([
61
+ ["converted", 1997, "Ford", "E350", 2.34],
62
+ ["converted", 2000, "Mercury", "Cougar", 2.38],
63
+ ])
64
+ end
65
+
66
+ it "d3.csv_parse_rows" do
67
+ expect(D3.csv_parse_rows(csv_example)).to eq(
68
+ csv_format.parse_rows(csv_example))
69
+ expect(dsv_format.parse_rows(dsv_example)).to eq(
70
+ csv_format.parse_rows(csv_example))
71
+ expect(D3.csv_parse_rows(csv_example, format_row)).to eq(
72
+ csv_format.parse_rows(csv_example, format_row))
73
+ expect(D3.csv_parse_rows(csv_example, &format_row)).to eq(
74
+ csv_format.parse_rows(csv_example, &format_row))
75
+ expect(D3.csv_parse_rows(csv_example, filter_row)).to eq(
76
+ csv_format.parse_rows(csv_example, filter_row))
77
+ expect(D3.csv_parse_rows(csv_example, &filter_row)).to eq(
78
+ csv_format.parse_rows(csv_example, &filter_row))
79
+ end
80
+
81
+ it "d3.tsv_parse_rows" do
82
+ expect(D3.tsv_parse_rows(tsv_example)).to eq(
83
+ tsv_format.parse_rows(tsv_example))
84
+ expect(dsv_format.parse_rows(dsv_example)).to eq(
85
+ tsv_format.parse_rows(tsv_example))
86
+ expect(D3.tsv_parse_rows(tsv_example, format_row)).to eq(
87
+ tsv_format.parse_rows(tsv_example, format_row))
88
+ expect(D3.tsv_parse_rows(tsv_example, &format_row)).to eq(
89
+ tsv_format.parse_rows(tsv_example, &format_row))
90
+ expect(D3.tsv_parse_rows(tsv_example, filter_row)).to eq(
91
+ tsv_format.parse_rows(tsv_example, filter_row))
92
+ expect(D3.tsv_parse_rows(tsv_example, &filter_row)).to eq(
93
+ tsv_format.parse_rows(tsv_example, &filter_row))
94
+ end
95
+
96
+ # It's awful practice not to include final \n,
97
+ # but it's not our place to workaround D3's bugs here
98
+ it "dsv_format.format_rows" do
99
+ expect(dsv_format.format_rows(rows_example)).to eq(dsv_example.chomp)
100
+ end
101
+
102
+ it "d3.csv_format_rows" do
103
+ expect(csv_format.format_rows(rows_example)).to eq(csv_example.chomp)
104
+ expect(D3.csv_format_rows(rows_example)).to eq(csv_example.chomp)
105
+ end
106
+
107
+ it "d3.tsv_format_rows" do
108
+ expect(tsv_format.format_rows(rows_example)).to eq(tsv_example.chomp)
109
+ expect(D3.tsv_format_rows(rows_example)).to eq(tsv_example.chomp)
110
+ end
111
+
112
+ # We have ways to enforce proper Hash order, maybe it's a good idea
113
+ it "dsv_format.parse" do
114
+ expect(dsv_format.parse(dsv_example)).to eq(objs_example)
115
+ expect(dsv_format.parse(dsv_example, format_obj)).to eq(
116
+ dsv_format.parse(dsv_example, &format_obj))
117
+ expect(dsv_format.parse(dsv_example, &format_obj)).to eq([
118
+ {"y"=>1997, "f"=>"Ford", "m"=>"E350", "l"=>2.34},
119
+ {"y"=>2000, "f"=>"Mercury", "m"=>"Cougar", "l"=>2.38},
120
+ ])
121
+ end
122
+
123
+ it "dsv_format.parse - filtering" do
124
+ expect(dsv_format.parse(dsv_example, &filter_obj)).to eq(
125
+ dsv_format.parse(dsv_example, filter_obj))
126
+ expect(dsv_format.parse(dsv_example, &filter_obj)).to eq([
127
+ {"y"=>2000, "f"=>"Mercury", "m"=>"Cougar", "l"=>2.38},
128
+ ])
129
+ end
130
+
131
+ it "d3.csv_parse" do
132
+ expect(D3.csv_parse(csv_example)).to eq(
133
+ csv_format.parse(csv_example))
134
+ expect(dsv_format.parse(dsv_example)).to eq(
135
+ csv_format.parse(csv_example))
136
+ expect(D3.csv_parse(csv_example, format_obj)).to eq(
137
+ csv_format.parse(csv_example, format_obj))
138
+ expect(D3.csv_parse(csv_example, &format_obj)).to eq(
139
+ csv_format.parse(csv_example, &format_obj))
140
+ expect(D3.csv_parse(csv_example, filter_obj)).to eq(
141
+ csv_format.parse(csv_example, filter_obj))
142
+ expect(D3.csv_parse(csv_example, &filter_obj)).to eq(
143
+ csv_format.parse(csv_example, &filter_obj))
144
+ end
145
+
146
+ it "d3.tsv_parse" do
147
+ expect(D3.tsv_parse(tsv_example)).to eq(
148
+ tsv_format.parse(tsv_example))
149
+ expect(dsv_format.parse(dsv_example)).to eq(
150
+ tsv_format.parse(tsv_example))
151
+ expect(D3.tsv_parse(tsv_example, format_obj)).to eq(
152
+ tsv_format.parse(tsv_example, format_obj))
153
+ expect(D3.tsv_parse(tsv_example, &format_obj)).to eq(
154
+ tsv_format.parse(tsv_example, &format_obj))
155
+ expect(D3.tsv_parse(tsv_example, filter_obj)).to eq(
156
+ tsv_format.parse(tsv_example, filter_obj))
157
+ expect(D3.tsv_parse(tsv_example, &filter_obj)).to eq(
158
+ tsv_format.parse(tsv_example, &filter_obj))
159
+ end
160
+
161
+ # Same awful idea of not including final \n
162
+ it "dsv_format.format" do
163
+ expect(dsv_format.format(objs_example)).to eq(dsv_example.chomp)
164
+ expect(dsv_format.format(objs_example, ["Year", "Make", "Speed"])).to eq(
165
+ "Year;Make;Speed\n"+
166
+ "1997;Ford;\n"+
167
+ "2000;Mercury;"
168
+ )
169
+ end
170
+
171
+ it "d3.tsv_format" do
172
+ expect(tsv_format.format(objs_example, ["Year", "Make", "Speed"])).to eq(
173
+ "Year\tMake\tSpeed\n"+
174
+ "1997\tFord\t\n"+
175
+ "2000\tMercury\t"
176
+ )
177
+ expect(tsv_format.format(objs_example)).to eq(
178
+ D3.tsv_format(objs_example))
179
+ expect(tsv_format.format(objs_example, ["Year", "Make", "Speed"])).to eq(
180
+ D3.tsv_format(objs_example, ["Year", "Make", "Speed"]))
181
+ end
182
+
183
+ it "d3.csv_format" do
184
+ expect(csv_format.format(objs_example, ["Year", "Make", "Speed"])).to eq(
185
+ "Year,Make,Speed\n"+
186
+ "1997,Ford,\n"+
187
+ "2000,Mercury,"
188
+ )
189
+ expect(csv_format.format(objs_example)).to eq(
190
+ D3.csv_format(objs_example))
191
+ expect(csv_format.format(objs_example, ["Year", "Make", "Speed"])).to eq(
192
+ D3.csv_format(objs_example, ["Year", "Make", "Speed"]))
193
+ end
194
+ end