Fix jest test suites (#268)

* CRLF to LF

* add babel-jest

* use ES6 style imports

* fix bugs manifest by test suite

* add babel test config
This commit is contained in:
Bruce Martin
2018-09-27 17:52:17 -07:00
committed by GitHub
parent 2d218fa099
commit f0d9d873be
5 changed files with 807 additions and 788 deletions
+185 -184
View File
@@ -1,184 +1,185 @@
// jshint esversion: 6 // jshint esversion: 6
const BitArray = require("../../src/util/typedCrossfilter/bitArray"); import BitArray from "../../src/util/typedCrossfilter/bitArray";
const defaultTestLength = 8;
const defaultTestLength = 8;
describe("default select state", () => {
test("newly created Bitarray should be deselected", () => { describe("default select state", () => {
const ba = new BitArray(defaultTestLength); test("newly created Bitarray should be deselected", () => {
expect(ba).toBeDefined(); const ba = new BitArray(defaultTestLength);
expect(ba).toBeDefined();
for (let i = 0; i < defaultTestLength; i++) {
expect(ba.isSelected(i)).toEqual(false); for (let i = 0; i < defaultTestLength; i++) {
} expect(ba.isSelected(i)).toEqual(false);
}
const dim = ba.allocDimension();
expect(dim).toBeDefined(); const dim = ba.allocDimension();
for (let i = 0; i < defaultTestLength; i++) { expect(dim).toBeDefined();
expect(ba.isSelected(i)).toEqual(false); for (let i = 0; i < defaultTestLength; i++) {
} expect(ba.isSelected(i)).toEqual(false);
}
ba.freeDimension(dim);
for (let i = 0; i < defaultTestLength; i++) { ba.freeDimension(dim);
expect(ba.isSelected(i)).toEqual(false); for (let i = 0; i < defaultTestLength; i++) {
} expect(ba.isSelected(i)).toEqual(false);
}); }
}); });
});
describe("select and deselect", () => {
test("selectAll and deselectAll", () => { describe("select and deselect", () => {
const ba = new BitArray(defaultTestLength); test("selectAll and deselectAll", () => {
expect(ba).toBeDefined(); const ba = new BitArray(defaultTestLength);
const dim1 = ba.allocDimension(); expect(ba).toBeDefined();
expect(dim1).toBeDefined(); const dim1 = ba.allocDimension();
ba.selectAll(dim1); expect(dim1).toBeDefined();
ba.selectAll(dim1);
for (let i = 0; i < defaultTestLength; i++) {
expect(ba.isSelected(i)).toEqual(true); for (let i = 0; i < defaultTestLength; i++) {
} expect(ba.isSelected(i)).toEqual(true);
}
const dim2 = ba.allocDimension();
expect(dim2).toBeDefined(); const dim2 = ba.allocDimension();
for (let i = 0; i < defaultTestLength; i++) { expect(dim2).toBeDefined();
expect(ba.isSelected(i)).toEqual(false); for (let i = 0; i < defaultTestLength; i++) {
} expect(ba.isSelected(i)).toEqual(false);
}
ba.selectAll(dim2);
for (let i = 0; i < defaultTestLength; i++) { ba.selectAll(dim2);
expect(ba.isSelected(i)).toEqual(true); for (let i = 0; i < defaultTestLength; i++) {
} expect(ba.isSelected(i)).toEqual(true);
}
ba.deselectAll(dim1);
for (let i = 0; i < defaultTestLength; i++) { ba.deselectAll(dim1);
expect(ba.isSelected(i)).toEqual(false); for (let i = 0; i < defaultTestLength; i++) {
} expect(ba.isSelected(i)).toEqual(false);
}
ba.deselectAll(dim2);
for (let i = 0; i < defaultTestLength; i++) { ba.deselectAll(dim2);
expect(ba.isSelected(i)).toEqual(false); for (let i = 0; i < defaultTestLength; i++) {
} expect(ba.isSelected(i)).toEqual(false);
}
ba.selectAll(dim1);
ba.selectAll(dim2); ba.selectAll(dim1);
for (let i = 0; i < defaultTestLength; i++) { ba.selectAll(dim2);
expect(ba.isSelected(i)).toEqual(true); for (let i = 0; i < defaultTestLength; i++) {
} expect(ba.isSelected(i)).toEqual(true);
}
ba.freeDimension(dim1);
for (let i = 0; i < defaultTestLength; i++) { ba.freeDimension(dim1);
expect(ba.isSelected(i)).toEqual(true); for (let i = 0; i < defaultTestLength; i++) {
} expect(ba.isSelected(i)).toEqual(true);
}
ba.freeDimension(dim2);
for (let i = 0; i < defaultTestLength; i++) { ba.freeDimension(dim2);
expect(ba.isSelected(i)).toEqual(false); for (let i = 0; i < defaultTestLength; i++) {
} expect(ba.isSelected(i)).toEqual(false);
}); }
});
test("selectOne and deselectOne", () => {
const ba = new BitArray(defaultTestLength); test("selectOne and deselectOne", () => {
expect(ba).toBeDefined(); const ba = new BitArray(defaultTestLength);
const dim = ba.allocDimension(); expect(ba).toBeDefined();
expect(dim).toBeDefined(); const dim = ba.allocDimension();
expect(dim).toBeDefined();
ba.selectOne(dim, 0);
expect(ba.isSelected(0)).toEqual(true); ba.selectOne(dim, 0);
for (let i = 1; i < defaultTestLength; i++) { expect(ba.isSelected(0)).toEqual(true);
expect(ba.isSelected(i)).toEqual(false); for (let i = 1; i < defaultTestLength; i++) {
} expect(ba.isSelected(i)).toEqual(false);
}
ba.deselectOne(dim, 0);
for (let i = 0; i < defaultTestLength; i++) { ba.deselectOne(dim, 0);
expect(ba.isSelected(i)).toEqual(false); for (let i = 0; i < defaultTestLength; i++) {
} expect(ba.isSelected(i)).toEqual(false);
}
ba.selectOne(dim, 1);
expect(ba.isSelected(1)).toEqual(true); ba.selectOne(dim, 1);
expect(ba.isSelected(0)).toEqual(false); expect(ba.isSelected(1)).toEqual(true);
for (let i = 2; i < defaultTestLength; i++) { expect(ba.isSelected(0)).toEqual(false);
expect(ba.isSelected(i)).toEqual(false); for (let i = 2; i < defaultTestLength; i++) {
} expect(ba.isSelected(i)).toEqual(false);
}
ba.selectAll(dim);
ba.deselectOne(dim, defaultTestLength - 1); ba.selectAll(dim);
expect(ba.isSelected(defaultTestLength - 1)).toEqual(false); ba.deselectOne(dim, defaultTestLength - 1);
for (let i = 0; i < defaultTestLength - 1; i++) { expect(ba.isSelected(defaultTestLength - 1)).toEqual(false);
expect(ba.isSelected(i)).toEqual(true); for (let i = 0; i < defaultTestLength - 1; i++) {
} expect(ba.isSelected(i)).toEqual(true);
}); }
}); });
});
describe("selectionCount", () => {
test("simple", () => { describe("selectionCount", () => {
const ba = new BitArray(defaultTestLength); test("simple", () => {
expect(ba).toBeDefined(); const ba = new BitArray(defaultTestLength);
const dim1 = ba.allocDimension(); expect(ba).toBeDefined();
expect(dim1).toBeDefined(); const dim1 = ba.allocDimension();
const dim2 = ba.allocDimension(); expect(dim1).toBeDefined();
expect(dim2).toBeDefined(); const dim2 = ba.allocDimension();
expect(dim2).toBeDefined();
expect(ba.selectionCount).toEqual(0);
ba.selectAll(dim1); expect(ba.selectionCount).toEqual(0);
expect(ba.selectionCount).toEqual(0); ba.selectAll(dim1);
ba.selectAll(dim2); expect(ba.selectionCount).toEqual(0);
expect(ba.selectionCount).toEqual(defaultTestLength); ba.selectAll(dim2);
expect(ba.selectionCount).toEqual(defaultTestLength);
for (let i = 0; i < defaultTestLength; i++) {
ba.deselectOne(dim1, i); for (let i = 0; i < defaultTestLength; i++) {
expect(ba.selectionCount).toEqual(defaultTestLength - i - 1); ba.deselectOne(dim1, i);
expect(ba.selectionCount).toEqual(ba.countAllOnes()); expect(ba.selectionCount).toEqual(defaultTestLength - i - 1);
} expect(ba.selectionCount).toEqual(ba.countAllOnes());
}
ba.freeDimension(dim1);
ba.freeDimension(dim2); ba.freeDimension(dim1);
}); ba.freeDimension(dim2);
}); });
});
describe("fillBySelection", () => {
test("sets values correctly", () => { describe("fillBySelection", () => {
const ba = new BitArray(defaultTestLength); test("sets values correctly", () => {
expect(ba).toBeDefined(); const ba = new BitArray(defaultTestLength);
const dim = ba.allocDimension(); expect(ba).toBeDefined();
expect(dim).toBeDefined(); const dim = ba.allocDimension();
expect(dim).toBeDefined();
const arr = new Int32Array(defaultTestLength);
arr.fill(0); const arr = new Int32Array(defaultTestLength);
const truth = new Int32Array(defaultTestLength); arr.fill(0);
truth.fill(0); const truth = new Int32Array(defaultTestLength);
truth.fill(0);
// initial state should be deselected
ba.fillBySelection(arr, 1, 0); // initial state should be deselected
expect(arr).toEqual(expect.not.arrayContaining([1])); ba.fillBySelection(arr, 1, 0);
expect(arr).toEqual(expect.not.arrayContaining([1]));
// selectAll
ba.selectAll(dim); // selectAll
ba.fillBySelection(arr, 1, 0); ba.selectAll(dim);
expect(arr).toEqual(expect.not.arrayContaining([0])); ba.fillBySelection(arr, 1, 0);
expect(arr).toEqual(expect.not.arrayContaining([0]));
// deselectOne
ba.deselectOne(dim, 3); // deselectOne
ba.fillBySelection(arr, 1, 0); ba.deselectOne(dim, 3);
truth.fill(1); ba.fillBySelection(arr, 1, 0);
truth[3] = 0; truth.fill(1);
expect(arr).toEqual(truth); truth[3] = 0;
expect(arr).toEqual(truth);
// deselectAll
ba.deselectAll(dim); // deselectAll
ba.fillBySelection(arr, 1, 0); ba.deselectAll(dim);
truth.fill(0); ba.fillBySelection(arr, 1, 0);
expect(arr).toEqual(truth); truth.fill(0);
expect(arr).toEqual(truth);
// selectOne
ba.selectOne(dim, 5); // selectOne
ba.fillBySelection(arr, 6, 1); ba.selectOne(dim, 5);
truth.fill(1); ba.fillBySelection(arr, 6, 1);
truth[5] = 6; truth.fill(1);
expect(arr).toEqual(truth); truth[5] = 6;
expect(arr).toEqual(truth);
// should be deselected after dimension disposal
ba.freeDimension(dim); // should be deselected after dimension disposal
ba.fillBySelection(arr, 3, 9); ba.freeDimension(dim);
truth.fill(9); ba.fillBySelection(arr, 3, 9);
expect(arr).toEqual(truth); truth.fill(9);
}); expect(arr).toEqual(truth);
}); });
});
+141 -140
View File
@@ -1,140 +1,141 @@
// jshint esversion: 6 // jshint esversion: 6
const PositiveIntervals = require("../../src/util/typedCrossfilter/positiveIntervals"); // const PositiveIntervals = require("../../src/util/typedCrossfilter/positiveIntervals");
import PositiveIntervals from "../../src/util/typedCrossfilter/positiveIntervals";
describe("canonicalize", () => {
test("empty", () => { describe("canonicalize", () => {
expect(PositiveIntervals.canonicalize([])).toEqual([]); test("empty", () => {
}); expect(PositiveIntervals.canonicalize([])).toEqual([]);
});
test("simple, already correct", () => {
expect(PositiveIntervals.canonicalize([[0, 1]])).toEqual([[0, 1]]); test("simple, already correct", () => {
expect(PositiveIntervals.canonicalize([[0, 1], [2, 3]])).toEqual([ expect(PositiveIntervals.canonicalize([[0, 1]])).toEqual([[0, 1]]);
[0, 1], expect(PositiveIntervals.canonicalize([[0, 1], [2, 3]])).toEqual([
[2, 3] [0, 1],
]); [2, 3]
}); ]);
});
test("non-canonical, need to be canonicalized", () => {
expect(PositiveIntervals.canonicalize([[0, 1], [1, 2]])).toEqual([[0, 2]]); test("non-canonical, need to be canonicalized", () => {
expect(PositiveIntervals.canonicalize([[1, 2], [2, 3]])).toEqual([[1, 3]]); expect(PositiveIntervals.canonicalize([[0, 1], [1, 2]])).toEqual([[0, 2]]);
}); expect(PositiveIntervals.canonicalize([[1, 2], [2, 3]])).toEqual([[1, 3]]);
}); });
});
describe("union", () => {
test("empty range", () => { describe("union", () => {
expect(PositiveIntervals.union([], [])).toEqual([]); test("empty range", () => {
expect(PositiveIntervals.union([], [[1, 2]])).toEqual([[1, 2]]); expect(PositiveIntervals.union([], [])).toEqual([]);
expect(PositiveIntervals.union([], [[1, 2], [3, 4]])).toEqual([ expect(PositiveIntervals.union([], [[1, 2]])).toEqual([[1, 2]]);
[1, 2], expect(PositiveIntervals.union([], [[1, 2], [3, 4]])).toEqual([
[3, 4] [1, 2],
]); [3, 4]
expect(PositiveIntervals.union([[3, 4]], [])).toEqual([[3, 4]]); ]);
expect(PositiveIntervals.union([[1, 2], [3, 4]], [])).toEqual([ expect(PositiveIntervals.union([[3, 4]], [])).toEqual([[3, 4]]);
[1, 2], expect(PositiveIntervals.union([[1, 2], [3, 4]], [])).toEqual([
[3, 4] [1, 2],
]); [3, 4]
expect(PositiveIntervals.union([[3, 3]], [])).toEqual([[3, 3]]); ]);
expect(PositiveIntervals.union([], [[3, 3]])).toEqual([[3, 3]]); expect(PositiveIntervals.union([[3, 3]], [])).toEqual([[3, 3]]);
}); expect(PositiveIntervals.union([], [[3, 3]])).toEqual([[3, 3]]);
});
test("simple ranges", () => {
expect(PositiveIntervals.union([[1, 2]], [[2, 3]])).toEqual([[1, 3]]); test("simple ranges", () => {
expect(PositiveIntervals.union([[2, 3]], [[1, 2]])).toEqual([[1, 3]]); expect(PositiveIntervals.union([[1, 2]], [[2, 3]])).toEqual([[1, 3]]);
expect(PositiveIntervals.union([[1, 2]], [[3, 4]])).toEqual([ expect(PositiveIntervals.union([[2, 3]], [[1, 2]])).toEqual([[1, 3]]);
[1, 2], expect(PositiveIntervals.union([[1, 2]], [[3, 4]])).toEqual([
[3, 4] [1, 2],
]); [3, 4]
expect( ]);
PositiveIntervals.union([[1, 2], [3, 4]], [[6, 7], [19, 40]]) expect(
).toEqual([[1, 2], [3, 4], [6, 7], [19, 40]]); PositiveIntervals.union([[1, 2], [3, 4]], [[6, 7], [19, 40]])
expect(PositiveIntervals.union([[1, 4]], [[1, 1], [3, 4]])).toEqual([ ).toEqual([[1, 2], [3, 4], [6, 7], [19, 40]]);
[1, 4] expect(PositiveIntervals.union([[1, 4]], [[1, 1], [3, 4]])).toEqual([
]); [1, 4]
expect(PositiveIntervals.union([[3, 3]], [[4, 4]])).toEqual([ ]);
[3, 3], expect(PositiveIntervals.union([[3, 3]], [[4, 4]])).toEqual([
[4, 4] [3, 3],
]); [4, 4]
}); ]);
}); });
});
describe("intersection", () => {
test("empty range", () => { describe("intersection", () => {
expect(PositiveIntervals.intersection([], [])).toEqual([]); test("empty range", () => {
expect(PositiveIntervals.intersection([], [[1, 2]])).toEqual([]); expect(PositiveIntervals.intersection([], [])).toEqual([]);
expect(PositiveIntervals.intersection([[1, 2]], [])).toEqual([]); expect(PositiveIntervals.intersection([], [[1, 2]])).toEqual([]);
}); expect(PositiveIntervals.intersection([[1, 2]], [])).toEqual([]);
});
test("simple", () => {
expect(PositiveIntervals.intersection([[1, 2]], [[2, 3]])).toEqual([]); test("simple", () => {
expect(PositiveIntervals.intersection([[2, 3]], [[1, 2]])).toEqual([]); expect(PositiveIntervals.intersection([[1, 2]], [[2, 3]])).toEqual([]);
expect(PositiveIntervals.intersection([[1, 10]], [[1, 10]])).toEqual([ expect(PositiveIntervals.intersection([[2, 3]], [[1, 2]])).toEqual([]);
[1, 10] expect(PositiveIntervals.intersection([[1, 10]], [[1, 10]])).toEqual([
]); [1, 10]
expect(PositiveIntervals.intersection([[1, 10]], [[2, 8]])).toEqual([ ]);
[2, 8] expect(PositiveIntervals.intersection([[1, 10]], [[2, 8]])).toEqual([
]); [2, 8]
expect(PositiveIntervals.intersection([[2, 8]], [[1, 10]])).toEqual([ ]);
[2, 8] expect(PositiveIntervals.intersection([[2, 8]], [[1, 10]])).toEqual([
]); [2, 8]
expect(PositiveIntervals.intersection([[1, 10]], [[2, 12]])).toEqual([ ]);
[2, 10] expect(PositiveIntervals.intersection([[1, 10]], [[2, 12]])).toEqual([
]); [2, 10]
expect(PositiveIntervals.intersection([[2, 12]], [[1, 10]])).toEqual([ ]);
[2, 10] expect(PositiveIntervals.intersection([[2, 12]], [[1, 10]])).toEqual([
]); [2, 10]
expect(PositiveIntervals.intersection([[1, 10]], [[1, 8]])).toEqual([ ]);
[1, 8] expect(PositiveIntervals.intersection([[1, 10]], [[1, 8]])).toEqual([
]); [1, 8]
expect(PositiveIntervals.intersection([[1, 8]], [[1, 10]])).toEqual([ ]);
[1, 8] expect(PositiveIntervals.intersection([[1, 8]], [[1, 10]])).toEqual([
]); [1, 8]
expect(PositiveIntervals.intersection([[1, 10]], [[1, 2], [6, 9]])).toEqual( ]);
[[1, 2], [6, 9]] expect(PositiveIntervals.intersection([[1, 10]], [[1, 2], [6, 9]])).toEqual(
); [[1, 2], [6, 9]]
expect(PositiveIntervals.intersection([[0, 2638]], [[1363, 2638]])).toEqual( );
[[1363, 2638]] expect(PositiveIntervals.intersection([[0, 2638]], [[1363, 2638]])).toEqual(
); [[1363, 2638]]
expect(PositiveIntervals.intersection([[1, 2]], [[1, 2]])).toEqual([ );
[1, 2] expect(PositiveIntervals.intersection([[1, 2]], [[1, 2]])).toEqual([
]); [1, 2]
}); ]);
}); });
});
describe("difference", () => {
test("empty", () => { describe("difference", () => {
expect(PositiveIntervals.difference([], [])).toEqual([]); test("empty", () => {
expect(PositiveIntervals.difference([], [[1, 10]])).toEqual([]); expect(PositiveIntervals.difference([], [])).toEqual([]);
expect(PositiveIntervals.difference([[1, 10]], [])).toEqual([[1, 10]]); expect(PositiveIntervals.difference([], [[1, 10]])).toEqual([]);
}); expect(PositiveIntervals.difference([[1, 10]], [])).toEqual([[1, 10]]);
});
test("simple", () => {
expect(PositiveIntervals.difference([[1, 2], [3, 4]], [])).toEqual([ test("simple", () => {
[1, 2], expect(PositiveIntervals.difference([[1, 2], [3, 4]], [])).toEqual([
[3, 4] [1, 2],
]); [3, 4]
expect(PositiveIntervals.difference([[1, 2], [3, 10]], [[5, 10]])).toEqual([ ]);
[1, 2], expect(PositiveIntervals.difference([[1, 2], [3, 10]], [[5, 10]])).toEqual([
[3, 5] [1, 2],
]); [3, 5]
expect(PositiveIntervals.difference([[1, 2], [3, 10]], [[0, 5]])).toEqual([ ]);
[5, 10] expect(PositiveIntervals.difference([[1, 2], [3, 10]], [[0, 5]])).toEqual([
]); [5, 10]
expect( ]);
PositiveIntervals.difference([[0, 2638]], [[0, 1363], [2055, 2638]]) expect(
).toEqual([[1363, 2055]]); PositiveIntervals.difference([[0, 2638]], [[0, 1363], [2055, 2638]])
expect( ).toEqual([[1363, 2055]]);
PositiveIntervals.difference([[0, 1363], [2055, 2638]], [[0, 2638]]) expect(
).toEqual([]); PositiveIntervals.difference([[0, 1363], [2055, 2638]], [[0, 2638]])
expect(PositiveIntervals.difference([[0, 10]], [[0, 1]])).toEqual([ ).toEqual([]);
[1, 10] expect(PositiveIntervals.difference([[0, 10]], [[0, 1]])).toEqual([
]); [1, 10]
expect(PositiveIntervals.difference([[0, 10]], [[1, 2]])).toEqual([ ]);
[0, 1], expect(PositiveIntervals.difference([[0, 10]], [[1, 2]])).toEqual([
[2, 10] [0, 1],
]); [2, 10]
expect(PositiveIntervals.difference([[0, 10]], [[9, 10]])).toEqual([ ]);
[0, 9] expect(PositiveIntervals.difference([[0, 10]], [[9, 10]])).toEqual([
]); [0, 9]
}); ]);
}); });
});
+462 -462
View File
@@ -1,462 +1,462 @@
// jshint esversion: 6 // jshint esversion: 6
const _ = require("lodash"); import _ from "lodash";
const crossfilter = require("../../src/util/typedCrossfilter"); import crossfilter from "../../src/util/typedCrossfilter";
const someData = [ const someData = [
{ {
date: "2011-11-14T16:17:54Z", date: "2011-11-14T16:17:54Z",
quantity: 2, quantity: 2,
total: 190, total: 190,
tip: 100, tip: 100,
type: "tab", type: "tab",
productIDs: ["001"] productIDs: ["001"]
}, },
{ {
date: "2011-11-14T16:20:19Z", date: "2011-11-14T16:20:19Z",
quantity: 2, quantity: 2,
total: 190, total: 190,
tip: 100, tip: 100,
type: "tab", type: "tab",
productIDs: ["001", "005"] productIDs: ["001", "005"]
}, },
{ {
date: "2011-11-14T16:28:54Z", date: "2011-11-14T16:28:54Z",
quantity: 1, quantity: 1,
total: 300, total: 300,
tip: 200, tip: 200,
type: "visa", type: "visa",
productIDs: ["004", "005"] productIDs: ["004", "005"]
}, },
{ {
date: "2011-11-14T16:30:43Z", date: "2011-11-14T16:30:43Z",
quantity: 2, quantity: 2,
total: 90, total: 90,
tip: 0, tip: 0,
type: "tab", type: "tab",
productIDs: ["001", "002"] productIDs: ["001", "002"]
}, },
{ {
date: "2011-11-14T16:48:46Z", date: "2011-11-14T16:48:46Z",
quantity: 2, quantity: 2,
total: 90, total: 90,
tip: 0, tip: 0,
type: "tab", type: "tab",
productIDs: ["005"] productIDs: ["005"]
}, },
{ {
date: "2011-11-14T16:53:41Z", date: "2011-11-14T16:53:41Z",
quantity: 2, quantity: 2,
total: 90, total: 90,
tip: 0, tip: 0,
type: "tab", type: "tab",
productIDs: ["001", "004", "005"] productIDs: ["001", "004", "005"]
}, },
{ {
date: "2011-11-14T16:54:06Z", date: "2011-11-14T16:54:06Z",
quantity: 1, quantity: 1,
total: 100, total: 100,
tip: 0, tip: 0,
type: "cash", type: "cash",
productIDs: ["001", "002", "003", "004", "005"] productIDs: ["001", "002", "003", "004", "005"]
}, },
{ {
date: "2011-11-14T16:58:03Z", date: "2011-11-14T16:58:03Z",
quantity: 2, quantity: 2,
total: 90, total: 90,
tip: 0, tip: 0,
type: "tab", type: "tab",
productIDs: ["001"] productIDs: ["001"]
}, },
{ {
date: "2011-11-14T17:07:21Z", date: "2011-11-14T17:07:21Z",
quantity: 2, quantity: 2,
total: 90, total: 90,
tip: 0, tip: 0,
type: "tab", type: "tab",
productIDs: ["004", "005"] productIDs: ["004", "005"]
}, },
{ {
date: "2011-11-14T17:22:59Z", date: "2011-11-14T17:22:59Z",
quantity: 2, quantity: 2,
total: 90, total: 90,
tip: 0, tip: 0,
type: "tab", type: "tab",
productIDs: ["001", "002", "004", "005"] productIDs: ["001", "002", "004", "005"]
}, },
{ {
date: "2011-11-14T17:25:45Z", date: "2011-11-14T17:25:45Z",
quantity: 2, quantity: 2,
total: 200, total: 200,
tip: 0, tip: 0,
type: "cash", type: "cash",
productIDs: ["002"] productIDs: ["002"]
}, },
{ {
date: "2011-11-14T17:29:52Z", date: "2011-11-14T17:29:52Z",
quantity: 1, quantity: 1,
total: 200, total: 200,
tip: 100, tip: 100,
type: "visa", type: "visa",
productIDs: ["004"] productIDs: ["004"]
} }
]; ];
function groupReduce(data, valueMap, valueReduce, valueInit) { function groupReduce(data, valueMap, valueReduce, valueInit) {
return _ return _
.reduce( .reduce(
data, data,
(acc, value) => { (acc, value) => {
const k = valueMap(value); const k = valueMap(value);
let r = _.find(acc, o => o.key === k); let r = _.find(acc, o => o.key === k);
if (!r) { if (!r) {
r = { key: k, value: valueInit() }; r = { key: k, value: valueInit() };
acc.push(r); acc.push(r);
} }
r.value = valueReduce(r.value, value); r.value = valueReduce(r.value, value);
return acc; return acc;
}, },
[] []
) )
.sort((a, b) => (a.key < b.key ? -1 : a.key > b.key ? 1 : 0)); .sort((a, b) => (a.key < b.key ? -1 : a.key > b.key ? 1 : 0));
} }
function groupCount(data, map) { function groupCount(data, map) {
return groupReduce(data, map, (p, v) => p + 1, () => 0); return groupReduce(data, map, (p, v) => p + 1, () => 0);
} }
function groupSum(data, map) { function groupSum(data, map) {
return groupReduce(data, map, (p, v) => (p += map(v)), () => 0); return groupReduce(data, map, (p, v) => (p += map(v)), () => 0);
} }
var payments = null; var payments = null;
beforeEach(() => { beforeEach(() => {
payments = crossfilter(someData); payments = crossfilter(someData);
}); });
describe("typedCrossfilter", () => { describe("typedCrossfilter", () => {
test("alloc and free", () => { test("alloc and free", () => {
expect(payments).toBeDefined(); expect(payments).toBeDefined();
expect(payments.size()).toEqual(someData.length); expect(payments.size()).toEqual(someData.length);
expect(payments.all()).toEqual(someData); expect(payments.all()).toEqual(someData);
const quantity = payments.dimension(r => r.quantity, Int32Array); const quantity = payments.dimension(r => r.quantity, Int32Array);
expect(quantity).toBeDefined(); expect(quantity).toBeDefined();
expect(quantity.id()).toBeDefined(); expect(quantity.id()).toBeDefined();
quantity.dispose(); quantity.dispose();
expect(payments.size()).toEqual(someData.length); expect(payments.size()).toEqual(someData.length);
expect(payments.all()).toEqual(someData); expect(payments.all()).toEqual(someData);
}); });
test("filterAll and filterNone", () => { test("filterAll and filterNone", () => {
expect(payments).toBeDefined(); expect(payments).toBeDefined();
const quantity = payments.dimension(r => r.quantity, Int32Array); const quantity = payments.dimension(r => r.quantity, Int32Array);
const tip = payments.dimension(r => r.tip, Float32Array); const tip = payments.dimension(r => r.tip, Float32Array);
const total = payments.dimension(r => r.total, Float32Array); const total = payments.dimension(r => r.total, Float32Array);
const type = payments.dimension(r => r.type, "enum"); const type = payments.dimension(r => r.type, "enum");
expect(quantity).toBeDefined(); expect(quantity).toBeDefined();
expect(tip).toBeDefined(); expect(tip).toBeDefined();
expect(total).toBeDefined(); expect(total).toBeDefined();
expect(type).toBeDefined(); expect(type).toBeDefined();
// initially, all should be filtered // initially, all should be filtered
expect(payments.allFiltered().length).toEqual(payments.size()); expect(payments.allFiltered().length).toEqual(payments.size());
expect(payments.allFiltered()).toEqual(payments.all()); expect(payments.allFiltered()).toEqual(payments.all());
expect(payments.countFiltered()).toEqual(someData.length); expect(payments.countFiltered()).toEqual(someData.length);
// filterAll // filterAll
tip.filterAll(); // should change nothing tip.filterAll(); // should change nothing
expect(payments.allFiltered()).toEqual(payments.all()); expect(payments.allFiltered()).toEqual(payments.all());
expect(payments.countFiltered()).toEqual(someData.length); expect(payments.countFiltered()).toEqual(someData.length);
// ditto // ditto
total.filterAll(); total.filterAll();
expect(payments.allFiltered()).toEqual(payments.all()); expect(payments.allFiltered()).toEqual(payments.all());
expect(payments.countFiltered()).toEqual(someData.length); expect(payments.countFiltered()).toEqual(someData.length);
// filterNone // filterNone
type.filterNone(); type.filterNone();
expect(payments.allFiltered()).toEqual([]); expect(payments.allFiltered()).toEqual([]);
expect(payments.countFiltered()).toEqual(0); expect(payments.countFiltered()).toEqual(0);
quantity.filterNone(); quantity.filterNone();
expect(payments.allFiltered()).toEqual([]); expect(payments.allFiltered()).toEqual([]);
expect(payments.countFiltered()).toEqual(0); expect(payments.countFiltered()).toEqual(0);
// invert the first none; should have no effect because type is // invert the first none; should have no effect because type is
// still not filtered // still not filtered
quantity.filterAll(); quantity.filterAll();
expect(payments.allFiltered()).toEqual([]); expect(payments.allFiltered()).toEqual([]);
expect(payments.countFiltered()).toEqual(0); expect(payments.countFiltered()).toEqual(0);
// filter all of type; should select all // filter all of type; should select all
type.filterAll(); type.filterAll();
expect(payments.allFiltered()).toEqual(payments.all()); expect(payments.allFiltered()).toEqual(payments.all());
expect(payments.countFiltered()).toEqual(payments.size()); expect(payments.countFiltered()).toEqual(payments.size());
}); });
test("filterExact", () => { test("filterExact", () => {
expect(payments).toBeDefined(); expect(payments).toBeDefined();
const quantity = payments.dimension(r => r.quantity, Int32Array); const quantity = payments.dimension(r => r.quantity, Int32Array);
const tip = payments.dimension(r => r.tip, Float32Array); const tip = payments.dimension(r => r.tip, Float32Array);
const total = payments.dimension(r => r.total, Float32Array); const total = payments.dimension(r => r.total, Float32Array);
const type = payments.dimension(r => r.type, "enum"); const type = payments.dimension(r => r.type, "enum");
quantity.filterExact(1); quantity.filterExact(1);
expect(payments.countFiltered()).toEqual( expect(payments.countFiltered()).toEqual(
_.countBy(someData, "quantity")[1] _.countBy(someData, "quantity")[1]
); );
expect(payments.allFiltered()).toEqual(_.filter(someData, { quantity: 1 })); expect(payments.allFiltered()).toEqual(_.filter(someData, { quantity: 1 }));
tip.filterExact(0); tip.filterExact(0);
expect(payments.allFiltered()).toEqual( expect(payments.allFiltered()).toEqual(
_.filter(someData, { tip: 0, quantity: 1 }) _.filter(someData, { tip: 0, quantity: 1 })
); );
type.filterExact("cash"); type.filterExact("cash");
expect(payments.allFiltered()).toEqual( expect(payments.allFiltered()).toEqual(
_.filter(someData, { tip: 0, quantity: 1, type: "cash" }) _.filter(someData, { tip: 0, quantity: 1, type: "cash" })
); );
}); });
test("filterRange", () => { test("filterRange", () => {
expect(payments).toBeDefined(); expect(payments).toBeDefined();
const quantity = payments.dimension(r => r.quantity, Int32Array); const quantity = payments.dimension(r => r.quantity, Int32Array);
const tip = payments.dimension(r => r.tip, Float32Array); const tip = payments.dimension(r => r.tip, Float32Array);
const total = payments.dimension(r => r.total, Float32Array); const total = payments.dimension(r => r.total, Float32Array);
const type = payments.dimension(r => r.type, "enum"); const type = payments.dimension(r => r.type, "enum");
tip.filterRange([0, 91]); tip.filterRange([0, 91]);
expect(payments.allFiltered()).toEqual( expect(payments.allFiltered()).toEqual(
_(someData) _(someData)
.filter(r => r.tip >= 0 && r.tip < 91) .filter(r => r.tip >= 0 && r.tip < 91)
.value() .value()
); );
tip.filterRange([0, 90]); tip.filterRange([0, 90]);
expect(payments.allFiltered()).toEqual( expect(payments.allFiltered()).toEqual(
_(someData) _(someData)
.filter(r => r.tip >= 0 && r.tip < 90) .filter(r => r.tip >= 0 && r.tip < 90)
.value() .value()
); );
tip.filterRange([1, 90]); tip.filterRange([1, 90]);
expect(payments.allFiltered()).toEqual( expect(payments.allFiltered()).toEqual(
_(someData) _(someData)
.filter(r => r.tip >= 1 && r.tip < 91) .filter(r => r.tip >= 1 && r.tip < 91)
.value() .value()
); );
}); });
test("filterEnum", () => { test("filterEnum", () => {
expect(payments).toBeDefined(); expect(payments).toBeDefined();
const quantity = payments.dimension(r => r.quantity, Int32Array); const quantity = payments.dimension(r => r.quantity, Int32Array);
const tip = payments.dimension(r => r.tip, Float32Array); const tip = payments.dimension(r => r.tip, Float32Array);
const total = payments.dimension(r => r.total, Float32Array); const total = payments.dimension(r => r.total, Float32Array);
const type = payments.dimension(r => r.type, "enum"); const type = payments.dimension(r => r.type, "enum");
type.filterEnum(["tab", "cash"]); type.filterEnum(["tab", "cash"]);
expect(payments.allFiltered()).toEqual( expect(payments.allFiltered()).toEqual(
_(someData) _(someData)
.filter(r => r.type === "cash" || r.type === "tab") .filter(r => r.type === "cash" || r.type === "tab")
.value() .value()
); );
tip.filterEnum([0, 100]); tip.filterEnum([0, 100]);
expect(payments.allFiltered()).toEqual( expect(payments.allFiltered()).toEqual(
_(someData) _(someData)
.filter(r => r.type === "cash" || r.type === "tab") .filter(r => r.type === "cash" || r.type === "tab")
.filter(r => r.tip === 0 || r.tip === 100) .filter(r => r.tip === 0 || r.tip === 100)
.value() .value()
); );
}); });
test("more than 32 dimensions", () => { test("more than 32 dimensions", () => {
expect(payments).toBeDefined(); expect(payments).toBeDefined();
const quantity = payments.dimension(r => r.quantity, Int32Array); const quantity = payments.dimension(r => r.quantity, Int32Array);
const tip = payments.dimension(r => r.tip, Float32Array); const tip = payments.dimension(r => r.tip, Float32Array);
const total = payments.dimension(r => r.total, Float32Array); const total = payments.dimension(r => r.total, Float32Array);
const type = payments.dimension(r => r.type, "enum"); const type = payments.dimension(r => r.type, "enum");
// Create a bunch of fake dimensions to ensure we can handle > 32 // Create a bunch of fake dimensions to ensure we can handle > 32
let dimMap = {}; let dimMap = {};
for (let i = 0; i < 65; i++) { for (let i = 0; i < 65; i++) {
dimMap[i] = payments.dimension(r => Math.random(), Float32Array); dimMap[i] = payments.dimension(r => Math.random(), Float32Array);
expect(dimMap[i]).toBeDefined(); expect(dimMap[i]).toBeDefined();
expect(dimMap[i].id()).toBeDefined(); expect(dimMap[i].id()).toBeDefined();
} }
// everything should start as selected/filtered // everything should start as selected/filtered
expect(payments.countFiltered()).toEqual(someData.length); expect(payments.countFiltered()).toEqual(someData.length);
dimMap[0].filterAll(); dimMap[0].filterAll();
dimMap[64].filterAll(); dimMap[64].filterAll();
expect(payments.countFiltered()).toEqual(someData.length); expect(payments.countFiltered()).toEqual(someData.length);
dimMap[33].filterNone(); dimMap[33].filterNone();
expect(payments.allFiltered()).toEqual([]); expect(payments.allFiltered()).toEqual([]);
dimMap[33].filterAll(); dimMap[33].filterAll();
expect(payments.allFiltered()).toEqual(someData); expect(payments.allFiltered()).toEqual(someData);
}); });
test("group, default mapping, default reducer, no filter", () => { test("group, default mapping, default reducer, no filter", () => {
expect(payments).toBeDefined(); expect(payments).toBeDefined();
var quantity = payments.dimension(r => r.quantity, Int32Array); var quantity = payments.dimension(r => r.quantity, Int32Array);
var tip = payments.dimension(r => r.tip, Int32Array); var tip = payments.dimension(r => r.tip, Int32Array);
var type = payments.dimension(r => r.type, "enum"); var type = payments.dimension(r => r.type, "enum");
var total = payments.dimension(r => r.total, Int32Array); var total = payments.dimension(r => r.total, Int32Array);
_.each( _.each(
{ {
tip: tip.group(r => r), tip: tip.group(r => r),
type: type.group(), type: type.group(),
total: total.group(), total: total.group(),
quantity: quantity.group() quantity: quantity.group()
}, },
(grp, k) => { (grp, k) => {
const whatWeExpect = groupCount(someData, v => v[k]); const whatWeExpect = groupCount(someData, v => v[k]);
expect(grp.all()).toEqual(whatWeExpect); expect(grp.all()).toEqual(whatWeExpect);
expect(grp.size()).toEqual(whatWeExpect.length); expect(grp.size()).toEqual(whatWeExpect.length);
expect(grp.dispose()).toEqual(grp); expect(grp.dispose()).toEqual(grp);
} }
); );
}); });
test("group, custom map, default reducer, no filters", () => { test("group, custom map, default reducer, no filters", () => {
expect(payments).toBeDefined(); expect(payments).toBeDefined();
// custom mapping in groups only works for scalar types. Enums do not // custom mapping in groups only works for scalar types. Enums do not
// currently implement it. // currently implement it.
const tip = payments.dimension(r => r.tip, Int32Array); const tip = payments.dimension(r => r.tip, Int32Array);
const totalX10 = payments.dimension(r => r.total * 10, Int32Array); const totalX10 = payments.dimension(r => r.total * 10, Int32Array);
const type = payments.dimension(r => r.type, "enum"); const type = payments.dimension(r => r.type, "enum");
const paymentsByTip_A = tip.group(); const paymentsByTip_A = tip.group();
const paymentsByTip_B = tip.group(r => 10 * r); const paymentsByTip_B = tip.group(r => 10 * r);
const paymentsByType = type.group(); // identity only const paymentsByType = type.group(); // identity only
const paymentsByTotalX10_A = totalX10.group(); const paymentsByTotalX10_A = totalX10.group();
const paymentsByTotalX10_B = totalX10.group(r => r / 10); const paymentsByTotalX10_B = totalX10.group(r => r / 10);
expect(paymentsByTip_A.all()).toEqual(groupCount(someData, v => v.tip)); expect(paymentsByTip_A.all()).toEqual(groupCount(someData, v => v.tip));
expect(paymentsByTip_B.all()).toEqual( expect(paymentsByTip_B.all()).toEqual(
groupCount(someData, v => 10 * v.tip) groupCount(someData, v => 10 * v.tip)
); );
expect(paymentsByType.all()).toEqual(groupCount(someData, v => v.type)); expect(paymentsByType.all()).toEqual(groupCount(someData, v => v.type));
expect(paymentsByTotalX10_A.all()).toEqual( expect(paymentsByTotalX10_A.all()).toEqual(
groupCount(someData, v => 10 * v.total) groupCount(someData, v => 10 * v.total)
); );
expect(paymentsByTotalX10_B.all()).toEqual( expect(paymentsByTotalX10_B.all()).toEqual(
groupCount(someData, v => (10 * v.total) / 10) groupCount(someData, v => (10 * v.total) / 10)
); );
for (let i of [ for (let i of [
paymentsByTip_A, paymentsByTip_A,
paymentsByTip_B, paymentsByTip_B,
paymentsByType, paymentsByType,
paymentsByTotalX10_A, paymentsByTotalX10_A,
paymentsByTotalX10_B, paymentsByTotalX10_B,
tip, tip,
totalX10, totalX10,
type type
]) { ]) {
expect(i.dispose()).toEqual(i); expect(i.dispose()).toEqual(i);
} }
}); });
test("group, default map, custom reducer, no filters", () => { test("group, default map, custom reducer, no filters", () => {
expect(payments).toBeDefined(); expect(payments).toBeDefined();
const total = payments.dimension(r => r.total, Float32Array); const total = payments.dimension(r => r.total, Float32Array);
const type = payments.dimension(r => r.type, "enum"); const type = payments.dimension(r => r.type, "enum");
const paymentsByTotal = total.group(); const paymentsByTotal = total.group();
const paymentsByType = type.group(); const paymentsByType = type.group();
// reduceCount // reduceCount
expect(paymentsByTotal.reduceCount()).toEqual(paymentsByTotal); expect(paymentsByTotal.reduceCount()).toEqual(paymentsByTotal);
expect(paymentsByTotal.all()).toEqual(groupCount(someData, v => v.total)); expect(paymentsByTotal.all()).toEqual(groupCount(someData, v => v.total));
// reduceSum // reduceSum
expect(paymentsByTotal.reduceSum(v => v.total)).toEqual(paymentsByTotal); expect(paymentsByTotal.reduceSum(v => v.total)).toEqual(paymentsByTotal);
expect(paymentsByTotal.all()).toEqual(groupSum(someData, v => v.total)); expect(paymentsByTotal.all()).toEqual(groupSum(someData, v => v.total));
// use custom reducers (my reducers) - count by three, init 1 // use custom reducers (my reducers) - count by three, init 1
expect( expect(
paymentsByTotal.reduce((p, v) => (p += 3), (p, v) => (p -= 3), () => 1) paymentsByTotal.reduce((p, v) => (p += 3), (p, v) => (p -= 3), () => 1)
).toEqual(paymentsByTotal); ).toEqual(paymentsByTotal);
expect(paymentsByTotal.all()).toEqual( expect(paymentsByTotal.all()).toEqual(
groupReduce(someData, v => v.total, (p, v) => p + 3, () => 1) groupReduce(someData, v => v.total, (p, v) => p + 3, () => 1)
); );
for (let i of [paymentsByTotal, paymentsByType, type]) { for (let i of [paymentsByTotal, paymentsByType, type]) {
expect(i.dispose()).toEqual(i); expect(i.dispose()).toEqual(i);
} }
}); });
test("group, default map, default reducer, filters", () => { test("group, default map, default reducer, filters", () => {
// From the docs: // From the docs:
// Note: a grouping intersects the crossfilter's current filters, except for the // Note: a grouping intersects the crossfilter's current filters, except for the
// associated dimension's filter. Thus, group methods consider only records that // associated dimension's filter. Thus, group methods consider only records that
// satisfy every filter except this dimension's filter. So, if the crossfilter of // satisfy every filter except this dimension's filter. So, if the crossfilter of
// payments is filtered by type and total, then group by total only observes the // payments is filtered by type and total, then group by total only observes the
// filter by type. // filter by type.
expect(payments).toBeDefined(); expect(payments).toBeDefined();
const tip = payments.dimension(r => r.tip, Int32Array); const tip = payments.dimension(r => r.tip, Int32Array);
const total = payments.dimension(r => r.total, Int32Array); const total = payments.dimension(r => r.total, Int32Array);
const type = payments.dimension(r => r.type, "enum"); const type = payments.dimension(r => r.type, "enum");
const paymentsByTip = tip.group(); const paymentsByTip = tip.group();
const paymentsByTotal = total.group(); const paymentsByTotal = total.group();
const paymentsByType = type.group(); const paymentsByType = type.group();
// 1. confirm that changing the filter on a dimension does NOT change that // 1. confirm that changing the filter on a dimension does NOT change that
// dimensions groups. // dimensions groups.
{ {
tip.filterAll(), total.filterAll(), type.filterAll(); tip.filterAll(), total.filterAll(), type.filterAll();
let before = _.cloneDeep(paymentsByTip.all()); let before = _.cloneDeep(paymentsByTip.all());
tip.filterExact(0); tip.filterExact(0);
expect(paymentsByTip.all()).toEqual(before); expect(paymentsByTip.all()).toEqual(before);
} }
// 2. confirm that changing a filter on a different dimension DOES change // 2. confirm that changing a filter on a different dimension DOES change
// all other groups. // all other groups.
{ {
tip.filterAll(), total.filterAll(), type.filterAll(); tip.filterAll(), total.filterAll(), type.filterAll();
const before = _.cloneDeep([paymentsByTotal.all(), paymentsByType.all()]); const before = _.cloneDeep([paymentsByTotal.all(), paymentsByType.all()]);
tip.filterExact(0); tip.filterExact(0);
const after = [paymentsByTotal.all(), paymentsByType.all()]; const after = [paymentsByTotal.all(), paymentsByType.all()];
expect(after).not.toEqual(before); expect(after).not.toEqual(before);
expect(after).toEqual([ expect(after).toEqual([
groupReduce( groupReduce(
someData, someData,
v => v.total, v => v.total,
(p, v) => (v.tip !== 0 ? p : p + 1), (p, v) => (v.tip !== 0 ? p : p + 1),
() => 0 () => 0
), ),
groupReduce( groupReduce(
someData, someData,
v => v.type, v => v.type,
(p, v) => (v.tip !== 0 ? p : p + 1), (p, v) => (v.tip !== 0 ? p : p + 1),
() => 0 () => 0
) )
]); ]);
} }
for (let i of [ for (let i of [
paymentsByTip, paymentsByTip,
paymentsByTotal, paymentsByTotal,
paymentsByType, paymentsByType,
tip, tip,
total, total,
type type
]) { ]) {
expect(i.dispose()).toEqual(i); expect(i.dispose()).toEqual(i);
} }
}); });
}); });
+13
View File
@@ -59,6 +59,7 @@
"autoprefixer": "^9.1.1", "autoprefixer": "^9.1.1",
"babel-core": "^6.13.2", "babel-core": "^6.13.2",
"babel-eslint": "^8.2.6", "babel-eslint": "^8.2.6",
"babel-jest": "^23.6.0",
"babel-loader": "^7.1.2", "babel-loader": "^7.1.2",
"babel-plugin-istanbul": "^4.1.6", "babel-plugin-istanbul": "^4.1.6",
"babel-plugin-transform-decorators-legacy": "^1.3.4", "babel-plugin-transform-decorators-legacy": "^1.3.4",
@@ -105,5 +106,17 @@
"**/__tests__/**/?(*.)(spec|test).js?(x)" "**/__tests__/**/?(*.)(spec|test).js?(x)"
], ],
"testURL": "http://localhost/" "testURL": "http://localhost/"
},
"babel": {
"env": {
"test": {
"presets": [
[
"env"
],
"react"
]
}
}
} }
} }
+6 -2
View File
@@ -401,7 +401,11 @@ class ScalarGroup {
this.dimension = dimension; this.dimension = dimension;
// generate group names from dimension values // generate group names from dimension values
this.mapValue = this._map(groupValue, groupValueType, dimension); this.mapValue = this.constructor._map(
groupValue,
groupValueType,
dimension
);
// group index is mapping from data record index to group index // group index is mapping from data record index to group index
this.groupIndex = new Uint32Array(dimension.crossfilter.data.length); this.groupIndex = new Uint32Array(dimension.crossfilter.data.length);
@@ -469,7 +473,7 @@ class ScalarGroup {
// Each item in the range will be remved from `dim`. reduceRemove if it // Each item in the range will be remved from `dim`. reduceRemove if it
// is currently selected. // is currently selected.
const { data, selection } = this.dimension.crossfilter.selection; const { data, selection } = this.dimension.crossfilter;
intv.forEach(rng => { intv.forEach(rng => {
for (let r = rng[0]; r < rng[1]; r += 1) { for (let r = rng[0]; r < rng[1]; r += 1) {
const i = dim.index[r]; const i = dim.index[r];