257 строки
9.3 KiB
JavaScript
257 строки
9.3 KiB
JavaScript
var vows = require("vows"),
|
||
_ = require("../../"),
|
||
load = require("../load"),
|
||
assert = require("../assert");
|
||
|
||
var suite = vows.describe("d3.nest");
|
||
|
||
suite.addBatch({
|
||
"entries": {
|
||
topic: load("arrays/nest").expression("d3.nest"),
|
||
"returns an array of each distinct key in arbitrary order": function(nest) {
|
||
var keys = nest()
|
||
.key(function(d) { return d.foo; })
|
||
.entries([{foo: 1}, {foo: 1}, {foo: 2}])
|
||
.map(function(d) { return d.key; })
|
||
.sort(_.ascending);
|
||
assert.deepEqual(keys, ["1", "2"]);
|
||
},
|
||
"each entry is a key-values object, with values in input order": function(nest) {
|
||
var entries = nest()
|
||
.key(function(d) { return d.foo; })
|
||
.entries([{foo: 1, bar: 0}, {foo: 2}, {foo: 1, bar: 1}]);
|
||
assert.deepEqual(entries, [
|
||
{key: "1", values: [{foo: 1, bar: 0}, {foo: 1, bar: 1}]},
|
||
{key: "2", values: [{foo: 2}]}
|
||
]);
|
||
},
|
||
"keys can be sorted using an optional comparator": function(nest) {
|
||
var keys = nest()
|
||
.key(function(d) { return d.foo; }).sortKeys(_.descending)
|
||
.entries([{foo: 1}, {foo: 1}, {foo: 2}])
|
||
.map(function(d) { return d.key; });
|
||
assert.deepEqual(keys, ["2", "1"]);
|
||
},
|
||
"values can be sorted using an optional comparator": function(nest) {
|
||
var entries = nest()
|
||
.key(function(d) { return d.foo; })
|
||
.sortValues(function(a, b) { return a.bar - b.bar; })
|
||
.entries([{foo: 1, bar: 2}, {foo: 1, bar: 0}, {foo: 1, bar: 1}, {foo: 2}]);
|
||
assert.deepEqual(entries, [
|
||
{key: "1", values: [{foo: 1, bar: 0}, {foo: 1, bar: 1}, {foo: 1, bar: 2}]},
|
||
{key: "2", values: [{foo: 2}]}
|
||
]);
|
||
},
|
||
"values can be aggregated using an optional rollup": function(nest) {
|
||
var entries = nest()
|
||
.key(function(d) { return d.foo; })
|
||
.rollup(function(values) { return _.sum(values, function(d) { return d.bar; }); })
|
||
.entries([{foo: 1, bar: 2}, {foo: 1, bar: 0}, {foo: 1, bar: 1}, {foo: 2}]);
|
||
assert.deepEqual(entries, [
|
||
{key: "1", values: 3},
|
||
{key: "2", values: 0}
|
||
]);
|
||
},
|
||
"multiple key functions can be specified": function(nest) {
|
||
var entries = nest()
|
||
.key(function(d) { return d[0]; }).sortKeys(_.ascending)
|
||
.key(function(d) { return d[1]; }).sortKeys(_.ascending)
|
||
.entries([[0, 1], [0, 2], [1, 1], [1, 2], [0, 2]]);
|
||
assert.deepEqual(entries, [
|
||
{key: "0", values: [
|
||
{key: "1", values: [[0, 1]]},
|
||
{key: "2", values: [[0, 2], [0, 2]]}
|
||
]},
|
||
{key: "1", values: [
|
||
{key: "1", values: [[1, 1]]},
|
||
{key: "2", values: [[1, 2]]}
|
||
]}
|
||
]);
|
||
},
|
||
"the rollup function only applies to leaf values": function(nest) {
|
||
var entries = nest()
|
||
.key(function(d) { return d[0]; }).sortKeys(_.ascending)
|
||
.key(function(d) { return d[1]; }).sortKeys(_.ascending)
|
||
.rollup(function(values) { return values.length; })
|
||
.entries([[0, 1], [0, 2], [1, 1], [1, 2], [0, 2]]);
|
||
assert.deepEqual(entries, [
|
||
{key: "0", values: [
|
||
{key: "1", values: 1},
|
||
{key: "2", values: 2}
|
||
]},
|
||
{key: "1", values: [
|
||
{key: "1", values: 1},
|
||
{key: "2", values: 1}
|
||
]}
|
||
]);
|
||
},
|
||
"the value comparator only applies to leaf values": function(nest) {
|
||
var entries = nest()
|
||
.key(function(d) { return d[0]; }).sortKeys(_.ascending)
|
||
.key(function(d) { return d[1]; }).sortKeys(_.ascending)
|
||
.sortValues(function(a, b) { return a[2] - b[2]; })
|
||
.entries([[0, 1], [0, 2, 1], [1, 1], [1, 2], [0, 2, 0]]);
|
||
assert.deepEqual(entries, [
|
||
{key: "0", values: [
|
||
{key: "1", values: [[0, 1]]},
|
||
{key: "2", values: [[0, 2, 0], [0, 2, 1]]}
|
||
]},
|
||
{key: "1", values: [
|
||
{key: "1", values: [[1, 1]]},
|
||
{key: "2", values: [[1, 2]]}
|
||
]}
|
||
]);
|
||
},
|
||
"the key comparator only applies to the last-specified key": function(nest) {
|
||
var entries = nest()
|
||
.key(function(d) { return d[0]; }).sortKeys(_.ascending)
|
||
.key(function(d) { return d[1]; }).sortKeys(_.descending)
|
||
.entries([[0, 1], [0, 2], [1, 1], [1, 2], [0, 2]]);
|
||
assert.deepEqual(entries, [
|
||
{key: "0", values: [
|
||
{key: "2", values: [[0, 2], [0, 2]]},
|
||
{key: "1", values: [[0, 1]]}
|
||
]},
|
||
{key: "1", values: [
|
||
{key: "2", values: [[1, 2]]},
|
||
{key: "1", values: [[1, 1]]}
|
||
]}
|
||
]);
|
||
var entries = nest()
|
||
.key(function(d) { return d[0]; }).sortKeys(_.descending)
|
||
.key(function(d) { return d[1]; }).sortKeys(_.ascending)
|
||
.entries([[0, 1], [0, 2], [1, 1], [1, 2], [0, 2]]);
|
||
assert.deepEqual(entries, [
|
||
{key: "1", values: [
|
||
{key: "1", values: [[1, 1]]},
|
||
{key: "2", values: [[1, 2]]}
|
||
]},
|
||
{key: "0", values: [
|
||
{key: "1", values: [[0, 1]]},
|
||
{key: "2", values: [[0, 2], [0, 2]]}
|
||
]}
|
||
]);
|
||
},
|
||
"if no keys are specified, the input array is returned": function(nest) {
|
||
var array = [new Object()];
|
||
assert.strictEqual(nest().entries(array), array);
|
||
}
|
||
}
|
||
});
|
||
|
||
suite.addBatch({
|
||
"map": {
|
||
topic: load("arrays/nest").expression("d3.nest"),
|
||
"returns a map of each distinct key": function(nest) {
|
||
var map = nest()
|
||
.key(function(d) { return d.foo; })
|
||
.map([{foo: 1, bar: 0}, {foo: 2}, {foo: 1, bar: 1}]);
|
||
assert.deepEqual(map, {
|
||
"1": [{foo: 1, bar: 0}, {foo: 1, bar: 1}],
|
||
"2": [{foo: 2}]
|
||
});
|
||
},
|
||
"values can be sorted using an optional comparator": function(nest) {
|
||
var map = nest()
|
||
.key(function(d) { return d.foo; })
|
||
.sortValues(function(a, b) { return a.bar - b.bar; })
|
||
.map([{foo: 1, bar: 2}, {foo: 1, bar: 0}, {foo: 1, bar: 1}, {foo: 2}]);
|
||
assert.deepEqual(map, {
|
||
"1": [{foo: 1, bar: 0}, {foo: 1, bar: 1}, {foo: 1, bar: 2}],
|
||
"2": [{foo: 2}]
|
||
});
|
||
},
|
||
"values can be aggregated using an optional rollup": function(nest) {
|
||
var map = nest()
|
||
.key(function(d) { return d.foo; })
|
||
.rollup(function(values) { return _.sum(values, function(d) { return d.bar; }); })
|
||
.map([{foo: 1, bar: 2}, {foo: 1, bar: 0}, {foo: 1, bar: 1}, {foo: 2}]);
|
||
assert.deepEqual(map, {
|
||
"1": 3,
|
||
"2": 0
|
||
});
|
||
},
|
||
"multiple key functions can be specified": function(nest) {
|
||
var map = nest()
|
||
.key(function(d) { return d[0]; }).sortKeys(_.ascending)
|
||
.key(function(d) { return d[1]; }).sortKeys(_.ascending)
|
||
.map([[0, 1], [0, 2], [1, 1], [1, 2], [0, 2]]);
|
||
assert.deepEqual(map, {
|
||
"0": {
|
||
"1": [[0, 1]],
|
||
"2": [[0, 2], [0, 2]]
|
||
},
|
||
"1": {
|
||
"1": [[1, 1]],
|
||
"2": [[1, 2]]
|
||
}
|
||
});
|
||
},
|
||
"the rollup function only applies to leaf values": function(nest) {
|
||
var map = nest()
|
||
.key(function(d) { return d[0]; }).sortKeys(_.ascending)
|
||
.key(function(d) { return d[1]; }).sortKeys(_.ascending)
|
||
.rollup(function(values) { return values.length; })
|
||
.map([[0, 1], [0, 2], [1, 1], [1, 2], [0, 2]]);
|
||
assert.deepEqual(map, {
|
||
"0": {
|
||
"1": 1,
|
||
"2": 2
|
||
},
|
||
"1": {
|
||
"1": 1,
|
||
"2": 1
|
||
}
|
||
});
|
||
},
|
||
"the value comparator only applies to leaf values": function(nest) {
|
||
var map = nest()
|
||
.key(function(d) { return d[0]; }).sortKeys(_.ascending)
|
||
.key(function(d) { return d[1]; }).sortKeys(_.ascending)
|
||
.sortValues(function(a, b) { return a[2] - b[2]; })
|
||
.map([[0, 1], [0, 2, 1], [1, 1], [1, 2], [0, 2, 0]]);
|
||
assert.deepEqual(map, {
|
||
"0": {
|
||
"1": [[0, 1]],
|
||
"2": [[0, 2, 0], [0, 2, 1]]
|
||
},
|
||
"1": {
|
||
"1": [[1, 1]],
|
||
"2": [[1, 2]]
|
||
}
|
||
});
|
||
},
|
||
"if no keys are specified, the input array is returned": function(nest) {
|
||
var array = [new Object()];
|
||
assert.strictEqual(nest().map(array), array);
|
||
},
|
||
"handles keys that are built-in prototype properties": function(nest) {
|
||
var map = nest()
|
||
.key(String)
|
||
.map(["hasOwnProperty"]); // but note __proto__ wouldn’t work!
|
||
assert.deepEqual(map, {hasOwnProperty: ["hasOwnProperty"]});
|
||
},
|
||
"a custom map implementation can be specified": function(nest) {
|
||
var map = nest()
|
||
.key(String)
|
||
.map(["hasOwnProperty", "__proto__"], _.map);
|
||
assert.deepEqual(map.entries(), [
|
||
{key: "hasOwnProperty", value: ["hasOwnProperty"]},
|
||
{key: "__proto__", value: ["__proto__"]}
|
||
]);
|
||
},
|
||
"the custom map implementation works on multiple levels of nesting": function(nest) {
|
||
var map = nest()
|
||
.key(function(d) { return d.foo; })
|
||
.key(function(d) { return d.bar; })
|
||
.map([{foo: 42, bar: "red"}], _.map);
|
||
assert.deepEqual(map.keys(), ["42"]);
|
||
assert.deepEqual(map.get("42").keys(), ["red"]);
|
||
assert.deepEqual(map.get("42").values(), [[{foo: 42, bar: "red"}]]);
|
||
assert.deepEqual(map.get("42").entries(), [{key: "red", value: [{foo: 42, bar: "red"}]}]);
|
||
}
|
||
}
|
||
});
|
||
|
||
suite.export(module);
|