mirror of
https://github.com/chanzuckerberg/cellxgene.git
synced 2026-10-09 17:30:55 +08:00
finish tests for world (#340)
* Create Release_Validation_Recipe.md * nameCreators test and better error handling * add test for createObsDimensionMap * add last set of tests for world module
This commit is contained in:
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
Test cases for nameCreators.js.
|
||||||
|
*/
|
||||||
|
import {
|
||||||
|
layoutDimensionName,
|
||||||
|
obsAnnoDimensionName,
|
||||||
|
diffexpDimensionName,
|
||||||
|
userDefinedDimensionName,
|
||||||
|
makeContinuousDimensionName
|
||||||
|
} from "../../src/util/nameCreators";
|
||||||
|
|
||||||
|
describe("nameCreators", () => {
|
||||||
|
const nameCreators = [
|
||||||
|
layoutDimensionName,
|
||||||
|
obsAnnoDimensionName,
|
||||||
|
diffexpDimensionName,
|
||||||
|
userDefinedDimensionName
|
||||||
|
];
|
||||||
|
|
||||||
|
test("check for namespace isolation", () => {
|
||||||
|
const foo = "foo";
|
||||||
|
nameCreators.forEach(fn => expect(fn(foo)).not.toBe(foo));
|
||||||
|
|
||||||
|
const bar = "bar";
|
||||||
|
nameCreators.forEach(fn => expect(fn(foo)).not.toBe(fn(bar)));
|
||||||
|
|
||||||
|
nameCreators.forEach(fn => {
|
||||||
|
const allOtherFn = nameCreators.filter(elmnt => elmnt !== fn);
|
||||||
|
allOtherFn.forEach(otherFn => expect(fn(foo)).not.toBe(otherFn(foo)));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("check for legal keys", () => {
|
||||||
|
/* need namespace creators to return strings only */
|
||||||
|
nameCreators.forEach(fn => expect(fn("X")).toMatch(/X/));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("makeContinuousDimensionName", () => {
|
||||||
|
test("namespaces", () => {
|
||||||
|
expect(makeContinuousDimensionName({ isObs: true }, "OK")).toMatch(/OK/);
|
||||||
|
expect(makeContinuousDimensionName({ isDiffExp: true }, "OK")).toMatch(
|
||||||
|
/OK/
|
||||||
|
);
|
||||||
|
expect(makeContinuousDimensionName({ isUserDefined: true }, "OK")).toMatch(
|
||||||
|
/OK/
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("error handling", () => {
|
||||||
|
expect(() => makeContinuousDimensionName({}, "oops")).toThrow();
|
||||||
|
expect(() =>
|
||||||
|
makeContinuousDimensionName(
|
||||||
|
{ isObs: false, isDiffExp: false, isUserDefined: false },
|
||||||
|
"oops"
|
||||||
|
)
|
||||||
|
).toThrow();
|
||||||
|
expect(() =>
|
||||||
|
makeContinuousDimensionName({ isObs: true }, "OK")
|
||||||
|
).not.toThrow();
|
||||||
|
expect(() =>
|
||||||
|
makeContinuousDimensionName({ isDiffExp: true }, "OK")
|
||||||
|
).not.toThrow();
|
||||||
|
expect(() =>
|
||||||
|
makeContinuousDimensionName({ isUserDefined: true }, "OK")
|
||||||
|
).not.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -3,15 +3,40 @@ import * as Universe from "../../../src/util/stateManager/universe";
|
|||||||
import * as World from "../../../src/util/stateManager/world";
|
import * as World from "../../../src/util/stateManager/world";
|
||||||
import Crossfilter from "../../../src/util/typedCrossfilter";
|
import Crossfilter from "../../../src/util/typedCrossfilter";
|
||||||
import * as REST from "./sampleResponses";
|
import * as REST from "./sampleResponses";
|
||||||
import { obsAnnoDimensionName } from "../../../src/util/nameCreators";
|
import {
|
||||||
|
obsAnnoDimensionName,
|
||||||
|
layoutDimensionName
|
||||||
|
} from "../../../src/util/nameCreators";
|
||||||
|
import * as kvCache from "../../../src/util/stateManager/keyvalcache";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TODO: endpoints to test:
|
Helper - creates universe, world, corssfilter and dimensionMap from
|
||||||
|
the default REST test response.
|
||||||
createObsDimensionMap(crossfilter, world)
|
|
||||||
subsetVarData(world, universe, varData)
|
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
const defaultBigBang = () => {
|
||||||
|
/* create unverse, world, crossfilter and dimensionMap */
|
||||||
|
/* create universe */
|
||||||
|
const universe = Universe.createUniverseFromRestV02Response(
|
||||||
|
REST.config,
|
||||||
|
REST.schema,
|
||||||
|
REST.annotationsObs,
|
||||||
|
REST.annotationsVar,
|
||||||
|
REST.layoutObs
|
||||||
|
);
|
||||||
|
/* create world */
|
||||||
|
const world = World.createWorldFromEntireUniverse(universe);
|
||||||
|
/* create crossfilter */
|
||||||
|
const crossfilter = Crossfilter(world.obsAnnotations);
|
||||||
|
/* create dimension map */
|
||||||
|
const dimensionMap = World.createObsDimensionMap(crossfilter, world);
|
||||||
|
|
||||||
|
return {
|
||||||
|
universe,
|
||||||
|
world,
|
||||||
|
crossfilter,
|
||||||
|
dimensionMap
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
describe("createWorldFromEntireUniverse", () => {
|
describe("createWorldFromEntireUniverse", () => {
|
||||||
test("create from REST sample", () => {
|
test("create from REST sample", () => {
|
||||||
@@ -55,24 +80,14 @@ describe("createWorldFromEntireUniverse", () => {
|
|||||||
|
|
||||||
describe("createWorldFromCurrentSelection", () => {
|
describe("createWorldFromCurrentSelection", () => {
|
||||||
test("create from REST sample", () => {
|
test("create from REST sample", () => {
|
||||||
/* create universe */
|
const {
|
||||||
const universe = Universe.createUniverseFromRestV02Response(
|
universe,
|
||||||
REST.config,
|
world: originalWorld,
|
||||||
REST.schema,
|
|
||||||
REST.annotationsObs,
|
|
||||||
REST.annotationsVar,
|
|
||||||
REST.layoutObs
|
|
||||||
);
|
|
||||||
/* create world */
|
|
||||||
const originalWorld = World.createWorldFromEntireUniverse(universe);
|
|
||||||
/* create crossfilter */
|
|
||||||
const crossfilter = Crossfilter(originalWorld.obsAnnotations);
|
|
||||||
|
|
||||||
/* fake a selection */
|
|
||||||
const dimensionMap = World.createObsDimensionMap(
|
|
||||||
crossfilter,
|
crossfilter,
|
||||||
originalWorld
|
dimensionMap
|
||||||
);
|
} = defaultBigBang();
|
||||||
|
|
||||||
|
/* mock a selection */
|
||||||
dimensionMap[obsAnnoDimensionName("field1")].filterRange([0, 5]);
|
dimensionMap[obsAnnoDimensionName("field1")].filterRange([0, 5]);
|
||||||
dimensionMap[obsAnnoDimensionName("field3")].filterExact(false);
|
dimensionMap[obsAnnoDimensionName("field3")].filterExact(false);
|
||||||
|
|
||||||
@@ -128,3 +143,87 @@ describe("createWorldFromCurrentSelection", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("createObsDimensionMap", () => {
|
||||||
|
test("when universe eq world", () => {
|
||||||
|
/*
|
||||||
|
check for:
|
||||||
|
- creates a dimension for all obsAnnotations, PLUS X/Y layout
|
||||||
|
- check that dimension typing is sane
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { dimensionMap } = defaultBigBang();
|
||||||
|
|
||||||
|
const schemaByObsName = _.keyBy(REST.schema.schema.annotations.obs, "name");
|
||||||
|
expect(dimensionMap).toBeDefined();
|
||||||
|
REST.annotationsObs.names.forEach(name => {
|
||||||
|
const dim = dimensionMap[obsAnnoDimensionName(name)];
|
||||||
|
const { type } = schemaByObsName[name];
|
||||||
|
if (type === "string" || type === "boolean" || type === "categorical") {
|
||||||
|
expect(dim).toBeInstanceOf(Crossfilter.EnumDimension);
|
||||||
|
} else {
|
||||||
|
expect(dim).toBeInstanceOf(Crossfilter.ScalarDimension);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(dimensionMap[layoutDimensionName("X")]).toBeInstanceOf(
|
||||||
|
Crossfilter.ScalarDimension
|
||||||
|
);
|
||||||
|
expect(dimensionMap[layoutDimensionName("Y")]).toBeInstanceOf(
|
||||||
|
Crossfilter.ScalarDimension
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("subsetVarData", () => {
|
||||||
|
test("when world eq universe", () => {
|
||||||
|
const { universe, world } = defaultBigBang();
|
||||||
|
/* create a mock varData array for subsetting */
|
||||||
|
const sourceVarData = new Float32Array(universe.nObs);
|
||||||
|
|
||||||
|
/* expect literally the same object back */
|
||||||
|
const result = World.subsetVarData(world, universe, sourceVarData);
|
||||||
|
expect(result).toBe(sourceVarData);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("when world neq universe", () => {
|
||||||
|
const { universe, world, crossfilter, dimensionMap } = defaultBigBang();
|
||||||
|
/* create a mock varData array for subsetting */
|
||||||
|
const sourceVarData = Float32Array.from(_.range(universe.nObs));
|
||||||
|
|
||||||
|
/* mock a selection */
|
||||||
|
dimensionMap[obsAnnoDimensionName("field1")].filterRange([0, 5]);
|
||||||
|
dimensionMap[obsAnnoDimensionName("field3")].filterExact(false);
|
||||||
|
|
||||||
|
/* create the world from the selection */
|
||||||
|
const newWorld = World.createWorldFromCurrentSelection(
|
||||||
|
universe,
|
||||||
|
world,
|
||||||
|
crossfilter
|
||||||
|
);
|
||||||
|
|
||||||
|
/* expect a subset */
|
||||||
|
const result = World.subsetVarData(newWorld, universe, sourceVarData);
|
||||||
|
expect(result).not.toBe(sourceVarData);
|
||||||
|
expect(result).toHaveLength(newWorld.nObs);
|
||||||
|
/* check that we have expected source var content */
|
||||||
|
expect(result).toMatchObject(new Float32Array([0, 2]));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("createVarDimension", () => {
|
||||||
|
/* create default universe */
|
||||||
|
const { world, crossfilter } = defaultBigBang();
|
||||||
|
/* create a mock var data cache */
|
||||||
|
const varDataCache = kvCache.set(
|
||||||
|
kvCache.create(),
|
||||||
|
"GENE",
|
||||||
|
Float32Array.from(_.range(world.nObs))
|
||||||
|
);
|
||||||
|
const result = World.createVarDimension(
|
||||||
|
world,
|
||||||
|
varDataCache,
|
||||||
|
crossfilter,
|
||||||
|
"GENE"
|
||||||
|
);
|
||||||
|
expect(result).toBeInstanceOf(Crossfilter.ScalarDimension);
|
||||||
|
});
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ export const makeContinuousDimensionName = (continuousNamespace, key) => {
|
|||||||
name = diffexpDimensionName(key);
|
name = diffexpDimensionName(key);
|
||||||
} else if (continuousNamespace.isUserDefined) {
|
} else if (continuousNamespace.isUserDefined) {
|
||||||
name = userDefinedDimensionName(key);
|
name = userDefinedDimensionName(key);
|
||||||
|
} else {
|
||||||
|
throw new Error("unknown continuous dimension");
|
||||||
}
|
}
|
||||||
|
|
||||||
return name;
|
return name;
|
||||||
|
|||||||
Reference in New Issue
Block a user