| var vows = require("vows"), | |
| load = require("../load"), | |
| assert = require("../assert"); | |
| var suite = vows.describe("selection.classed"); | |
| suite.addBatch({ | |
| "select(body)": { | |
| topic: load("selection/classed").document(), | |
| "on a simple page": { | |
| topic: function(d3) { | |
| return d3.select("body"); | |
| }, | |
| "adds a missing class as true": function(body) { | |
| body.attr("class", null); | |
| body.classed("foo", true); | |
| assert.equal(body.node().className, "foo"); | |
| body.classed("bar", true); | |
| assert.equal(body.node().className, "foo bar"); | |
| }, | |
| "removes an existing class as false": function(body) { | |
| body.attr("class", "bar foo"); | |
| body.classed("foo", false); | |
| assert.equal(body.node().className, "bar"); | |
| body.classed("bar", false); | |
| assert.equal(body.node().className, ""); | |
| }, | |
| "preserves an existing class as true": function(body) { | |
| body.attr("class", "bar foo"); | |
| body.classed("foo", true); | |
| assert.equal(body.node().className, "bar foo"); | |
| body.classed("bar", true); | |
| assert.equal(body.node().className, "bar foo"); | |
| }, | |
| "preserves a missing class as false": function(body) { | |
| body.attr("class", "baz"); | |
| body.classed("foo", false); | |
| assert.equal(body.node().className, "baz"); | |
| body.attr("class", null); | |
| body.classed("bar", false); | |
| assert.equal(body.node().className, ""); | |
| }, | |
| "gets an existing class": function(body) { | |
| body.attr("class", " foo\tbar baz"); | |
| assert.isTrue(body.classed("foo")); | |
| assert.isTrue(body.classed("bar")); | |
| assert.isTrue(body.classed("baz")); | |
| }, | |
| "does not get a missing class": function(body) { | |
| body.attr("class", " foo\tbar baz"); | |
| assert.isFalse(body.classed("foob")); | |
| assert.isFalse(body.classed("bare")); | |
| assert.isFalse(body.classed("rbaz")); | |
| }, | |
| "accepts a name with whitespace, collapsing it": function(body) { | |
| body.attr("class", null); | |
| body.classed(" foo\t", true); | |
| assert.equal(body.node().className, "foo"); | |
| body.classed("\tfoo ", false); | |
| assert.equal(body.node().className, ""); | |
| }, | |
| "accepts a name with multiple classes separated by whitespace": function(body) { | |
| body.attr("class", null); | |
| body.classed("foo bar", true); | |
| assert.equal(body.node().className, "foo bar"); | |
| assert.isTrue(body.classed("foo bar")); | |
| assert.isTrue(body.classed("bar foo")); | |
| assert.isFalse(body.classed("foo bar baz")); | |
| assert.isFalse(body.classed("foob bar")); | |
| body.classed("bar foo", false); | |
| assert.equal(body.node().className, ""); | |
| }, | |
| "accepts a silly class name with unsafe characters": function(body) { | |
| body.attr("class", null); | |
| body.classed("foo.bar", true); | |
| assert.equal(body.node().className, "foo.bar"); | |
| assert.isTrue(body.classed("foo.bar")); | |
| assert.isFalse(body.classed("foo")); | |
| assert.isFalse(body.classed("bar")); | |
| body.classed("bar.foo", false); | |
| assert.equal(body.node().className, "foo.bar"); | |
| body.classed("foo.bar", false); | |
| assert.equal(body.node().className, ""); | |
| }, | |
| "accepts a name with duplicate classes, ignoring them": function(body) { | |
| body.attr("class", null); | |
| body.classed(" foo\tfoo ", true); | |
| assert.equal(body.node().className, "foo"); | |
| body.classed("\tfoo foo ", false); | |
| assert.equal(body.node().className, ""); | |
| }, | |
| "accepts an empty name, doing nothing or returning true": function(body) { | |
| body.attr("class", null); | |
| body.classed("", true); | |
| assert.equal(body.node().className, ""); | |
| assert.isTrue(body.classed("")); | |
| body.classed(" \t ", true); | |
| assert.equal(body.node().className, ""); | |
| assert.isTrue(body.classed("")); | |
| body.classed("", false); | |
| assert.equal(body.node().className, ""); | |
| assert.isTrue(body.classed("")); | |
| }, | |
| "accepts a value function returning true or false": function(body) { | |
| body.attr("class", null); | |
| body.classed("foo", function() { return true; }); | |
| assert.equal(body.node().className, "foo"); | |
| body.classed("foo bar", function() { return true; }); | |
| assert.equal(body.node().className, "foo bar"); | |
| body.classed("foo", function() { return false; }); | |
| assert.equal(body.node().className, "bar"); | |
| }, | |
| "accepts a name object containing true or false": function(body) { | |
| body.attr("class", null); | |
| body.classed({foo: true}); | |
| assert.equal(body.node().className, "foo"); | |
| body.classed({bar: true, foo: false}); | |
| assert.equal(body.node().className, "bar"); | |
| }, | |
| "accepts a name object containing a function returning true or false": function(body) { | |
| body.attr("class", null); | |
| body.classed({foo: function() { return true; }}); | |
| assert.equal(body.node().className, "foo"); | |
| }, | |
| "accepts a name object containing a mix of functions and non-functions": function(body) { | |
| body.attr("class", "foo"); | |
| body.classed({foo: false, bar: function() { return true; }}); | |
| assert.equal(body.node().className, "bar"); | |
| }, | |
| "the value may be truthy or falsey": function(body) { | |
| body.attr("class", "foo"); | |
| body.classed({foo: null, bar: function() { return 1; }}); | |
| assert.equal(body.node().className, "bar"); | |
| }, | |
| "keys in the name object may contain whitespace": function(body) { | |
| body.attr("class", null); | |
| body.classed({" foo\t": function() { return true; }}); | |
| assert.equal(body.node().className, "foo"); | |
| body.attr("class", null); | |
| }, | |
| "keys in the name object may reference multiple classes": function(body) { | |
| body.attr("class", null); | |
| body.classed({"foo bar": function() { return true; }}); | |
| assert.equal(body.node().className, "foo bar"); | |
| body.attr("class", null); | |
| }, | |
| "keys in the name object may contain duplicates": function(body) { | |
| body.attr("class", null); | |
| body.classed({"foo foo": function() { return true; }}); | |
| assert.equal(body.node().className, "foo"); | |
| body.attr("class", null); | |
| }, | |
| "value functions are only evaluated once when used for multiple classes": function(body) { | |
| var count = 0; | |
| body.attr("class", null); | |
| body.classed({"foo bar": function() { return ++count; }}); | |
| assert.equal(body.node().className, "foo bar"); | |
| assert.equal(count, 1); | |
| }, | |
| "returns the current selection": function(body) { | |
| assert.isTrue(body.classed("foo", true) === body); | |
| } | |
| } | |
| } | |
| }); | |
| suite.addBatch({ | |
| "selectAll(div)": { | |
| topic: load("selection/classed").document(), | |
| "on a simple page": { | |
| topic: function(d3) { | |
| return d3.select("body").selectAll("div").data([0, 1]).enter().append("div"); | |
| }, | |
| "adds a missing class as true": function(div) { | |
| div.attr("class", null); | |
| div.classed("foo", true); | |
| assert.equal(div[0][0].className, "foo"); | |
| assert.equal(div[0][1].className, "foo"); | |
| div.classed("bar", true); | |
| assert.equal(div[0][0].className, "foo bar"); | |
| assert.equal(div[0][1].className, "foo bar"); | |
| }, | |
| "adds a missing class as a function": function(div) { | |
| div.data([0, 1]).attr("class", null); | |
| div.classed("foo", function(d, i) { return d === 0; }); | |
| assert.equal(div[0][0].className, "foo"); | |
| assert.equal(div[0][1].className, ""); | |
| div.classed("bar", function(d, i) { return i === 1; }); | |
| assert.equal(div[0][0].className, "foo"); | |
| assert.equal(div[0][1].className, "bar"); | |
| }, | |
| "removes an existing class as false": function(div) { | |
| div.attr("class", "bar foo"); | |
| div.classed("foo", false); | |
| assert.equal(div[0][0].className, "bar"); | |
| assert.equal(div[0][1].className, "bar"); | |
| div.classed("bar", false); | |
| assert.equal(div[0][0].className, ""); | |
| assert.equal(div[0][1].className, ""); | |
| }, | |
| "removes an existing class as a function": function(div) { | |
| div.data([0, 1]).attr("class", "bar foo"); | |
| div.classed("foo", function(d, i) { return d === 0; }); | |
| assert.equal(div[0][0].className, "bar foo"); | |
| assert.equal(div[0][1].className, "bar"); | |
| div.classed("bar", function(d, i) { return i === 1; }); | |
| assert.equal(div[0][0].className, "foo"); | |
| assert.equal(div[0][1].className, "bar"); | |
| div.classed("foo", function() { return false; }); | |
| assert.equal(div[0][0].className, ""); | |
| assert.equal(div[0][1].className, "bar"); | |
| div.classed("bar", function() { return false; }); | |
| assert.equal(div[0][0].className, ""); | |
| assert.equal(div[0][1].className, ""); | |
| }, | |
| "preserves an existing class as true": function(div) { | |
| div.attr("class", "bar foo"); | |
| div.classed("foo", true); | |
| assert.equal(div[0][0].className, "bar foo"); | |
| assert.equal(div[0][1].className, "bar foo"); | |
| div.classed("bar", true); | |
| assert.equal(div[0][0].className, "bar foo"); | |
| assert.equal(div[0][1].className, "bar foo"); | |
| }, | |
| "preserves an existing class as a function": function(div) { | |
| div.attr("class", "bar foo"); | |
| div.classed("foo", function() { return true; }); | |
| assert.equal(div[0][0].className, "bar foo"); | |
| assert.equal(div[0][1].className, "bar foo"); | |
| div.classed("bar", function() { return true; }); | |
| assert.equal(div[0][0].className, "bar foo"); | |
| assert.equal(div[0][1].className, "bar foo"); | |
| }, | |
| "preserves a missing class as false": function(div) { | |
| div.attr("class", "baz"); | |
| div.classed("foo", false); | |
| assert.equal(div[0][0].className, "baz"); | |
| assert.equal(div[0][1].className, "baz"); | |
| div.attr("class", null); | |
| div.classed("bar", false); | |
| assert.equal(div[0][0].className, ""); | |
| assert.equal(div[0][1].className, ""); | |
| }, | |
| "preserves a missing class as a function": function(div) { | |
| div.attr("class", "baz"); | |
| div.classed("foo", function() { return false; }); | |
| assert.equal(div[0][0].className, "baz"); | |
| assert.equal(div[0][1].className, "baz"); | |
| div.attr("class", null); | |
| div.classed("bar", function() { return false; }); | |
| assert.equal(div[0][0].className, ""); | |
| assert.equal(div[0][1].className, ""); | |
| }, | |
| "gets an existing class": function(div) { | |
| div[0][0].className = " foo\tbar baz"; | |
| assert.isTrue(div.classed("foo")); | |
| assert.isTrue(div.classed("bar")); | |
| assert.isTrue(div.classed("baz")); | |
| }, | |
| "does not get a missing class": function(div) { | |
| div[0][0].className = " foo\tbar baz"; | |
| assert.isFalse(div.classed("foob")); | |
| assert.isFalse(div.classed("bare")); | |
| assert.isFalse(div.classed("rbaz")); | |
| }, | |
| "returns the current selection": function(div) { | |
| assert.isTrue(div.classed("foo", true) === div); | |
| }, | |
| "ignores null nodes": function(div) { | |
| var node = div[0][1]; | |
| div.attr("class", null); | |
| div[0][1] = null; | |
| div.classed("foo", true); | |
| assert.equal(div[0][0].className, "foo"); | |
| assert.equal(node.className, ""); | |
| } | |
| } | |
| } | |
| }); | |
| suite.export(module); |