Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Resolver] simulator tests select elements directly instead of using descendant selectors. #75058

Merged
merged 2 commits into from
Aug 14, 2020

Conversation

oatkiller
Copy link
Contributor

@oatkiller oatkiller commented Aug 14, 2020

Summary

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.

Checklist

For maintainers

@oatkiller oatkiller requested review from a team as code owners August 14, 2020 16:01
@oatkiller oatkiller added release_note:skip Skip the PR/issue when compiling release notes v7.10.0 labels Aug 14, 2020
*/
public processNodeChildElements(entityID: string, selector: string): ReactWrapper {
public processNodeSubmenuButton(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This no longer relies on the DOM structure.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, I wonder if it's better to just remove this method entirely to just use the testSubject and make the processNodeSubmenuButton a separate utility function? Only rationale is keeping the simulator as generic as possible. so you would have something like expect(simulator().testSubject(processNodeSubmenuButton(entityId))).toBe(blah)...then again that looks a bit gross 🤷‍♂️

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i actually considered this, but the testSubject method takes just a single test subject string while processNodeSubmenuButton involves two data-attribute selectors.

I also considered packing all of the info we need into the data-test-subj attribute.

I wasn't 100% on either of those, but I think this PR is still an improvement.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yea, it can really go either way. We could have testSubject take an options obj that builds the selector based on what's defined a la your processNodeElementSelector. So testSubject would now take the following

{
	dataTestSubj: string,
	dataTestResolverNodeId: string,
    ...potentially any other future options
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yah that might work. I first want to discuss this topic: is it important that the buttons are descendants of the node's wrapper <div />. Having methods like processNodeSubmenuButton provides a level of abstraction that will allow us to easily change our mind on that. In this PR it selects an element using two attribute selectors. If we decide that the DOM structure does matter then we could change that to use a descendant selector.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be resolved by @bkimmel's comment below. Thanks

/**
* The primary button (used to select a node) which contains a label for the node as its content.
*/
public processNodePrimaryButton(
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Node's have 2 buttons, one to select it, one to open its submenu. This is the one that selects it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above, but if we decide to stay this route, would a name like processNodeShowDetailsButton work? But then again, that could be confusing considering the process cube is also clickable as well and has the same effect?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That name could also work. We could also drop process from the name. We could also do something involving aria roles somehow. For example, if the graph has a test subj, we could select [role="treeitem"] descendants to get the node wrapper elements. We could also select some other role to get this 'primary' button perhaps. I don't know enough about it yet.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

aria attributes could work. The primary reason I lean towards naming this the effect the button has is that it provides the reader an initial idea of what any related tests should be doing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see what you mean. Related idea: perhaps we could have a selectNodeViaButtonClick method.

@@ -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,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this test used to check for the presence of a div, now it checks for a button (that the user can see and interact w/)

@@ -404,6 +404,8 @@ const UnstyledProcessEventDot = React.memo(
}}
tabIndex={-1}
title={eventModel.processNameSafeVersion(event)}
data-test-subj="resolver:node:primary-button"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thoughts on this pattern?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 I don't see a scenario where we add more buttons in the future, but if we do, then we can change it then. The possible future scenario I'm thinking about is something like this potentially around a process node: https://tympanus.net/codrops/2013/08/09/building-a-circular-navigation-with-css-transforms/

Probably a lot of accessibility concerns with that that I have not thought about though

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like it

@oatkiller oatkiller added Feature:Resolver Security Solution Resolver feature Team:Endpoint Data Visibility Team managing the endpoint resolver labels Aug 14, 2020
@elasticmachine
Copy link
Contributor

Pinging @elastic/endpoint-data-visibility-team (Team:Endpoint Data Visibility)

@elasticmachine
Copy link
Contributor

Pinging @elastic/endpoint-app-team (Feature:Resolver)

return this.domNodes(
`${processNodeElementSelector({ entityID })} [data-test-subj="${selector}"]`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❔ This is one case where the structure of the selector before ("button that is owned by the process") was valuable I think. I don't see that reflected as much in simplifying it to "a button with an ID". Someone could move that button out from the node, changing the semantics and this test would still pass.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How exactly would removing a wrapper div change the semantics?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The wrapper gets an aria-selected attribute. is that what you're thinking about?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even though the submenu button gets tagged with the data-test-resolver-node-id that doesn't really say the same thing as the button being contained by the node. A well-meaning dev could move that button outside the node (while finding another way to populate data-test-resolver-node-id as the test expects here and break the semantic meaning without tripping the test up at all. I don't see that as an "improvement" to what's there or easier to read. We could discuss at office hours.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we could assert this "contains" stuff in the test itself, but then to Michael's point earlier, it kinda beggars the purpose of this separate method altogether.

Copy link
Contributor Author

@oatkiller oatkiller Aug 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A well-meaning dev could move that button outside the node (while finding another way to populate data-test-resolver-node-id as the test expects here

That's exactly what I'm going for. Why would we want that to break the test? Is there some observable behavior that's being broken?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📏

Post discussion at office hours: We do want to test things like that buttons are contained by certain elements (say with certain aria-roles or they have some other kind of equivalent aria- relationship like owns ) but that is perhaps better to assert in individual tests (i.e. write a test that asserts that all sumbenu button are children of a role=treeitem or have some equivalent structural relationship established via other attributes.)

That allows us to keep methods on the simulator more simple/single-purpose ("just get this element") and write tests for the things we care to assert.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we discussed this. The DOM structure is important. These abstractions are still useful. With them, not every tests needs to be coupled to the DOM structure. These methods may change in the future to rely on the DOM structure, that should be fine. Also, we will have separate tests that check the DOM structure and a11y roles.

@@ -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}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sweeet

@kibanamachine
Copy link
Contributor

💚 Build Succeeded

Build metrics

async chunks size

id value diff baseline
securitySolution 7.2MB +154.0B 7.2MB

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@oatkiller oatkiller merged commit 459e9d6 into elastic:master Aug 14, 2020
oatkiller pushed a commit to oatkiller/kibana that referenced this pull request Aug 14, 2020
…descendant selectors. (elastic#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.
gmmorris added a commit to gmmorris/kibana that referenced this pull request Aug 17, 2020
* master: (24 commits)
  [ML] Functional tests - skip regression and classification tests
  [Ingest Manager] fix removing ingest pipelines from elasticsearch (elastic#75092)
  move tests for placeholder indices to setup (elastic#75096)
  [jest] temporarily extend default test timeout (elastic#75118)
  [cli] remove reference to removed --optimize flag (elastic#75083)
  skip flaky suite (elastic#75044)
  Adding /etc/rc.d/init.d/functions to the init script when present to … (elastic#22985)
  [jenkins] add pipeline for hourly security solution cypress tests (elastic#75087)
  [Reporting/Flaky Test] Skip test for paging list of reports (elastic#75075)
  remove .kbn-optimizer-cache upload (elastic#75086)
  skip flaky suite (elastic#74814)
  Actions add proxy support (elastic#74289)
  [ILM] TS conversion of Edit policy components (elastic#74747)
  [Resolver] simulator tests select elements directly instead of using descendant selectors. (elastic#75058)
  [Enterprise Search] Add Workplace Search side navigation (elastic#74894)
  [Security solution] Sourcerer: Kibana index pattern selector for security views (elastic#74706)
  [Logs UI] Remove apollo deps from log link-to routes (elastic#74502)
  [Maps] add map configurations to docker list (elastic#75035)
  [functional test][saved objects] update tests for additional copy saved objects to space (elastic#74907)
  Make the alerts plugin support generics (elastic#72716)
  ...
oatkiller pushed a commit that referenced this pull request Aug 17, 2020
…descendant selectors. (#75058) (#75084)

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.

Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
@oatkiller oatkiller deleted the panel-tests branch March 31, 2022 11:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature:Resolver Security Solution Resolver feature release_note:skip Skip the PR/issue when compiling release notes Team:Endpoint Data Visibility Team managing the endpoint resolver v7.10.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants