From 91a0e8fa9b5cac93d110d2a1d6c263a16463aed0 Mon Sep 17 00:00:00 2001 From: Michael Olorunnisola Date: Mon, 10 Aug 2020 10:37:11 -0400 Subject: [PATCH 1/7] initialized graph control tests --- .../test_utilities/simulator/index.tsx | 30 +++++- .../simulator/mock_resolver.tsx | 15 +-- .../resolver/view/graph_controls.test.tsx | 101 ++++++++++++++++++ .../public/resolver/view/graph_controls.tsx | 1 + 4 files changed, 137 insertions(+), 10 deletions(-) create mode 100644 x-pack/plugins/security_solution/public/resolver/view/graph_controls.test.tsx diff --git a/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx b/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx index cae6a18576ebd..6e64e5a957e3c 100644 --- a/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx +++ b/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx @@ -14,8 +14,9 @@ import { spyMiddlewareFactory } from '../spy_middleware_factory'; import { resolverMiddlewareFactory } from '../../store/middleware'; import { resolverReducer } from '../../store/reducer'; import { MockResolver } from './mock_resolver'; -import { ResolverState, DataAccessLayer, SpyMiddleware } from '../../types'; +import { ResolverState, DataAccessLayer, SpyMiddleware, SideEffectSimulator } from '../../types'; import { ResolverAction } from '../../store/actions'; +import { sideEffectSimulatorFactory } from '../../view/side_effect_simulator_factory'; /** * Test a Resolver instance using jest, enzyme, and a mock data layer. @@ -43,6 +44,11 @@ export class Simulator { * This is used by `debugActions`. */ private readonly spyMiddleware: SpyMiddleware; + /** + * A fake simulator that allows you to explicitly simulate resize events and run animation frames + */ + public readonly sideEffectSimulator: SideEffectSimulator; + constructor({ dataAccessLayer, resolverComponentInstanceID, @@ -87,11 +93,14 @@ export class Simulator { // Used for `KibanaContextProvider` const coreStart: CoreStart = coreMock.createStart(); + this.sideEffectSimulator = sideEffectSimulatorFactory(); + // Render Resolver via the `MockResolver` component, using `enzyme`. this.wrapper = mount( ['history']; /** Pass a resolver store. See `storeFactory` and `mockDataAccessLayer` */ store: Store; + /** + * Pass the side effect simulator which handles animations and resizing. See `sideEffectSimulatorFactory` + */ + sideEffectSimulator: SideEffectSimulator; /** * All the props from `ResolverWithoutStore` can be passed. These aren't defaulted to anything (you might want to test what happens when they aren't present.) */ @@ -66,8 +69,6 @@ export const MockResolver = React.memo((props: MockResolverProps) => { setResolverElement(element); }, []); - const simulator: SideEffectSimulator = useMemo(() => sideEffectSimulatorFactory(), []); - // Resize the Resolver element to match the passed in props. Resolver is size dependent. useEffect(() => { if (resolverElement) { @@ -84,15 +85,15 @@ export const MockResolver = React.memo((props: MockResolverProps) => { return this; }, }; - simulator.controls.simulateElementResize(resolverElement, size); + props.sideEffectSimulator.controls.simulateElementResize(resolverElement, size); } - }, [props.rasterWidth, props.rasterHeight, simulator.controls, resolverElement]); + }, [props.rasterWidth, props.rasterHeight, props.sideEffectSimulator.controls, resolverElement]); return ( - + { + let simulator: Simulator; + let originEntityID: string; + const resolverComponentInstanceID = 'graph-controls-test'; + + beforeEach(async () => { + const { + metadata: { databaseDocumentID, entityIDs }, + dataAccessLayer, + } = oneAncestorTwoChildren(); + + simulator = new Simulator({ + dataAccessLayer, + databaseDocumentID, + resolverComponentInstanceID, + }); + originEntityID = entityIDs.origin; + }); + + it('should load graph controls', () => { + expect(simulator.graphControlElement().length).toBe(1); + }); + + describe('panning', () => { + const originalPositionStyle = { left: '746.93132px', top: '535.5792px' }; + it('should pan west', async () => { + const originNode = simulator.processNodeElements({ entityID: originEntityID }); + expect(originNode.getDOMNode()).toHaveStyle(originalPositionStyle); + + const westPanButton = simulator.graphControlElement().find('[data-test-subj="west-button"]'); + westPanButton.simulate('click'); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + + expect(originNode.getDOMNode()).toHaveStyle({ left: '796.93132px', top: '535.5792px' }); + }); + + it('should pan south', async () => { + const originNode = simulator.processNodeElements({ entityID: originEntityID }); + expect(originNode.getDOMNode()).toHaveStyle(originalPositionStyle); + + const southPanButton = simulator + .graphControlElement() + .find('[data-test-subj="south-button"]'); + southPanButton.simulate('click'); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + + expect(originNode.getDOMNode()).toHaveStyle({ left: '746.93132px', top: '485.5792px' }); + }); + + it('should pan east', async () => { + const originNode = simulator.processNodeElements({ entityID: originEntityID }); + expect(originNode.getDOMNode()).toHaveStyle(originalPositionStyle); + + const eastPanButton = simulator.graphControlElement().find('[data-test-subj="east-button"]'); + eastPanButton.simulate('click'); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + + expect(originNode.getDOMNode()).toHaveStyle({ left: '696.93132px', top: '535.5792px' }); + }); + + it('should pan north', async () => { + const originNode = simulator.processNodeElements({ entityID: originEntityID }); + expect(originNode.getDOMNode()).toHaveStyle(originalPositionStyle); + + const northButton = simulator.graphControlElement().find('[data-test-subj="north-button"]'); + northButton.simulate('click'); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + + expect(originNode.getDOMNode()).toHaveStyle({ left: '746.93132px', top: '585.5792px' }); + }); + + it('should recenter', async () => { + const originNode = simulator.processNodeElements({ entityID: originEntityID }); + const northButton = simulator.graphControlElement().find('[data-test-subj="north-button"]'); + const centerButton = simulator.graphControlElement().find('[data-test-subj="center-button"]'); + + expect(originNode.getDOMNode()).toHaveStyle(originalPositionStyle); + + northButton.simulate('click'); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + + expect(originNode.getDOMNode()).toHaveStyle({ left: '746.93132px', top: '585.5792px' }); + + centerButton.simulate('click'); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + + expect(originNode.getDOMNode()).toHaveStyle(originalPositionStyle); + }); + }); +}); diff --git a/x-pack/plugins/security_solution/public/resolver/view/graph_controls.tsx b/x-pack/plugins/security_solution/public/resolver/view/graph_controls.tsx index c2a7bbaacbf1d..b2632996f9937 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/graph_controls.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/graph_controls.tsx @@ -125,6 +125,7 @@ const GraphControlsComponent = React.memo( className={className} graphControlsBackground={colorMap.graphControlsBackground} graphControlsIconColor={colorMap.graphControls} + data-test-subj="resolver:graph-controls" >
From 9b3b5bbd4ea90c51aef702c989d584294ac5c252 Mon Sep 17 00:00:00 2001 From: Michael Olorunnisola Date: Mon, 10 Aug 2020 12:38:20 -0400 Subject: [PATCH 2/7] added zoom tests --- .../test_utilities/simulator/index.tsx | 2 +- .../resolver/view/graph_controls.test.tsx | 71 ++++++++++++++++++- 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx b/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx index 6e64e5a957e3c..8ebe153b2f776 100644 --- a/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx +++ b/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx @@ -271,7 +271,7 @@ export class Simulator { * Wrapper for the panning and zooming controls */ public graphControlElement(): ReactWrapper { - return this.findInDOM('[data-test-subj="resolver:graph-controls"]'); + return this.domNodes('[data-test-subj="resolver:graph-controls"]'); } /** diff --git a/x-pack/plugins/security_solution/public/resolver/view/graph_controls.test.tsx b/x-pack/plugins/security_solution/public/resolver/view/graph_controls.test.tsx index 4bbffd1fb4735..ee2e5d6aed698 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/graph_controls.test.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/graph_controls.test.tsx @@ -5,7 +5,7 @@ */ import { Simulator } from '../test_utilities/simulator'; -import { oneAncestorTwoChildren } from '../data_access_layer/mocks/one_ancestor_two_children'; +import { noAncestorsTwoChildren } from '../data_access_layer/mocks/no_ancestors_two_children'; import { nudgeAnimationDuration } from '../store/camera/scaling_constants'; import '../test_utilities/extend_jest'; @@ -18,7 +18,7 @@ describe('graph controls', () => { const { metadata: { databaseDocumentID, entityIDs }, dataAccessLayer, - } = oneAncestorTwoChildren(); + } = noAncestorsTwoChildren(); simulator = new Simulator({ dataAccessLayer, @@ -98,4 +98,71 @@ describe('graph controls', () => { expect(originNode.getDOMNode()).toHaveStyle(originalPositionStyle); }); }); + + describe('zoom', () => { + const originalSizeStyle = { width: '360px', height: '120px' }; + describe('buttons', () => { + it('should zoom in', () => { + const originNode = simulator.processNodeElements({ entityID: originEntityID }); + expect(originNode.getDOMNode()).toHaveStyle(originalSizeStyle); + + const zoomInButton = simulator.graphControlElement().find('[data-test-subj="zoom-in"]'); + zoomInButton.simulate('click'); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + + expect(originNode.getDOMNode()).toHaveStyle({ + width: '427.7538290724795px', + height: '142.5846096908265px', + }); + }); + it('should zoom out', () => { + const originNode = simulator.processNodeElements({ entityID: originEntityID }); + expect(originNode.getDOMNode()).toHaveStyle(originalSizeStyle); + + const zoomInButton = simulator.graphControlElement().find('[data-test-subj="zoom-out"]'); + zoomInButton.simulate('click'); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + + expect(originNode.getDOMNode()).toHaveStyle({ + width: '303.0461709275204px', + height: '101.01539030917347px', + }); + }); + }); + + describe('slider', () => { + it('should zoom in', () => { + const originNode = simulator.processNodeElements({ entityID: originEntityID }); + expect(originNode.getDOMNode()).toHaveStyle(originalSizeStyle); + + const zoomSlider = simulator + .graphControlElement() + .find('[data-test-subj="zoom-slider"]') + .last(); + zoomSlider.simulate('change', { target: { value: 0.8 } }); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + + expect(originNode.getDOMNode()).toHaveStyle({ + width: '525.6000000000001px', + height: '175.20000000000005px', + }); + }); + it('should zoom out', () => { + const originNode = simulator.processNodeElements({ entityID: originEntityID }); + expect(originNode.getDOMNode()).toHaveStyle(originalSizeStyle); + + const zoomSlider = simulator + .graphControlElement() + .find('[data-test-subj="zoom-slider"]') + .last(); + zoomSlider.simulate('change', { target: { value: 0.2 } }); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + + expect(originNode.getDOMNode()).toHaveStyle({ + width: '201.60000000000002px', + height: '67.2px', + }); + }); + }); + }); }); From daa259201504805c8938435e3db7d92e2e248898 Mon Sep 17 00:00:00 2001 From: Michael Olorunnisola Date: Mon, 10 Aug 2020 12:45:16 -0400 Subject: [PATCH 3/7] fix comments --- .../public/resolver/test_utilities/simulator/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx b/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx index 8ebe153b2f776..cca5dc212c651 100644 --- a/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx +++ b/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx @@ -45,7 +45,7 @@ export class Simulator { */ private readonly spyMiddleware: SpyMiddleware; /** - * A fake simulator that allows you to explicitly simulate resize events and run animation frames + * Simulator which allows you to explicitly simulate resize events and trigger animation frames */ public readonly sideEffectSimulator: SideEffectSimulator; @@ -193,7 +193,7 @@ export class Simulator { /** * Return an Enzyme ReactWrapper that includes the Related Events host button for a given process node * - * @param entityID The entity ID of åthe proocess node to select in + * @param entityID The entity ID of the proocess node to select in */ public processNodeRelatedEventButton(entityID: string): ReactWrapper { return this.domNodes( From 3c430b438b607c3e687ab302d95381eea2233fb9 Mon Sep 17 00:00:00 2001 From: Michael Olorunnisola Date: Mon, 10 Aug 2020 16:43:51 -0400 Subject: [PATCH 4/7] make graph control tests more explicit --- .../test_utilities/simulator/index.tsx | 4 +- .../resolver/view/graph_controls.test.tsx | 221 ++++++++++++------ .../public/resolver/view/graph_controls.tsx | 24 +- 3 files changed, 172 insertions(+), 77 deletions(-) diff --git a/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx b/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx index cca5dc212c651..68a380387ba54 100644 --- a/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx +++ b/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx @@ -47,7 +47,7 @@ export class Simulator { /** * Simulator which allows you to explicitly simulate resize events and trigger animation frames */ - public readonly sideEffectSimulator: SideEffectSimulator; + private readonly sideEffectSimulator: SideEffectSimulator; constructor({ dataAccessLayer, @@ -186,7 +186,7 @@ export class Simulator { * This manually runs the animation frames tied to a configurable timestamp in the future */ public runAnimationFramesTimeFromNow(time: number = 0) { - this.sideEffectSimulator.controls.time = new Date().getTime() + time; + this.sideEffectSimulator.controls.time = time; this.sideEffectSimulator.controls.provideAnimationFrame(); } diff --git a/x-pack/plugins/security_solution/public/resolver/view/graph_controls.test.tsx b/x-pack/plugins/security_solution/public/resolver/view/graph_controls.test.tsx index ee2e5d6aed698..043845c8f45a5 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/graph_controls.test.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/graph_controls.test.tsx @@ -8,10 +8,12 @@ import { Simulator } from '../test_utilities/simulator'; import { noAncestorsTwoChildren } from '../data_access_layer/mocks/no_ancestors_two_children'; import { nudgeAnimationDuration } from '../store/camera/scaling_constants'; import '../test_utilities/extend_jest'; +import { ReactWrapper } from 'enzyme'; describe('graph controls', () => { let simulator: Simulator; let originEntityID: string; + let originNode: ReactWrapper; const resolverComponentInstanceID = 'graph-controls-test'; beforeEach(async () => { @@ -28,101 +30,183 @@ describe('graph controls', () => { originEntityID = entityIDs.origin; }); - it('should load graph controls', () => { - expect(simulator.graphControlElement().length).toBe(1); + describe('when the graph controls load', () => { + it('should display all cardinal panning buttons and the center button', () => { + const westPanButton = simulator + .graphControlElement() + .find('[data-test-subj="resolver:graph-controls:west-button"]'); + const southPanButton = simulator + .graphControlElement() + .find('[data-test-subj="resolver:graph-controls:west-button"]'); + const eastPanButton = simulator + .graphControlElement() + .find('[data-test-subj="resolver:graph-controls:west-button"]'); + const northPanButton = simulator + .graphControlElement() + .find('[data-test-subj="resolver:graph-controls:west-button"]'); + const centerButton = simulator + .graphControlElement() + .find('[data-test-subj="resolver:graph-controls:center-button"]'); + + expect(westPanButton.length).toBe(1); + expect(southPanButton.length).toBe(1); + expect(eastPanButton.length).toBe(1); + expect(northPanButton.length).toBe(1); + expect(centerButton.length).toBe(1); + }); + + it('should display the zoom buttons and slider', () => { + const zoomInButton = simulator + .graphControlElement() + .find('[data-test-subj="resolver:graph-controls:zoom-in"]'); + const zoomOutButton = simulator + .graphControlElement() + .find('[data-test-subj="resolver:graph-controls:zoom-out"]'); + const zoomSlider = simulator + .graphControlElement() + .find('[data-test-subj="resolver:graph-controls:zoom-slider"]'); + + expect(zoomInButton.length).toBe(1); + expect(zoomOutButton.length).toBe(1); + // Zoom slider is an EUI component that enzyme renders as EUIRangeTrack, EUIRangeSlider, input element + expect(zoomSlider.length).toBeGreaterThan(0); + }); }); describe('panning', () => { const originalPositionStyle = { left: '746.93132px', top: '535.5792px' }; - it('should pan west', async () => { - const originNode = simulator.processNodeElements({ entityID: originEntityID }); - expect(originNode.getDOMNode()).toHaveStyle(originalPositionStyle); - - const westPanButton = simulator.graphControlElement().find('[data-test-subj="west-button"]'); - westPanButton.simulate('click'); - simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); - - expect(originNode.getDOMNode()).toHaveStyle({ left: '796.93132px', top: '535.5792px' }); + beforeEach(() => { + originNode = simulator.processNodeElements({ entityID: originEntityID }); }); - it('should pan south', async () => { - const originNode = simulator.processNodeElements({ entityID: originEntityID }); - expect(originNode.getDOMNode()).toHaveStyle(originalPositionStyle); + describe('when the user has not interacted with panning yet', () => { + it("should show the origin node in it's original position", () => { + expect(originNode.getDOMNode()).toHaveStyle(originalPositionStyle); + }); + }); - const southPanButton = simulator - .graphControlElement() - .find('[data-test-subj="south-button"]'); - southPanButton.simulate('click'); - simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + describe('when the user clicks the west panning button', () => { + let westPanButton: ReactWrapper; + beforeEach(() => { + westPanButton = simulator + .graphControlElement() + .find('[data-test-subj="resolver:graph-controls:west-button"]'); + westPanButton.simulate('click'); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + }); - expect(originNode.getDOMNode()).toHaveStyle({ left: '746.93132px', top: '485.5792px' }); + it('should show the origin node further left on the screen', async () => { + expect(originNode.getDOMNode()).toHaveStyle({ left: '796.93132px', top: '535.5792px' }); + }); }); - it('should pan east', async () => { - const originNode = simulator.processNodeElements({ entityID: originEntityID }); - expect(originNode.getDOMNode()).toHaveStyle(originalPositionStyle); - - const eastPanButton = simulator.graphControlElement().find('[data-test-subj="east-button"]'); - eastPanButton.simulate('click'); - simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + describe('when the user clicks the south panning button', () => { + let southPanButton: ReactWrapper; + beforeEach(() => { + southPanButton = simulator + .graphControlElement() + .find('[data-test-subj="resolver:graph-controls:south-button"]'); + southPanButton.simulate('click'); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + }); - expect(originNode.getDOMNode()).toHaveStyle({ left: '696.93132px', top: '535.5792px' }); + it('should show the origin node lower on the screen', async () => { + expect(originNode.getDOMNode()).toHaveStyle({ left: '746.93132px', top: '485.5792px' }); + }); }); - it('should pan north', async () => { - const originNode = simulator.processNodeElements({ entityID: originEntityID }); - expect(originNode.getDOMNode()).toHaveStyle(originalPositionStyle); - - const northButton = simulator.graphControlElement().find('[data-test-subj="north-button"]'); - northButton.simulate('click'); - simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + describe('when the user clicks the east panning button', () => { + let eastPanButton: ReactWrapper; + beforeEach(() => { + eastPanButton = simulator + .graphControlElement() + .find('[data-test-subj="resolver:graph-controls:east-button"]'); + eastPanButton.simulate('click'); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + }); - expect(originNode.getDOMNode()).toHaveStyle({ left: '746.93132px', top: '585.5792px' }); + it('should show the origin node further right on the screen', async () => { + expect(originNode.getDOMNode()).toHaveStyle({ left: '696.93132px', top: '535.5792px' }); + }); }); - it('should recenter', async () => { - const originNode = simulator.processNodeElements({ entityID: originEntityID }); - const northButton = simulator.graphControlElement().find('[data-test-subj="north-button"]'); - const centerButton = simulator.graphControlElement().find('[data-test-subj="center-button"]'); - - expect(originNode.getDOMNode()).toHaveStyle(originalPositionStyle); + describe('when the user clicks the north panning button', () => { + let northPanButton: ReactWrapper; + beforeEach(() => { + northPanButton = simulator + .graphControlElement() + .find('[data-test-subj="resolver:graph-controls:north-button"]'); + northPanButton.simulate('click'); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + }); - northButton.simulate('click'); - simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + it('should show the origin node higher on the screen', async () => { + expect(originNode.getDOMNode()).toHaveStyle({ left: '746.93132px', top: '585.5792px' }); + }); + }); - expect(originNode.getDOMNode()).toHaveStyle({ left: '746.93132px', top: '585.5792px' }); + describe('when the user clicks the center panning button', () => { + let northPanButton: ReactWrapper; + let centerButton: ReactWrapper; + beforeEach(() => { + northPanButton = simulator + .graphControlElement() + .find('[data-test-subj="resolver:graph-controls:north-button"]'); + centerButton = simulator + .graphControlElement() + .find('[data-test-subj="resolver:graph-controls:center-button"]'); - centerButton.simulate('click'); - simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + northPanButton.simulate('click'); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + centerButton.simulate('click'); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + }); - expect(originNode.getDOMNode()).toHaveStyle(originalPositionStyle); + it("should return the origin node to it's original position", async () => { + expect(originNode.getDOMNode()).toHaveStyle(originalPositionStyle); + }); }); }); - describe('zoom', () => { + describe('zooming', () => { const originalSizeStyle = { width: '360px', height: '120px' }; - describe('buttons', () => { - it('should zoom in', () => { - const originNode = simulator.processNodeElements({ entityID: originEntityID }); + beforeEach(() => { + originNode = simulator.processNodeElements({ entityID: originEntityID }); + }); + + describe('when the user has not interacted with the zoom buttons or slider yet', () => { + it('should show the origin node as larger on the screen', () => { expect(originNode.getDOMNode()).toHaveStyle(originalSizeStyle); + }); + }); - const zoomInButton = simulator.graphControlElement().find('[data-test-subj="zoom-in"]'); + describe('when the zoom in button is clicked', () => { + beforeEach(() => { + const zoomInButton = simulator + .graphControlElement() + .find('[data-test-subj="resolver:graph-controls:zoom-in"]'); zoomInButton.simulate('click'); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + }); + it('should show the origin node as larger on the screen', () => { expect(originNode.getDOMNode()).toHaveStyle({ width: '427.7538290724795px', height: '142.5846096908265px', }); }); - it('should zoom out', () => { - const originNode = simulator.processNodeElements({ entityID: originEntityID }); - expect(originNode.getDOMNode()).toHaveStyle(originalSizeStyle); + }); - const zoomInButton = simulator.graphControlElement().find('[data-test-subj="zoom-out"]'); - zoomInButton.simulate('click'); + describe('when the zoom out button is clicked', () => { + beforeEach(() => { + const zoomOutButton = simulator + .graphControlElement() + .find('[data-test-subj="resolver:graph-controls:zoom-out"]'); + zoomOutButton.simulate('click'); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + }); + it('should show the origin node as smaller on the screen', () => { expect(originNode.getDOMNode()).toHaveStyle({ width: '303.0461709275204px', height: '101.01539030917347px', @@ -130,34 +214,37 @@ describe('graph controls', () => { }); }); - describe('slider', () => { - it('should zoom in', () => { - const originNode = simulator.processNodeElements({ entityID: originEntityID }); + describe('when the slider is moved upwards', () => { + beforeEach(() => { expect(originNode.getDOMNode()).toHaveStyle(originalSizeStyle); const zoomSlider = simulator .graphControlElement() - .find('[data-test-subj="zoom-slider"]') + .find('[data-test-subj="resolver:graph-controls:zoom-slider"]') .last(); zoomSlider.simulate('change', { target: { value: 0.8 } }); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + }); + it('should show the origin node as large on the screen', () => { expect(originNode.getDOMNode()).toHaveStyle({ width: '525.6000000000001px', height: '175.20000000000005px', }); }); - it('should zoom out', () => { - const originNode = simulator.processNodeElements({ entityID: originEntityID }); - expect(originNode.getDOMNode()).toHaveStyle(originalSizeStyle); + }); + describe('when the slider is moved downwards', () => { + beforeEach(() => { const zoomSlider = simulator .graphControlElement() - .find('[data-test-subj="zoom-slider"]') - .last(); + .find('[data-test-subj="resolver:graph-controls:zoom-slider"]') + .last(); // The last element rendered is the actual slider input element zoomSlider.simulate('change', { target: { value: 0.2 } }); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + }); + it('should show the origin node as smaller on the screen', () => { expect(originNode.getDOMNode()).toHaveStyle({ width: '201.60000000000002px', height: '67.2px', diff --git a/x-pack/plugins/security_solution/public/resolver/view/graph_controls.tsx b/x-pack/plugins/security_solution/public/resolver/view/graph_controls.tsx index b2632996f9937..610deef07775b 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/graph_controls.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/graph_controls.tsx @@ -131,7 +131,7 @@ const GraphControlsComponent = React.memo(
- - From e788b45308be7b666babedf1ec6ba8b8979270e7 Mon Sep 17 00:00:00 2001 From: Michael Olorunnisola Date: Tue, 11 Aug 2020 14:55:12 -0400 Subject: [PATCH 5/7] refactor to use domNodes and map --- .../test_utilities/simulator/index.tsx | 55 +++++++- .../resolver/view/graph_controls.test.tsx | 128 ++++++------------ 2 files changed, 92 insertions(+), 91 deletions(-) diff --git a/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx b/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx index 68a380387ba54..d195a80da3832 100644 --- a/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx +++ b/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx @@ -268,10 +268,59 @@ export class Simulator { } /** - * Wrapper for the panning and zooming controls + * Wrapper for the west panning button */ - public graphControlElement(): ReactWrapper { - return this.domNodes('[data-test-subj="resolver:graph-controls"]'); + public westPanElement(): ReactWrapper { + return this.domNodes('[data-test-subj="resolver:graph-controls:west-button"]'); + } + + /** + * Wrapper for the south panning button + */ + public southPanElement(): ReactWrapper { + return this.domNodes('[data-test-subj="resolver:graph-controls:south-button"]'); + } + + /** + * Wrapper for the east panning button + */ + public eastPanElement(): ReactWrapper { + return this.domNodes('[data-test-subj="resolver:graph-controls:east-button"]'); + } + + /** + * Wrapper for the north panning button + */ + public northPanElement(): ReactWrapper { + return this.domNodes('[data-test-subj="resolver:graph-controls:north-button"]'); + } + + /** + * Wrapper for the center panning button + */ + public centerPanElement(): ReactWrapper { + return this.domNodes('[data-test-subj="resolver:graph-controls:center-button"]'); + } + + /** + * Wrapper for the zoom in button + */ + public zoomInElement(): ReactWrapper { + return this.domNodes('[data-test-subj="resolver:graph-controls:zoom-in"]'); + } + + /** + * Wrapper for the zoom out button + */ + public zoomOutElement(): ReactWrapper { + return this.domNodes('[data-test-subj="resolver:graph-controls:zoom-out"]'); + } + + /** + * Wrapper for the zoom slider button + */ + public zoomSliderElement(): ReactWrapper { + return this.domNodes('[data-test-subj="resolver:graph-controls:zoom-slider"]'); } /** diff --git a/x-pack/plugins/security_solution/public/resolver/view/graph_controls.test.tsx b/x-pack/plugins/security_solution/public/resolver/view/graph_controls.test.tsx index 043845c8f45a5..9c484d936f58c 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/graph_controls.test.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/graph_controls.test.tsx @@ -31,45 +31,36 @@ describe('graph controls', () => { }); describe('when the graph controls load', () => { - it('should display all cardinal panning buttons and the center button', () => { - const westPanButton = simulator - .graphControlElement() - .find('[data-test-subj="resolver:graph-controls:west-button"]'); - const southPanButton = simulator - .graphControlElement() - .find('[data-test-subj="resolver:graph-controls:west-button"]'); - const eastPanButton = simulator - .graphControlElement() - .find('[data-test-subj="resolver:graph-controls:west-button"]'); - const northPanButton = simulator - .graphControlElement() - .find('[data-test-subj="resolver:graph-controls:west-button"]'); - const centerButton = simulator - .graphControlElement() - .find('[data-test-subj="resolver:graph-controls:center-button"]'); - - expect(westPanButton.length).toBe(1); - expect(southPanButton.length).toBe(1); - expect(eastPanButton.length).toBe(1); - expect(northPanButton.length).toBe(1); - expect(centerButton.length).toBe(1); - }); - - it('should display the zoom buttons and slider', () => { - const zoomInButton = simulator - .graphControlElement() - .find('[data-test-subj="resolver:graph-controls:zoom-in"]'); - const zoomOutButton = simulator - .graphControlElement() - .find('[data-test-subj="resolver:graph-controls:zoom-out"]'); - const zoomSlider = simulator - .graphControlElement() - .find('[data-test-subj="resolver:graph-controls:zoom-slider"]'); - - expect(zoomInButton.length).toBe(1); - expect(zoomOutButton.length).toBe(1); - // Zoom slider is an EUI component that enzyme renders as EUIRangeTrack, EUIRangeSlider, input element - expect(zoomSlider.length).toBeGreaterThan(0); + it('should display all cardinal panning buttons and the center button', async () => { + await expect( + simulator.map(() => ({ + westPanButton: simulator.westPanElement().length, + southPanButton: simulator.southPanElement().length, + eastPanButton: simulator.eastPanElement().length, + northPanButton: simulator.northPanElement().length, + centerButton: simulator.centerPanElement().length, + })) + ).toYieldEqualTo({ + westPanButton: 1, + southPanButton: 1, + eastPanButton: 1, + northPanButton: 1, + centerButton: 1, + }); + }); + + it('should display the zoom buttons and slider', async () => { + await expect( + simulator.map(() => ({ + zoomInButton: simulator.zoomInElement().length, + zoomOutButton: simulator.zoomOutElement().length, + zoomSlider: simulator.zoomSliderElement().length, + })) + ).toYieldEqualTo({ + zoomInButton: 1, + zoomOutButton: 1, + zoomSlider: 1, + }); }); }); @@ -86,12 +77,8 @@ describe('graph controls', () => { }); describe('when the user clicks the west panning button', () => { - let westPanButton: ReactWrapper; beforeEach(() => { - westPanButton = simulator - .graphControlElement() - .find('[data-test-subj="resolver:graph-controls:west-button"]'); - westPanButton.simulate('click'); + simulator.westPanElement().simulate('click'); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); }); @@ -101,12 +88,8 @@ describe('graph controls', () => { }); describe('when the user clicks the south panning button', () => { - let southPanButton: ReactWrapper; beforeEach(() => { - southPanButton = simulator - .graphControlElement() - .find('[data-test-subj="resolver:graph-controls:south-button"]'); - southPanButton.simulate('click'); + simulator.southPanElement().simulate('click'); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); }); @@ -116,12 +99,8 @@ describe('graph controls', () => { }); describe('when the user clicks the east panning button', () => { - let eastPanButton: ReactWrapper; beforeEach(() => { - eastPanButton = simulator - .graphControlElement() - .find('[data-test-subj="resolver:graph-controls:east-button"]'); - eastPanButton.simulate('click'); + simulator.eastPanElement().simulate('click'); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); }); @@ -131,12 +110,8 @@ describe('graph controls', () => { }); describe('when the user clicks the north panning button', () => { - let northPanButton: ReactWrapper; beforeEach(() => { - northPanButton = simulator - .graphControlElement() - .find('[data-test-subj="resolver:graph-controls:north-button"]'); - northPanButton.simulate('click'); + simulator.northPanElement().simulate('click'); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); }); @@ -146,19 +121,10 @@ describe('graph controls', () => { }); describe('when the user clicks the center panning button', () => { - let northPanButton: ReactWrapper; - let centerButton: ReactWrapper; beforeEach(() => { - northPanButton = simulator - .graphControlElement() - .find('[data-test-subj="resolver:graph-controls:north-button"]'); - centerButton = simulator - .graphControlElement() - .find('[data-test-subj="resolver:graph-controls:center-button"]'); - - northPanButton.simulate('click'); + simulator.northPanElement().simulate('click'); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); - centerButton.simulate('click'); + simulator.centerPanElement().simulate('click'); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); }); @@ -182,10 +148,7 @@ describe('graph controls', () => { describe('when the zoom in button is clicked', () => { beforeEach(() => { - const zoomInButton = simulator - .graphControlElement() - .find('[data-test-subj="resolver:graph-controls:zoom-in"]'); - zoomInButton.simulate('click'); + simulator.zoomInElement().simulate('click'); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); }); @@ -199,10 +162,7 @@ describe('graph controls', () => { describe('when the zoom out button is clicked', () => { beforeEach(() => { - const zoomOutButton = simulator - .graphControlElement() - .find('[data-test-subj="resolver:graph-controls:zoom-out"]'); - zoomOutButton.simulate('click'); + simulator.zoomOutElement().simulate('click'); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); }); @@ -218,11 +178,7 @@ describe('graph controls', () => { beforeEach(() => { expect(originNode.getDOMNode()).toHaveStyle(originalSizeStyle); - const zoomSlider = simulator - .graphControlElement() - .find('[data-test-subj="resolver:graph-controls:zoom-slider"]') - .last(); - zoomSlider.simulate('change', { target: { value: 0.8 } }); + simulator.zoomSliderElement().simulate('change', { target: { value: 0.8 } }); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); }); @@ -236,11 +192,7 @@ describe('graph controls', () => { describe('when the slider is moved downwards', () => { beforeEach(() => { - const zoomSlider = simulator - .graphControlElement() - .find('[data-test-subj="resolver:graph-controls:zoom-slider"]') - .last(); // The last element rendered is the actual slider input element - zoomSlider.simulate('change', { target: { value: 0.2 } }); + simulator.zoomSliderElement().simulate('change', { target: { value: 0.2 } }); simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); }); From cf33fd52121a3f15fe1da543b1224b6d8457c89d Mon Sep 17 00:00:00 2001 From: Michael Olorunnisola Date: Tue, 11 Aug 2020 14:58:44 -0400 Subject: [PATCH 6/7] slider, not button --- .../public/resolver/test_utilities/simulator/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx b/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx index d195a80da3832..85b283a76cfa9 100644 --- a/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx +++ b/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx @@ -317,7 +317,7 @@ export class Simulator { } /** - * Wrapper for the zoom slider button + * Wrapper for the zoom slider */ public zoomSliderElement(): ReactWrapper { return this.domNodes('[data-test-subj="resolver:graph-controls:zoom-slider"]'); From 3de7be9429a6f3fa801dbf6621b9232958e761ad Mon Sep 17 00:00:00 2001 From: oatkiller Date: Wed, 12 Aug 2020 12:44:20 -0400 Subject: [PATCH 7/7] Add .toYieldObjectEqualTo matcher. resolve graph control test wrappers before use. use yield-equal-to pattern in graph control tests. change graph control spec language --- .../resolver/test_utilities/extend_jest.ts | 65 +++++ .../test_utilities/simulator/index.tsx | 2 +- .../resolver/view/graph_controls.test.tsx | 272 +++++++++--------- 3 files changed, 209 insertions(+), 130 deletions(-) diff --git a/x-pack/plugins/security_solution/public/resolver/test_utilities/extend_jest.ts b/x-pack/plugins/security_solution/public/resolver/test_utilities/extend_jest.ts index 9fc7af38beb42..df8f32d15a7ab 100644 --- a/x-pack/plugins/security_solution/public/resolver/test_utilities/extend_jest.ts +++ b/x-pack/plugins/security_solution/public/resolver/test_utilities/extend_jest.ts @@ -17,6 +17,7 @@ declare global { namespace jest { interface Matchers { toYieldEqualTo(expectedYield: T extends AsyncIterable ? E : never): Promise; + toYieldObjectEqualTo(expectedYield: unknown): Promise; } } } @@ -57,6 +58,70 @@ expect.extend({ } } + // Use `pass` as set in the above loop (or initialized to `false`) + // See https://jestjs.io/docs/en/expect#custom-matchers-api and https://jestjs.io/docs/en/expect#thisutils + const message = pass + ? () => + `${this.utils.matcherHint(matcherName, undefined, undefined, options)}\n\n` + + `Expected: not ${this.utils.printExpected(expected)}\n${ + this.utils.stringify(expected) !== this.utils.stringify(received[received.length - 1]!) + ? `Received: ${this.utils.printReceived(received[received.length - 1])}` + : '' + }` + : () => + `${this.utils.matcherHint(matcherName, undefined, undefined, options)}\n\nCompared ${ + received.length + } yields.\n\n${received + .map( + (next, index) => + `yield ${index + 1}:\n\n${this.utils.printDiffOrStringify( + expected, + next, + 'Expected', + 'Received', + this.expand + )}` + ) + .join(`\n\n`)}`; + + return { message, pass }; + }, + /** + * A custom matcher that takes an async generator and compares each value it yields to an expected value. + * This uses the same equality logic as `toMatchObject`. + * If any yielded value equals the expected value, the matcher will pass. + * If the generator ends with none of the yielded values matching, it will fail. + */ + async toYieldObjectEqualTo( + this: jest.MatcherContext, + receivedIterable: AsyncIterable, + expected: T + ): Promise<{ pass: boolean; message: () => string }> { + // Used in printing out the pass or fail message + const matcherName = 'toSometimesYieldEqualTo'; + const options: jest.MatcherHintOptions = { + comment: 'deep equality with any yielded value', + isNot: this.isNot, + promise: this.promise, + }; + // The last value received: Used in printing the message + const received: T[] = []; + + // Set to true if the test passes. + let pass: boolean = false; + + // Async iterate over the iterable + for await (const next of receivedIterable) { + // keep track of all received values. Used in pass and fail messages + received.push(next); + // Use deep equals to compare the value to the expected value + if ((this.equals(next, expected), [this.utils.iterableEquality, this.utils.subsetEquality])) { + // If the value is equal, break + pass = true; + break; + } + } + // Use `pass` as set in the above loop (or initialized to `false`) // See https://jestjs.io/docs/en/expect#custom-matchers-api and https://jestjs.io/docs/en/expect#thisutils const message = pass diff --git a/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx b/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx index 85b283a76cfa9..6607056b2a4bc 100644 --- a/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx +++ b/x-pack/plugins/security_solution/public/resolver/test_utilities/simulator/index.tsx @@ -370,7 +370,7 @@ export class Simulator { public async resolveWrapper( wrapperFactory: () => ReactWrapper, predicate: (wrapper: ReactWrapper) => boolean = (wrapper) => wrapper.length > 0 - ): Promise { + ): Promise { for await (const wrapper of this.map(wrapperFactory)) { if (predicate(wrapper)) { return wrapper; diff --git a/x-pack/plugins/security_solution/public/resolver/view/graph_controls.test.tsx b/x-pack/plugins/security_solution/public/resolver/view/graph_controls.test.tsx index 9c484d936f58c..3b66f6af87cb4 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/graph_controls.test.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/graph_controls.test.tsx @@ -8,14 +8,22 @@ import { Simulator } from '../test_utilities/simulator'; import { noAncestorsTwoChildren } from '../data_access_layer/mocks/no_ancestors_two_children'; import { nudgeAnimationDuration } from '../store/camera/scaling_constants'; import '../test_utilities/extend_jest'; -import { ReactWrapper } from 'enzyme'; -describe('graph controls', () => { +describe('graph controls: when relsover is loaded with an origin node', () => { let simulator: Simulator; let originEntityID: string; - let originNode: ReactWrapper; + let originNodeStyle: () => AsyncIterable; const resolverComponentInstanceID = 'graph-controls-test'; + const originalPositionStyle: Readonly<{ left: string; top: string }> = { + left: '746.93132px', + top: '535.5792px', + }; + const originalSizeStyle: Readonly<{ width: string; height: string }> = { + width: '360px', + height: '120px', + }; + beforeEach(async () => { const { metadata: { databaseDocumentID, entityIDs }, @@ -28,179 +36,185 @@ describe('graph controls', () => { resolverComponentInstanceID, }); originEntityID = entityIDs.origin; - }); - - describe('when the graph controls load', () => { - it('should display all cardinal panning buttons and the center button', async () => { - await expect( - simulator.map(() => ({ - westPanButton: simulator.westPanElement().length, - southPanButton: simulator.southPanElement().length, - eastPanButton: simulator.eastPanElement().length, - northPanButton: simulator.northPanElement().length, - centerButton: simulator.centerPanElement().length, - })) - ).toYieldEqualTo({ - westPanButton: 1, - southPanButton: 1, - eastPanButton: 1, - northPanButton: 1, - centerButton: 1, - }); - }); - it('should display the zoom buttons and slider', async () => { - await expect( - simulator.map(() => ({ - zoomInButton: simulator.zoomInElement().length, - zoomOutButton: simulator.zoomOutElement().length, - zoomSlider: simulator.zoomSliderElement().length, - })) - ).toYieldEqualTo({ - zoomInButton: 1, - zoomOutButton: 1, - zoomSlider: 1, + originNodeStyle = () => + simulator.map(() => { + const wrapper = simulator.processNodeElements({ entityID: originEntityID }); + // `getDOMNode` can only be called on a wrapper of a single node: https://enzymejs.github.io/enzyme/docs/api/ReactWrapper/getDOMNode.html + if (wrapper.length === 1) { + return wrapper.getDOMNode().style; + } + return null; }); - }); }); - describe('panning', () => { - const originalPositionStyle = { left: '746.93132px', top: '535.5792px' }; - beforeEach(() => { - originNode = simulator.processNodeElements({ entityID: originEntityID }); + it('should display all cardinal panning buttons and the center button', async () => { + await expect( + simulator.map(() => ({ + westPanButton: simulator.westPanElement().length, + southPanButton: simulator.southPanElement().length, + eastPanButton: simulator.eastPanElement().length, + northPanButton: simulator.northPanElement().length, + centerButton: simulator.centerPanElement().length, + })) + ).toYieldEqualTo({ + westPanButton: 1, + southPanButton: 1, + eastPanButton: 1, + northPanButton: 1, + centerButton: 1, }); + }); - describe('when the user has not interacted with panning yet', () => { - it("should show the origin node in it's original position", () => { - expect(originNode.getDOMNode()).toHaveStyle(originalPositionStyle); - }); + it('should display the zoom buttons and slider', async () => { + await expect( + simulator.map(() => ({ + zoomInButton: simulator.zoomInElement().length, + zoomOutButton: simulator.zoomOutElement().length, + zoomSlider: simulator.zoomSliderElement().length, + })) + ).toYieldEqualTo({ + zoomInButton: 1, + zoomOutButton: 1, + zoomSlider: 1, }); + }); - describe('when the user clicks the west panning button', () => { - beforeEach(() => { - simulator.westPanElement().simulate('click'); - simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); - }); + it("should show the origin node in it's original position", async () => { + await expect(originNodeStyle()).toYieldObjectEqualTo(originalPositionStyle); + }); - it('should show the origin node further left on the screen', async () => { - expect(originNode.getDOMNode()).toHaveStyle({ left: '796.93132px', top: '535.5792px' }); - }); + describe('when the user clicks the west panning button', () => { + beforeEach(async () => { + (await simulator.resolveWrapper(() => simulator.westPanElement()))!.simulate('click'); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); }); - describe('when the user clicks the south panning button', () => { - beforeEach(() => { - simulator.southPanElement().simulate('click'); - simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); - }); - - it('should show the origin node lower on the screen', async () => { - expect(originNode.getDOMNode()).toHaveStyle({ left: '746.93132px', top: '485.5792px' }); + it('should show the origin node further left on the screen', async () => { + await expect(originNodeStyle()).toYieldObjectEqualTo({ + left: '796.93132px', + top: '535.5792px', }); }); + }); - describe('when the user clicks the east panning button', () => { - beforeEach(() => { - simulator.eastPanElement().simulate('click'); - simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); - }); + describe('when the user clicks the south panning button', () => { + beforeEach(async () => { + (await simulator.resolveWrapper(() => simulator.southPanElement()))!.simulate('click'); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + }); - it('should show the origin node further right on the screen', async () => { - expect(originNode.getDOMNode()).toHaveStyle({ left: '696.93132px', top: '535.5792px' }); + it('should show the origin node lower on the screen', async () => { + await expect(originNodeStyle()).toYieldObjectEqualTo({ + left: '746.93132px', + top: '485.5792px', }); }); + }); - describe('when the user clicks the north panning button', () => { - beforeEach(() => { - simulator.northPanElement().simulate('click'); - simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); - }); + describe('when the user clicks the east panning button', () => { + beforeEach(async () => { + (await simulator.resolveWrapper(() => simulator.eastPanElement()))!.simulate('click'); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + }); - it('should show the origin node higher on the screen', async () => { - expect(originNode.getDOMNode()).toHaveStyle({ left: '746.93132px', top: '585.5792px' }); + it('should show the origin node further right on the screen', async () => { + await expect(originNodeStyle()).toYieldObjectEqualTo({ + left: '696.93132px', + top: '535.5792px', }); }); + }); - describe('when the user clicks the center panning button', () => { - beforeEach(() => { - simulator.northPanElement().simulate('click'); - simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); - simulator.centerPanElement().simulate('click'); - simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); - }); + describe('when the user clicks the north panning button', () => { + beforeEach(async () => { + (await simulator.resolveWrapper(() => simulator.northPanElement()))!.simulate('click'); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + }); - it("should return the origin node to it's original position", async () => { - expect(originNode.getDOMNode()).toHaveStyle(originalPositionStyle); + it('should show the origin node higher on the screen', async () => { + await expect(originNodeStyle()).toYieldObjectEqualTo({ + left: '746.93132px', + top: '585.5792px', }); }); }); - describe('zooming', () => { - const originalSizeStyle = { width: '360px', height: '120px' }; - beforeEach(() => { - originNode = simulator.processNodeElements({ entityID: originEntityID }); + describe('when the user clicks the center panning button', () => { + beforeEach(async () => { + (await simulator.resolveWrapper(() => simulator.northPanElement()))!.simulate('click'); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + (await simulator.resolveWrapper(() => simulator.centerPanElement()))!.simulate('click'); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); }); - describe('when the user has not interacted with the zoom buttons or slider yet', () => { - it('should show the origin node as larger on the screen', () => { - expect(originNode.getDOMNode()).toHaveStyle(originalSizeStyle); - }); + it("should return the origin node to it's original position", async () => { + await expect(originNodeStyle()).toYieldObjectEqualTo(originalPositionStyle); }); + }); - describe('when the zoom in button is clicked', () => { - beforeEach(() => { - simulator.zoomInElement().simulate('click'); - simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); - }); + it('should show the origin node as larger on the screen', async () => { + await expect(originNodeStyle()).toYieldObjectEqualTo(originalSizeStyle); + }); - it('should show the origin node as larger on the screen', () => { - expect(originNode.getDOMNode()).toHaveStyle({ - width: '427.7538290724795px', - height: '142.5846096908265px', - }); - }); + describe('when the zoom in button is clicked', () => { + beforeEach(async () => { + (await simulator.resolveWrapper(() => simulator.zoomInElement()))!.simulate('click'); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); }); - describe('when the zoom out button is clicked', () => { - beforeEach(() => { - simulator.zoomOutElement().simulate('click'); - simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + it('should show the origin node as larger on the screen', async () => { + await expect(originNodeStyle()).toYieldObjectEqualTo({ + width: '427.7538290724795px', + height: '142.5846096908265px', }); + }); + }); + + describe('when the zoom out button is clicked', () => { + beforeEach(async () => { + (await simulator.resolveWrapper(() => simulator.zoomOutElement()))!.simulate('click'); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + }); - it('should show the origin node as smaller on the screen', () => { - expect(originNode.getDOMNode()).toHaveStyle({ - width: '303.0461709275204px', - height: '101.01539030917347px', - }); + it('should show the origin node as smaller on the screen', async () => { + await expect(originNodeStyle()).toYieldObjectEqualTo({ + width: '303.0461709275204px', + height: '101.01539030917347px', }); }); + }); - describe('when the slider is moved upwards', () => { - beforeEach(() => { - expect(originNode.getDOMNode()).toHaveStyle(originalSizeStyle); + describe('when the slider is moved upwards', () => { + beforeEach(async () => { + await expect(originNodeStyle()).toYieldObjectEqualTo(originalSizeStyle); - simulator.zoomSliderElement().simulate('change', { target: { value: 0.8 } }); - simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + (await simulator.resolveWrapper(() => simulator.zoomSliderElement()))!.simulate('change', { + target: { value: 0.8 }, }); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + }); - it('should show the origin node as large on the screen', () => { - expect(originNode.getDOMNode()).toHaveStyle({ - width: '525.6000000000001px', - height: '175.20000000000005px', - }); + it('should show the origin node as large on the screen', async () => { + await expect(originNodeStyle()).toYieldObjectEqualTo({ + width: '525.6000000000001px', + height: '175.20000000000005px', }); }); + }); - describe('when the slider is moved downwards', () => { - beforeEach(() => { - simulator.zoomSliderElement().simulate('change', { target: { value: 0.2 } }); - simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + describe('when the slider is moved downwards', () => { + beforeEach(async () => { + (await simulator.resolveWrapper(() => simulator.zoomSliderElement()))!.simulate('change', { + target: { value: 0.2 }, }); + simulator.runAnimationFramesTimeFromNow(nudgeAnimationDuration); + }); - it('should show the origin node as smaller on the screen', () => { - expect(originNode.getDOMNode()).toHaveStyle({ - width: '201.60000000000002px', - height: '67.2px', - }); + it('should show the origin node as smaller on the screen', async () => { + await expect(originNodeStyle()).toYieldObjectEqualTo({ + width: '201.60000000000002px', + height: '67.2px', }); }); });