auspice
Version:
Web app for visualizing pathogen evolution
168 lines (134 loc) • 7.18 kB
text/typescript
/**
* @jest-environment jsdom
*/
/* eslint-disable @typescript-eslint/consistent-type-assertions */
/* eslint-disable @typescript-eslint/ban-ts-comment */
import { configureStore } from '@reduxjs/toolkit';
import rootReducer from "../src/reducers";
import { createStateFromQueryOrJSONs } from "../src/actions/recomputeReduxState";
import { createDatasetJson } from "../src/util/constructDatasetJson";
import { changeColorBy } from "../src/actions/colors.js";
import { changeLayout } from "../src/actions/layout.js";
import { updateVisibleTipsAndBranchThicknesses } from "../src/actions/tree";
import { toggleStreamTree } from "../src/actions/treeStreams";
import { togglePanelDisplay } from "../src/actions/panelDisplay.js";
import { CLEAN_START, CHANGE_DISTANCE_MEASURE, TOGGLE_TRANSMISSION_LINES, CHANGE_GEO_RESOLUTION, CHANGE_BRANCH_LABEL, CHANGE_LANGUAGE, CHANGE_TIP_LABEL_KEY } from "../src/actions/types";
import genericDataset from "./data/generic.json";
/* P.S. provision these (non-git-committed) dataset JSONs via `npm run fetch-test-data` */
// @ts-ignore This will fail type-check if the JSONs haven't been fetched
import ebov2013 from './fetched-jsons/ebola-ebov-2013.json';
function clone<T>(obj: T): T { return JSON.parse(JSON.stringify(obj)); }
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
function createTestStore(originalJson) {
const store = configureStore({
reducer: rootReducer,
middleware: (getDefaultMiddleware) =>
getDefaultMiddleware({ serializableCheck: false, immutableCheck: false }),
});
const cleanStartState = createStateFromQueryOrJSONs({
json: clone(originalJson) as any, query: {}, dispatch: store.dispatch,
});
store.dispatch({ type: CLEAN_START, ...cleanStartState });
return store;
}
type TestStore = ReturnType<typeof createTestStore>;
function recreateDisplayDefaultsJson(store: TestStore): Record<string, any> {
return createDatasetJson(store.getState).meta.display_defaults;
}
describe("Downloaded JSON's display_defaults reflect dynamic redux state (Ebola 2013 tree)", () => {
let store: TestStore;
beforeAll(() => {
jest.spyOn(console, 'error').mockImplementation(() => { });
jest.spyOn(console, 'log').mockImplementation(() => {});
store = createTestStore(ebov2013);
});
afterAll(() => {
jest.restoreAllMocks();
});
it("baseline: without any modifications, display_defaults is as expected", () => {
const display_defaults = recreateDisplayDefaultsJson(store); // round-tripped through redux state
expect(display_defaults.layout).toBeUndefined(); // not in the JSON
expect(display_defaults.color_by).toEqual('division');
});
it("Changing layout sets display_defaults.layout", () => {
store.dispatch(changeLayout({ layout: 'radial' } as any))
expect(recreateDisplayDefaultsJson(store).layout).toEqual("radial");
});
it("Changing color to num_date sets display_defaults.color_by = num_date", () => {
store.dispatch(changeColorBy('num_date'));
expect(recreateDisplayDefaultsJson(store).color_by).toEqual("num_date");
});
it("Changing color to country (Auspice hardcoded default) removes display_defaults.color_by", () => {
store.dispatch(changeColorBy('country'));
expect(recreateDisplayDefaultsJson(store).color_by).toBeUndefined();
});
it("Changing distance_measure to 'div' sets display_defaults.distance_measure = div", () => {
store.dispatch({ type: CHANGE_DISTANCE_MEASURE, data: 'div' });
expect(recreateDisplayDefaultsJson(store).distance_measure).toEqual("div");
});
it("Changing distance_measure back to 'num_date' removes display_defaults.distance_measure", () => {
store.dispatch({ type: CHANGE_DISTANCE_MEASURE, data: 'num_date' });
expect(recreateDisplayDefaultsJson(store).distance_measure).toBeUndefined();
});
it("Changing geographic resolution to 'country' removes display_defaults.geo_resolution", () => {
store.dispatch({ type: CHANGE_GEO_RESOLUTION, data: 'country' });
expect(recreateDisplayDefaultsJson(store).geo_resolution).toBeUndefined();
});
it("Changing geographic resolution back to 'division' sets display_defaults.geo_resolution = division", () => {
store.dispatch({ type: CHANGE_GEO_RESOLUTION, data: 'division' });
expect(recreateDisplayDefaultsJson(store).geo_resolution).toEqual('division');
});
it("Changing branch label to 'aa' sets display_defaults.branch_label = 'aa'", () => {
store.dispatch({ type: CHANGE_BRANCH_LABEL, value: 'aa' });
expect(recreateDisplayDefaultsJson(store).branch_label).toEqual('aa');
});
it("Changing tip label to 'country' sets display_defaults.tip_label = 'country'", () => {
store.dispatch({ type: CHANGE_TIP_LABEL_KEY, key: 'country' });
expect(recreateDisplayDefaultsJson(store).tip_label).toEqual('country');
});
it("Changing tip label to 'country' sets display_defaults.tip_label = 'country'", () => {
store.dispatch({ type: CHANGE_TIP_LABEL_KEY, key: 'country' });
expect(recreateDisplayDefaultsJson(store).tip_label).toEqual('country');
});
it("Changing language to Spanish sets display_defaults.language = 'es'", () => {
store.dispatch({ type: CHANGE_LANGUAGE, data: 'es' });
expect(recreateDisplayDefaultsJson(store).language).toEqual('es');
});
it("Toggling off 'show transmission lines' sets display_defaults.transmission_lines = false", () => {
store.dispatch({ type: TOGGLE_TRANSMISSION_LINES, data: false });
expect(recreateDisplayDefaultsJson(store).transmission_lines).toEqual(false);
});
it("Toggling off map panel removes it from display_defaults", () => {
store.dispatch(togglePanelDisplay('map'));
expect(recreateDisplayDefaultsJson(store).panels).not.toContain('map');
expect(recreateDisplayDefaultsJson(store).panels).toContain('tree');
});
});
/**
* The generic.json has branch labels to test stream trees & label defaults
*/
describe("Downloaded JSON's display_defaults reflect dynamic redux state (generic.json tree)", () => {
let store: TestStore;
beforeAll(() => {
jest.spyOn(console, 'error').mockImplementation(() => { });
store = createTestStore(genericDataset);
});
afterAll(() => {
jest.restoreAllMocks();
});
it("baseline: without any modifications, display_defaults is as expected", () => {
const display_defaults = recreateDisplayDefaultsJson(store); // round-tripped through redux state
expect(display_defaults.branch_label).toEqual('node_name');
expect(display_defaults.label).toEqual('node_name:alpha');
expect(display_defaults.tip_label).toEqual('subtree');
expect(display_defaults.stream_label).toEqual('river');
});
it("Toggling off stream-trees removes display_defaults.stream_label", () => {
store.dispatch(toggleStreamTree());
expect(recreateDisplayDefaultsJson(store).stream_label).toBeUndefined();
});
it("Zooming into node 'echo' sets display_defaults.label = node_name:echo", () => {
store.dispatch(updateVisibleTipsAndBranchThicknesses({ root: [6, undefined] }));
expect(recreateDisplayDefaultsJson(store).label).toEqual('node_name:echo');
});
})