|
1 require("../env"); |
|
2 require("../../d3"); |
|
3 |
|
4 var vows = require("vows"), |
|
5 assert = require("assert"); |
|
6 |
|
7 var suite = vows.describe("d3.svg.axis"); |
|
8 |
|
9 suite.addBatch({ |
|
10 "axis": { |
|
11 topic: function() { |
|
12 return d3.svg.axis; |
|
13 }, |
|
14 |
|
15 "scale": { |
|
16 "defaults to a linear scale": function(axis) { |
|
17 var a = axis(), x = a.scale(); |
|
18 assert.deepEqual(x.domain(), [0, 1]); |
|
19 assert.deepEqual(x.range(), [0, 1]); |
|
20 assert.equal(x(0.5), 0.5); |
|
21 }, |
|
22 "can be defined as a scale object": function(axis) { |
|
23 var x = d3.scale.linear(), a = axis().scale(x); |
|
24 assert.equal(a.scale(), x); |
|
25 }, |
|
26 "can be a polylinear scale": function(axis) { |
|
27 var a = axis().scale(d3.scale.linear().domain([0, 1, 10]).range([2, 20, 200])), |
|
28 g = d3.select("body").html("").append("svg:g").call(a), |
|
29 path = g.selectAll("path"); |
|
30 assert.equal(path.attr("d"), "M2,6V0H200V6"); |
|
31 } |
|
32 }, |
|
33 |
|
34 "orient": { |
|
35 "defaults to bottom": function(axis) { |
|
36 var a = axis(); |
|
37 assert.equal(a.orient(), "bottom"); |
|
38 }, |
|
39 "supports top orientation": function(axis) { |
|
40 var a = axis().orient("top"), |
|
41 g = d3.select("body").html("").append("svg:g").call(a), |
|
42 tick = g.select("g:nth-child(3)"), |
|
43 text = tick.select("text"), |
|
44 line = tick.select("line"), |
|
45 path = g.select("path.domain"); |
|
46 assert.equal(tick.attr("transform"), "translate(0.2,0)"); |
|
47 assert.equal(text.attr("y"), -9) |
|
48 assert.equal(text.attr("dy"), "0em"); |
|
49 assert.equal(text.attr("text-anchor"), "middle"); |
|
50 assert.equal(text.text(), "0.2"); |
|
51 assert.equal(line.attr("y2"), -6); |
|
52 assert.equal(path.attr("d"), "M0,-6V0H1V-6"); |
|
53 }, |
|
54 "supports right orientation": function(axis) { |
|
55 var a = axis().orient("right"), |
|
56 g = d3.select("body").html("").append("svg:g").call(a), |
|
57 tick = g.select("g:nth-child(3)"), |
|
58 text = tick.select("text"), |
|
59 line = tick.select("line"), |
|
60 path = g.select("path.domain"); |
|
61 assert.equal(tick.attr("transform"), "translate(0,0.2)"); |
|
62 assert.equal(text.attr("x"), 9) |
|
63 assert.equal(text.attr("dy"), ".32em"); |
|
64 assert.equal(text.attr("text-anchor"), "start"); |
|
65 assert.equal(text.text(), "0.2"); |
|
66 assert.equal(line.attr("x2"), 6); |
|
67 assert.equal(path.attr("d"), "M6,0H0V1H6"); |
|
68 }, |
|
69 "supports bottom orientation": function(axis) { |
|
70 var a = axis().orient("bottom"), |
|
71 g = d3.select("body").html("").append("svg:g").call(a), |
|
72 tick = g.select("g:nth-child(3)"), |
|
73 text = tick.select("text"), |
|
74 line = tick.select("line"), |
|
75 path = g.select("path.domain"); |
|
76 assert.equal(tick.attr("transform"), "translate(0.2,0)"); |
|
77 assert.equal(text.attr("y"), 9) |
|
78 assert.equal(text.attr("dy"), ".71em"); |
|
79 assert.equal(text.attr("text-anchor"), "middle"); |
|
80 assert.equal(text.text(), "0.2"); |
|
81 assert.equal(line.attr("y2"), 6); |
|
82 assert.equal(path.attr("d"), "M0,6V0H1V6"); |
|
83 }, |
|
84 "supports left orientation": function(axis) { |
|
85 var a = axis().orient("left"), |
|
86 g = d3.select("body").html("").append("svg:g").call(a), |
|
87 tick = g.select("g:nth-child(3)"), |
|
88 text = tick.select("text"), |
|
89 line = tick.select("line"), |
|
90 path = g.select("path.domain"); |
|
91 assert.equal(tick.attr("transform"), "translate(0,0.2)"); |
|
92 assert.equal(text.attr("x"), -9) |
|
93 assert.equal(text.attr("dy"), ".32em"); |
|
94 assert.equal(text.attr("text-anchor"), "end"); |
|
95 assert.equal(text.text(), "0.2"); |
|
96 assert.equal(line.attr("x2"), -6); |
|
97 assert.equal(path.attr("d"), "M-6,0H0V1H-6"); |
|
98 } |
|
99 }, |
|
100 |
|
101 "tickSize": { |
|
102 "defaults to six pixels": function(axis) { |
|
103 var a = axis(); |
|
104 assert.equal(a.tickSize(), 6); |
|
105 }, |
|
106 "can be defined as a number": function(axis) { |
|
107 var a = axis().tickSize(3); |
|
108 assert.equal(a.tickSize(), 3); |
|
109 }, |
|
110 "coerces input value to a number": function(axis) { |
|
111 var a = axis().tickSize("3"); |
|
112 assert.strictEqual(a.tickSize(), 3); |
|
113 }, |
|
114 "affects the generated domain path": function(axis) { |
|
115 var a = axis().tickSize(3), |
|
116 g = d3.select("body").html("").append("svg:g").call(a), |
|
117 path = g.select("path.domain"); |
|
118 assert.equal(path.attr("d"), "M0,3V0H1V3"); |
|
119 }, |
|
120 "affects the generated tick lines": function(axis) { |
|
121 var a = axis().tickSize(3), |
|
122 g = d3.select("body").html("").append("svg:g").call(a), |
|
123 line = g.selectAll("g line"); |
|
124 line.each(function() { |
|
125 assert.equal(d3.select(this).attr("y2"), 3); |
|
126 }); |
|
127 }, |
|
128 "if negative, labels are placed on the opposite end": function(axis) { |
|
129 var a = axis().tickSize(-80), |
|
130 g = d3.select("body").html("").append("svg:g").call(a), |
|
131 line = g.selectAll("g line"), |
|
132 text = g.selectAll("g text"); |
|
133 line.each(function() { |
|
134 assert.equal(d3.select(this).attr("y2"), -80); |
|
135 }); |
|
136 text.each(function() { |
|
137 assert.equal(d3.select(this).attr("y"), 3); |
|
138 }); |
|
139 }, |
|
140 "with two arguments, specifies end tick size": function(axis) { |
|
141 var a = axis().tickSize(6, 3), |
|
142 g = d3.select("body").html("").append("svg:g").call(a), |
|
143 path = g.selectAll("path"); |
|
144 assert.equal(path.attr("d"), "M0,3V0H1V3"); |
|
145 }, |
|
146 "with three arguments, specifies end and minor tick sizes": function(axis) { |
|
147 var a = axis().tickSubdivide(3).tickSize(6, 3, 9), |
|
148 g = d3.select("body").html("").append("svg:g").call(a), |
|
149 path = g.selectAll("path"), |
|
150 line = g.select(".minor"); |
|
151 assert.equal(path.attr("d"), "M0,9V0H1V9"); |
|
152 assert.equal(line.attr("y2"), "3"); |
|
153 } |
|
154 }, |
|
155 |
|
156 "tickPadding": { |
|
157 "defaults to three pixels": function(axis) { |
|
158 var a = axis(); |
|
159 assert.equal(a.tickPadding(), 3); |
|
160 }, |
|
161 "can be defined as a number": function(axis) { |
|
162 var a = axis().tickPadding(6); |
|
163 assert.equal(a.tickPadding(), 6); |
|
164 }, |
|
165 "coerces input value to a number": function(axis) { |
|
166 var a = axis().tickPadding("6"); |
|
167 assert.strictEqual(a.tickPadding(), 6); |
|
168 }, |
|
169 "affects the generated tick labels": function(axis) { |
|
170 var a = axis().tickSize(2).tickPadding(7), |
|
171 g = d3.select("body").html("").append("svg:g").call(a), |
|
172 text = g.selectAll("g text"); |
|
173 text.each(function() { |
|
174 assert.equal(d3.select(this).attr("y"), 9); |
|
175 }); |
|
176 } |
|
177 }, |
|
178 |
|
179 "ticks": { |
|
180 "defaults to 10": function(axis) { |
|
181 var a = axis(); |
|
182 assert.deepEqual(a.ticks(), [10]); |
|
183 }, |
|
184 "can be defined as any arguments": function(axis) { |
|
185 var b = {}, a = axis().ticks(b, 42), t = a.ticks(); |
|
186 assert.equal(t[0], b); |
|
187 assert.equal(t[1], 42); |
|
188 assert.equal(t.length, 2); |
|
189 }, |
|
190 "passes any arguments to the scale's ticks function": function(axis) { |
|
191 var x = d3.scale.linear(), b = {}, a = axis().ticks(b, 42).scale(x), aa = [], |
|
192 g = d3.select("body").html("").append("svg:g"); |
|
193 x.ticks = function() { aa.push(arguments); return [42]; }; |
|
194 g.call(a); |
|
195 assert.equal(aa.length, 1); |
|
196 assert.equal(aa[0].length, 2); |
|
197 assert.equal(aa[0][0], b); |
|
198 assert.equal(aa[0][1], 42); |
|
199 }, |
|
200 "passes any arguments to the scale's tickFormat function": function(axis) { |
|
201 var b = {}, |
|
202 x = d3.scale.linear(), |
|
203 a = axis().scale(x).ticks(b, 42), |
|
204 g = d3.select("body").html("").append("svg:g"), |
|
205 aa = []; |
|
206 |
|
207 x.tickFormat = function() { |
|
208 aa.push(arguments); |
|
209 return String; |
|
210 }; |
|
211 |
|
212 g.call(a); |
|
213 assert.equal(aa.length, 1); |
|
214 assert.equal(aa[0].length, 2); |
|
215 assert.equal(aa[0][0], b); |
|
216 assert.equal(aa[0][1], 42); |
|
217 }, |
|
218 "affects the generated ticks": function(axis) { |
|
219 var a = axis().ticks(20), |
|
220 g = d3.select("body").html("").append("svg:g").call(a), |
|
221 t = g.selectAll("g"); |
|
222 assert.equal(t[0].length, 21); |
|
223 } |
|
224 }, |
|
225 |
|
226 "tickSubdivide": { |
|
227 "defaults to zero": function(axis) { |
|
228 var a = axis(); |
|
229 assert.equal(a.tickSubdivide(), 0); |
|
230 }, |
|
231 "coerces input value to a number": function(axis) { |
|
232 var a = axis().tickSubdivide(true); |
|
233 assert.strictEqual(a.tickSubdivide(), 1); |
|
234 }, |
|
235 "does not generate minor ticks when zero": function(axis) { |
|
236 var g = d3.select("body").html("").append("svg:g").call(axis()); |
|
237 assert.isTrue(g.selectAll(".minor").empty()); |
|
238 }, |
|
239 "affects the generated minor ticks": function(axis) { |
|
240 var a = axis().tickSubdivide(3), |
|
241 g = d3.select("body").html("").append("svg:g").call(a), |
|
242 t = g.selectAll("line.tick.minor"); |
|
243 assert.equal(t[0].length, 30); |
|
244 assert.equal(t[0][1].getAttribute("transform"), "translate(0.05,0)"); |
|
245 } |
|
246 }, |
|
247 |
|
248 "tickFormat": { |
|
249 "defaults to null": function(axis) { |
|
250 var a = axis(); |
|
251 assert.isTrue(a.tickFormat() == null); |
|
252 }, |
|
253 "when null, uses the scale's tick format": function(axis) { |
|
254 var x = d3.scale.linear(), a = axis().scale(x), |
|
255 g = d3.select("body").html("").append("svg:g"); |
|
256 |
|
257 x.tickFormat = function() { |
|
258 return function(d) { |
|
259 return "foo-" + d; |
|
260 }; |
|
261 }; |
|
262 |
|
263 g.call(a); |
|
264 var t = g.selectAll("g text"); |
|
265 assert.equal(t.text(), "foo-0"); |
|
266 }, |
|
267 "affects the generated tick labels": function(axis) { |
|
268 var a = axis().tickFormat(d3.format("+.2%")), |
|
269 g = d3.select("body").html("").append("svg:g").call(a), |
|
270 t = g.selectAll("g text"); |
|
271 assert.equal(t.text(), "+0.00%"); |
|
272 }, |
|
273 "can be set to a constant": function(axis) { |
|
274 var a = axis().tickFormat("I'm a tick!"), |
|
275 g = d3.select("body").html("").append("svg:g").call(a), |
|
276 t = g.selectAll("g text"); |
|
277 assert.equal(t.text(), "I'm a tick!"); |
|
278 }, |
|
279 "can be set to a falsey constant": function(axis) { |
|
280 var a = axis().tickFormat(""), |
|
281 g = d3.select("body").html("").append("svg:g").call(a), |
|
282 t = g.selectAll("g text"); |
|
283 assert.equal(t.text(), ""); |
|
284 } |
|
285 }, |
|
286 |
|
287 "enter": { |
|
288 "generates a new domain path": function(axis) { |
|
289 var a = axis(), |
|
290 g = d3.select("body").html("").append("svg:g").call(a), |
|
291 path = g.selectAll("path.domain"); |
|
292 assert.equal(path[0].length, 1); |
|
293 assert.equal(path.attr("d"), "M0,6V0H1V6"); |
|
294 assert.isNull(path.node().nextSibling); |
|
295 }, |
|
296 "generates new tick marks with labels": function(axis) { |
|
297 var a = axis(), |
|
298 g = d3.select("body").html("").append("svg:g").call(a), |
|
299 x = d3.scale.linear(), |
|
300 tick = g.selectAll("g"), |
|
301 ticks = x.ticks(10), |
|
302 tickFormat = x.tickFormat(10); |
|
303 assert.equal(tick[0].length, ticks.length); |
|
304 tick.each(function(d, i) { |
|
305 var t = d3.select(this); |
|
306 assert.isFalse(t.select("line").empty()); |
|
307 assert.isFalse(t.select("text").empty()); |
|
308 assert.equal(t.select("text").text(), tickFormat(ticks[i])); |
|
309 }); |
|
310 } |
|
311 }, |
|
312 |
|
313 "update": { |
|
314 "updates the domain path": function(axis) { |
|
315 var a = axis(), |
|
316 g = d3.select("body").html("").append("svg:g").call(a); |
|
317 a.scale().domain([0, 2]).range([1, 2]); |
|
318 a.tickSize(3); |
|
319 g.call(a); |
|
320 var path = g.selectAll("path.domain"); |
|
321 assert.equal(path[0].length, 1); |
|
322 assert.equal(path.attr("d"), "M1,3V0H2V3"); |
|
323 assert.domEqual(path.node().nextSibling, null); |
|
324 }, |
|
325 "enters, exits and updates tick marks": function(axis) { |
|
326 var a = axis(), |
|
327 g = d3.select("body").html("").append("svg:g").call(a), |
|
328 x = d3.scale.linear().domain([1, 1.5]); |
|
329 a.scale().domain(x.domain()); |
|
330 a.tickSize(3).tickPadding(9); |
|
331 g.call(a); |
|
332 var tick = g.selectAll("g"), |
|
333 ticks = x.ticks(10), |
|
334 tickFormat = x.tickFormat(10); |
|
335 assert.equal(tick[0].length, ticks.length); |
|
336 tick.each(function(d, i) { |
|
337 var t = d3.select(this); |
|
338 assert.isFalse(t.select("line").empty()); |
|
339 assert.isFalse(t.select("text").empty()); |
|
340 assert.equal(t.select("text").text(), tickFormat(ticks[i])); |
|
341 }); |
|
342 } |
|
343 } |
|
344 } |
|
345 }); |
|
346 |
|
347 suite.export(module); |