Skip to content

Commit

Permalink
fix tests. use real lib for integration react dev tools. more tests f…
Browse files Browse the repository at this point in the history
…or useCamera
  • Loading branch information
oatkiller committed Feb 7, 2020
1 parent 491df12 commit cd173cd
Show file tree
Hide file tree
Showing 12 changed files with 232 additions and 120 deletions.
3 changes: 2 additions & 1 deletion x-pack/plugins/endpoint/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"react-redux": "^7.1.0"
},
"devDependencies": {
"@types/react-redux": "^7.1.0"
"@types/react-redux": "^7.1.0",
"redux-devtools-extension": "^2.13.8"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { Middleware, Dispatch, MiddlewareAPI } from 'redux';
import { AppAction } from './action';
import { GlobalState } from '../types';

export type Selector<S, R> = (state: S) => R;

export const substateMiddlewareFactory = <Substate>(
selector: Selector<GlobalState, Substate>,
middleware: Middleware<{}, Substate, Dispatch<AppAction>>
): Middleware<{}, GlobalState, Dispatch<AppAction>> => {
return api => {
const substateAPI: MiddlewareAPI<Dispatch<AppAction>, Substate> = {
...api,
getState() {
return selector(api.getState());
},
};
return middleware(substateAPI);
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('inverseProjectionMatrix', () => {
store = createStore(cameraReducer, undefined);
compare = (rasterPosition: [number, number], expectedWorldPosition: [number, number]) => {
// time isn't really relevant as we aren't testing animation
const time = new Date(0);
const time = 0;
const [worldX, worldY] = applyMatrix3(
rasterPosition,
inverseProjectionMatrix(store.getState())(time)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ describe('projectionMatrix', () => {
store = createStore(cameraReducer, undefined);
compare = (worldPosition: [number, number], expectedRasterPosition: [number, number]) => {
// time isn't really relevant as we aren't testing animation
const time = new Date(0);
const time = 0;
const [rasterX, rasterY] = applyMatrix3(
worldPosition,
projectionMatrix(store.getState())(time)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { applyMatrix3 } from '../../lib/vector2';

describe('zooming', () => {
let store: Store<CameraState, CameraAction>;
let time: Date;
let time: number;

const cameraShouldBeBoundBy = (expectedViewableBoundingBox: AABB): [string, () => void] => {
return [
Expand All @@ -31,7 +31,7 @@ describe('zooming', () => {
};
beforeEach(() => {
// Time isn't relevant as we aren't testing animation
time = new Date(0);
time = 0;
store = createStore(cameraReducer, undefined);
});
describe('when the raster size is 300 x 200 pixels', () => {
Expand Down
48 changes: 14 additions & 34 deletions x-pack/plugins/endpoint/public/embeddables/resolver/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,23 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { createStore, StoreEnhancer } from 'redux';
import { ResolverAction } from '../types';
import { createStore, applyMiddleware, Store } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import { ResolverAction, ResolverMiddleware, ResolverState } from '../types';
import { resolverReducer } from './reducer';

export const storeFactory = () => {
/**
* Redux Devtools extension exposes itself via a property on the global object.
* This interface can be used to cast `window` to a type that may expose Redux Devtools.
*/
interface SomethingThatMightHaveReduxDevTools {
__REDUX_DEVTOOLS_EXTENSION__?: (options?: PartialReduxDevToolsOptions) => StoreEnhancer;
}
export const storeFactory = (
...middleware: ResolverMiddleware[]
): { store: Store<ResolverState, ResolverAction> } => {
const actionsBlacklist: Array<ResolverAction['type']> = ['userMovedPointer'];
const composeEnhancers = composeWithDevTools({
name: 'Resolver',
actionsBlacklist,
});

/**
* Some of the options that can be passed when configuring Redux Devtools.
*/
interface PartialReduxDevToolsOptions {
/**
* A name for this store
*/
name?: string;
/**
* A list of action types to ignore. This is used to ignore high frequency events created by a mousemove handler
*/
actionsBlacklist?: readonly string[];
}
const windowWhichMightHaveReduxDevTools = window as SomethingThatMightHaveReduxDevTools;
// Make sure blacklisted action types are valid
const actionsBlacklist: ReadonlyArray<ResolverAction['type']> = ['userMovedPointer'];
const store = createStore(
resolverReducer,
windowWhichMightHaveReduxDevTools.__REDUX_DEVTOOLS_EXTENSION__ &&
windowWhichMightHaveReduxDevTools.__REDUX_DEVTOOLS_EXTENSION__({
name: 'Resolver',
actionsBlacklist,
})
);
const middlewareEnhancer = applyMiddleware(...middleware);

const store = createStore(resolverReducer, composeEnhancers(middlewareEnhancer));
return {
store,
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { ResolverState, FullyEvaluatedSelectors, Selectors } from '../types';
import * as selectors from './selectors';

/**
* Evaluate all the selectors. Some selectors return a function of time, so evaluate those with a timestamp.
*/
export const presenter: (
state: ResolverState,
time: number,
onlyThese?: Set<keyof FullyEvaluatedSelectors>
) => FullyEvaluatedSelectors = (state, time, onlyThese) => {
const result: Partial<Record<
keyof FullyEvaluatedSelectors,
FullyEvaluatedSelectors[keyof FullyEvaluatedSelectors]
>> = {};
for (const key of Object.keys(selectors) as Array<keyof Selectors>) {
if (onlyThese && onlyThese.has(key) === false) {
continue;
}
const selector = selectors[key];
const value = selector(state);
if (typeof value === 'function') {
result[key] = value(time);
} else {
result[key] = value;
}
}
return result as FullyEvaluatedSelectors;
};
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ export const projectionMatrix = composeSelectors(
cameraSelectors.projectionMatrix
);

export const clippingPlanes = composeSelectors(cameraStateSelector, cameraSelectors.clippingPlanes);
export const translation = composeSelectors(cameraStateSelector, cameraSelectors.translation);

/**
* A matrix that when applied to a Vector2 converts it from screen coordinates to world coordinates.
* See https://en.wikipedia.org/wiki/Orthographic_projection
Expand Down
15 changes: 15 additions & 0 deletions x-pack/plugins/endpoint/public/embeddables/resolver/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { Middleware, Dispatch, Store } from 'redux';
import { ResolverAction } from './store/actions';
export { ResolverAction } from './store/actions';
import * as selectors from './store/selectors';

/**
* Redux state for the Resolver feature. Properties on this interface are populated via multiple reducers using redux's `combineReducers`.
Expand Down Expand Up @@ -248,3 +251,15 @@ export interface SideEffectors {
requestAnimationFrame: typeof window.requestAnimationFrame;
ResizeObserver: ResizeObserverConstructor;
}

export type ResolverMiddleware = Middleware<{}, ResolverState, Dispatch<ResolverAction>>;

export type Selectors = typeof selectors;

export type FullyEvaluatedSelectors = {
-readonly [K in keyof Selectors]: ReturnType<Selectors[K]> extends (...args: any[]) => infer R
? R
: ReturnType<Selectors[K]>;
};

export type ResolverStore = Store<ResolverState, ResolverAction>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

export class MockResizeObserver implements ResizeObserver {
static instances: Set<MockResizeObserver> = new Set();
static contentRects: Map<Element, DOMRect> = new Map();
static simulateElementResize: (target: Element, contentRect: DOMRect) => void = (
target,
contentRect
) => {
MockResizeObserver.contentRects.set(target, contentRect);
for (const instance of MockResizeObserver.instances) {
instance.simulateElementResize(target, contentRect);
}
};
static contentRectForElement: (target: Element) => DOMRect = target => {
if (MockResizeObserver.contentRects.has(target)) {
return MockResizeObserver.contentRects.get(target)!;
}
const domRect: DOMRect = {
x: 0,
y: 0,
top: 0,
right: 0,
bottom: 0,
left: 0,
width: 0,
height: 0,
toJSON() {
return this;
},
};
return domRect;
};
constructor(private readonly callback: ResizeObserverCallback) {
MockResizeObserver.instances.add(this);
}
private elements: Set<Element> = new Set();
simulateElementResize(target: Element, contentRect: DOMRect) {
if (this.elements.has(target)) {
const entries: ResizeObserverEntry[] = [{ target, contentRect }];
this.callback(entries, this);
}
}
observe(target: Element) {
this.elements.add(target);
}
unobserve(target: Element) {
this.elements.delete(target);
}
disconnect() {
this.elements.clear();
}
}
Loading

0 comments on commit cd173cd

Please sign in to comment.