Skip to content

Commit

Permalink
[Resolver] simulator tests select elements directly instead of using …
Browse files Browse the repository at this point in the history
…descendant selectors. (#75058)

Our tests shouldn't rely on the DOM structure of Resolver (when its arbitrary) because that will make them brittle. If the user doesn't care about the DOM structure, then neither should our tests.

Note: sometimes the user does care about the DOM structure, and in those cases the tests should as well.
  • Loading branch information
Robert Austin authored Aug 14, 2020
1 parent ac04e05 commit 459e9d6
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -175,14 +175,24 @@ export class Simulator {
}

/**
* Return an Enzyme ReactWrapper for any child elements of a specific processNodeElement
*
* @param entityID The entity ID of the proocess node to select in
* @param selector The selector for the child element of the process node
* The button that opens a node's submenu.
*/
public processNodeChildElements(entityID: string, selector: string): ReactWrapper {
public processNodeSubmenuButton(
/** nodeID for the related node */ entityID: string
): ReactWrapper {
return this.domNodes(
`${processNodeElementSelector({ entityID })} [data-test-subj="${selector}"]`
`[data-test-subj="resolver:submenu:button"][data-test-resolver-node-id="${entityID}"]`
);
}

/**
* The primary button (used to select a node) which contains a label for the node as its content.
*/
public processNodePrimaryButton(
/** nodeID for the related node */ entityID: string
): ReactWrapper {
return this.domNodes(
`[data-test-subj="resolver:node:primary-button"][data-test-resolver-node-id="${entityID}"]`
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ describe('Resolver, when analyzing a tree that has no ancestors and 2 children',
selectedOriginCount: simulator.selectedProcessNode(entityIDs.origin).length,
unselectedFirstChildCount: simulator.unselectedProcessNode(entityIDs.firstChild).length,
unselectedSecondChildCount: simulator.unselectedProcessNode(entityIDs.secondChild).length,
processNodeCount: simulator.processNodeElements().length,
nodePrimaryButtonCount: simulator.testSubject('resolver:node:primary-button').length,
}))
).toYieldEqualTo({
selectedOriginCount: 1,
unselectedFirstChildCount: 1,
unselectedSecondChildCount: 1,
processNodeCount: 3,
nodePrimaryButtonCount: 3,
});
});

Expand All @@ -82,13 +82,14 @@ describe('Resolver, when analyzing a tree that has no ancestors and 2 children',
});

