diff --git a/__tests__/util/bitArray.test.js b/__tests__/util/bitArray.test.js new file mode 100644 index 00000000..d5ffffba --- /dev/null +++ b/__tests__/util/bitArray.test.js @@ -0,0 +1,137 @@ +// jshint esversion: 6 + +const BitArray = require("../../src/util/typedCrossfilter/bitArray"); +const defaultTestLength = 8; + +describe("default select state", () => { + test("newly created Bitarray should be deselected", () => { + const ba = new BitArray(defaultTestLength); + expect(ba).toBeDefined(); + + for (let i = 0; i < defaultTestLength; i++) { + expect(ba.isSelected(i)).toEqual(false); + } + + const dim = ba.allocDimension(); + expect(dim).toBeDefined(); + for (let i = 0; i < defaultTestLength; i++) { + expect(ba.isSelected(i)).toEqual(false); + } + + ba.freeDimension(dim); + for (let i = 0; i < defaultTestLength; i++) { + expect(ba.isSelected(i)).toEqual(false); + } + }); +}); + +describe("select and deselect", () => { + test("selectAll and deselectAll", () => { + const ba = new BitArray(defaultTestLength); + expect(ba).toBeDefined(); + const dim1 = ba.allocDimension(); + expect(dim1).toBeDefined(); + ba.selectAll(dim1); + + for (let i = 0; i < defaultTestLength; i++) { + expect(ba.isSelected(i)).toEqual(true); + } + + const dim2 = ba.allocDimension(); + expect(dim2).toBeDefined(); + for (let i = 0; i < defaultTestLength; i++) { + expect(ba.isSelected(i)).toEqual(false); + } + + ba.selectAll(dim2); + for (let i = 0; i < defaultTestLength; i++) { + expect(ba.isSelected(i)).toEqual(true); + } + + ba.deselectAll(dim1); + for (let i = 0; i < defaultTestLength; i++) { + expect(ba.isSelected(i)).toEqual(false); + } + + ba.deselectAll(dim2); + for (let i = 0; i < defaultTestLength; i++) { + expect(ba.isSelected(i)).toEqual(false); + } + + ba.selectAll(dim1); + ba.selectAll(dim2); + for (let i = 0; i < defaultTestLength; i++) { + expect(ba.isSelected(i)).toEqual(true); + } + + ba.freeDimension(dim1); + for (let i = 0; i < defaultTestLength; i++) { + expect(ba.isSelected(i)).toEqual(true); + } + + ba.freeDimension(dim2); + for (let i = 0; i < defaultTestLength; i++) { + expect(ba.isSelected(i)).toEqual(false); + } + }); + + test("selectOne and deselectOne", () => { + const ba = new BitArray(defaultTestLength); + expect(ba).toBeDefined(); + const dim = ba.allocDimension(); + expect(dim).toBeDefined(); + + ba.selectOne(dim, 0); + expect(ba.isSelected(0)).toEqual(true); + for (let i = 1; i < defaultTestLength; i++) { + expect(ba.isSelected(i)).toEqual(false); + } + + ba.deselectOne(dim, 0); + for (let i = 0; i < defaultTestLength; i++) { + expect(ba.isSelected(i)).toEqual(false); + } + + ba.selectOne(dim, 1); + expect(ba.isSelected(1)).toEqual(true); + expect(ba.isSelected(0)).toEqual(false); + for (let i = 2; i < defaultTestLength; i++) { + expect(ba.isSelected(i)).toEqual(false); + } + + ba.selectAll(dim); + console.log(ba); + console.log(defaultTestLength - 1); + ba.deselectOne(dim, defaultTestLength - 1); + console.log(ba); + expect(ba.isSelected(defaultTestLength - 1)).toEqual(false); + for (let i = 0; i < defaultTestLength - 1; i++) { + expect(ba.isSelected(i)).toEqual(true); + } + }); +}); + +describe("selectionCount", () => { + test("simple", () => { + const ba = new BitArray(defaultTestLength); + expect(ba).toBeDefined(); + const dim1 = ba.allocDimension(); + expect(dim1).toBeDefined(); + const dim2 = ba.allocDimension(); + expect(dim2).toBeDefined(); + + expect(ba.selectionCount).toEqual(0); + ba.selectAll(dim1); + expect(ba.selectionCount).toEqual(0); + ba.selectAll(dim2); + expect(ba.selectionCount).toEqual(defaultTestLength); + + for (let i = 0; i < defaultTestLength; i++) { + ba.deselectOne(dim1, i); + expect(ba.selectionCount).toEqual(defaultTestLength - i - 1); + } + + ba.freeDimension(dim1); + ba.freeDimension(dim2); + }); +}); diff --git a/__tests__/util/positiveInterval.test.js b/__tests__/util/positiveInterval.test.js new file mode 100644 index 00000000..81c44496 --- /dev/null +++ b/__tests__/util/positiveInterval.test.js @@ -0,0 +1,140 @@ +// jshint esversion: 6 + +const PositiveIntervals = require("../../src/util/typedCrossfilter/positiveIntervals"); + +describe("canonicalize", () => { + test("empty", () => { + expect(PositiveIntervals.canonicalize([])).toEqual([]); + }); + + test("simple, already correct", () => { + expect(PositiveIntervals.canonicalize([[0, 1]])).toEqual([[0, 1]]); + expect(PositiveIntervals.canonicalize([[0, 1], [2, 3]])).toEqual([ + [0, 1], + [2, 3] + ]); + }); + + test("non-canonical, need to be canonicalized", () => { + 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", () => { + expect(PositiveIntervals.union([], [])).toEqual([]); + expect(PositiveIntervals.union([], [[1, 2]])).toEqual([[1, 2]]); + expect(PositiveIntervals.union([], [[1, 2], [3, 4]])).toEqual([ + [1, 2], + [3, 4] + ]); + expect(PositiveIntervals.union([[3, 4]], [])).toEqual([[3, 4]]); + expect(PositiveIntervals.union([[1, 2], [3, 4]], [])).toEqual([ + [1, 2], + [3, 4] + ]); + 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]]); + expect(PositiveIntervals.union([[2, 3]], [[1, 2]])).toEqual([[1, 3]]); + expect(PositiveIntervals.union([[1, 2]], [[3, 4]])).toEqual([ + [1, 2], + [3, 4] + ]); + expect( + PositiveIntervals.union([[1, 2], [3, 4]], [[6, 7], [19, 40]]) + ).toEqual([[1, 2], [3, 4], [6, 7], [19, 40]]); + expect(PositiveIntervals.union([[1, 4]], [[1, 1], [3, 4]])).toEqual([ + [1, 4] + ]); + expect(PositiveIntervals.union([[3, 3]], [[4, 4]])).toEqual([ + [3, 3], + [4, 4] + ]); + }); +}); + +describe("intersection", () => { + test("empty range", () => { + expect(PositiveIntervals.intersection([], [])).toEqual([]); + expect(PositiveIntervals.intersection([], [[1, 2]])).toEqual([]); + expect(PositiveIntervals.intersection([[1, 2]], [])).toEqual([]); + }); + + test("simple", () => { + expect(PositiveIntervals.intersection([[1, 2]], [[2, 3]])).toEqual([]); + expect(PositiveIntervals.intersection([[2, 3]], [[1, 2]])).toEqual([]); + expect(PositiveIntervals.intersection([[1, 10]], [[1, 10]])).toEqual([ + [1, 10] + ]); + expect(PositiveIntervals.intersection([[1, 10]], [[2, 8]])).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([[2, 12]], [[1, 10]])).toEqual([ + [2, 10] + ]); + expect(PositiveIntervals.intersection([[1, 10]], [[1, 8]])).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([[0, 2638]], [[1363, 2638]])).toEqual( + [[1363, 2638]] + ); + expect(PositiveIntervals.intersection([[1, 2]], [[1, 2]])).toEqual([ + [1, 2] + ]); + }); +}); + +describe("difference", () => { + test("empty", () => { + expect(PositiveIntervals.difference([], [])).toEqual([]); + expect(PositiveIntervals.difference([], [[1, 10]])).toEqual([]); + expect(PositiveIntervals.difference([[1, 10]], [])).toEqual([[1, 10]]); + }); + + test("simple", () => { + expect(PositiveIntervals.difference([[1, 2], [3, 4]], [])).toEqual([ + [1, 2], + [3, 4] + ]); + expect(PositiveIntervals.difference([[1, 2], [3, 10]], [[5, 10]])).toEqual([ + [1, 2], + [3, 5] + ]); + expect(PositiveIntervals.difference([[1, 2], [3, 10]], [[0, 5]])).toEqual([ + [5, 10] + ]); + expect( + PositiveIntervals.difference([[0, 2638]], [[0, 1363], [2055, 2638]]) + ).toEqual([[1363, 2055]]); + expect( + PositiveIntervals.difference([[0, 1363], [2055, 2638]], [[0, 2638]]) + ).toEqual([]); + expect(PositiveIntervals.difference([[0, 10]], [[0, 1]])).toEqual([ + [1, 10] + ]); + expect(PositiveIntervals.difference([[0, 10]], [[1, 2]])).toEqual([ + [0, 1], + [2, 10] + ]); + expect(PositiveIntervals.difference([[0, 10]], [[9, 10]])).toEqual([ + [0, 9] + ]); + }); +}); diff --git a/package.json b/package.json index 03568a9c..0698a3cb 100644 --- a/package.json +++ b/package.json @@ -4,12 +4,15 @@ "license": "MIT", "repository": "https://github.com/chanzuckerberg/cellxgene", "scripts": { - "build": "npm run clean && webpack --config configuration/webpack/webpack.config.prod.js", - "dev": "npm run clean && webpack --config configuration/webpack/webpack.config.dev.js", + "build": + "npm run clean && webpack --config configuration/webpack/webpack.config.prod.js", + "dev": + "npm run clean && webpack --config configuration/webpack/webpack.config.dev.js", "clean": "rimraf build", "start": "node server/development.js", "lint": "eslint src", - "prod": "cross-env NODE_ENV=production PORT=3000 node server/production.js" + "prod": "cross-env NODE_ENV=production PORT=3000 node server/production.js", + "test": "jest" }, "engineStrict": true, "engines": { @@ -90,6 +93,7 @@ "gzip-size": "^3.0.0", "html-webpack-inline-source-plugin": "0.0.6", "html-webpack-plugin": "^2.22.0", + "jest": "^23.0.1", "jsdom": "^9.4.1", "json-loader": "^0.5.4", "nyc": "^10.0.0", @@ -106,5 +110,8 @@ "webpack-dev-middleware": "^1.6.1", "webpack-hot-middleware": "^2.12.2", "whatwg-fetch": "^2.0.1" + }, + "jest": { + "testMatch": ["**/__tests__/**/?(*.)(spec|test).js?(x)"] } }