describe("when the second child node's first button has been clicked", () => {
beforeEach(() => {
// Click the first button under the second child element.
simulator
.processNodeElements({ entityID: entityIDs.secondChild })
.find('button')
.first()
.simulate('click');
beforeEach(async () => {
const button = await simulator.resolveWrapper(() =>
simulator.processNodePrimaryButton(entityIDs.secondChild)
);
// Click the second child node's primary button
if (button) {
button.simulate('click');
}
});
it('should render the second child node as selected, and the origin as not selected, and the query string should indicate that the second child is selected', async () => {
await expect(
Expand Down Expand Up @@ -141,23 +142,20 @@ describe('Resolver, when analyzing a tree that has two related events for the or
graphElements: simulator.testSubject('resolver:graph').length,
graphLoadingElements: simulator.testSubject('resolver:graph:loading').length,
graphErrorElements: simulator.testSubject('resolver:graph:error').length,
originNode: simulator.processNodeElements({ entityID: entityIDs.origin }).length,
originNodeButton: simulator.processNodePrimaryButton(entityIDs.origin).length,
}))
).toYieldEqualTo({
graphElements: 1,
graphLoadingElements: 0,
graphErrorElements: 0,
originNode: 1,
originNodeButton: 1,
});
});

it('should render a related events button', async () => {
await expect(
simulator.map(() => ({
relatedEventButtons: simulator.processNodeChildElements(
entityIDs.origin,
'resolver:submenu:button'
).length,
relatedEventButtons: simulator.processNodeSubmenuButton(entityIDs.origin).length,
}))
).toYieldEqualTo({
relatedEventButtons: 1,
Expand All @@ -166,7 +164,7 @@ describe('Resolver, when analyzing a tree that has two related events for the or
describe('when the related events button is clicked', () => {
beforeEach(async () => {
const button = await simulator.resolveWrapper(() =>
simulator.processNodeChildElements(entityIDs.origin, 'resolver:submenu:button')
simulator.processNodeSubmenuButton(entityIDs.origin)
);
if (button) {
button.simulate('click');
Expand All @@ -183,7 +181,7 @@ describe('Resolver, when analyzing a tree that has two related events for the or
describe('and when the related events button is clicked again', () => {
beforeEach(async () => {
const button = await simulator.resolveWrapper(() =>
simulator.processNodeChildElements(entityIDs.origin, 'resolver:submenu:button')
simulator.processNodeSubmenuButton(entityIDs.origin)
);
if (button) {
button.simulate('click');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,8 @@ const UnstyledProcessEventDot = React.memo(
}}
tabIndex={-1}
title={eventModel.processNameSafeVersion(event)}
data-test-subj="resolver:node:primary-button"
data-test-resolver-node-id={nodeID}
>
<span className="euiButton__content">
<span className="euiButton__text" data-test-subj={'euiButton__text'}>
Expand Down Expand Up @@ -433,6 +435,7 @@ const UnstyledProcessEventDot = React.memo(
menuTitle={subMenuAssets.relatedEvents.title}
projectionMatrix={projectionMatrix}
optionsWithActions={relatedEventStatusOrOptions}
nodeID={nodeID}
/>
)}
</EuiFlexItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ describe('Resolver, when analyzing a tree that has no ancestors and 2 children',

describe("when the second child node's first button has been clicked", () => {
beforeEach(async () => {
const node = await simulator.resolveWrapper(() =>
simulator.processNodeElements({ entityID: entityIDs.secondChild }).find('button')
const button = await simulator.resolveWrapper(() =>
simulator.processNodePrimaryButton(entityIDs.secondChild)
);
if (node) {
if (button) {
// Click the first button under the second child element.
node.first().simulate('click');
button.simulate('click');
}
});
const expectedSearch = urlSearch(resolverComponentInstanceID, {
Expand Down Expand Up @@ -68,12 +68,12 @@ describe('Resolver, when analyzing a tree that has no ancestors and 2 children',
});
describe("when the user clicks the second child node's button again", () => {
beforeEach(async () => {
const node = await simulator.resolveWrapper(() =>
simulator.processNodeElements({ entityID: entityIDs.secondChild }).find('button')
const button = await simulator.resolveWrapper(() =>
simulator.processNodePrimaryButton(entityIDs.secondChild)
);
if (node) {
if (button) {
// Click the first button under the second child element.
node.first().simulate('click');
button.simulate('click');
}
});
it(`should have a url search of ${urlSearch(newInstanceID, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ const NodeSubMenuComponents = React.memo(
optionsWithActions,
className,
projectionMatrix,
nodeID,
}: {
menuTitle: string;
className?: string;
Expand All @@ -148,6 +149,7 @@ const NodeSubMenuComponents = React.memo(
* Receive the projection matrix, so we can see when the camera position changed, so we can force the submenu to reposition itself.
*/
projectionMatrix: Matrix3;
nodeID: string;
} & {
optionsWithActions?: ResolverSubmenuOptionList | string | undefined;
}) => {
Expand Down Expand Up @@ -236,6 +238,7 @@ const NodeSubMenuComponents = React.memo(
iconSide="right"
tabIndex={-1}
data-test-subj="resolver:submenu:button"
data-test-resolver-node-id={nodeID}
>
{count ? <EuiI18nNumber value={count} /> : ''} {menuTitle}
</EuiButton>
Expand Down

0 comments on commit 459e9d6

Please sign in to comment.