[Resolver] simulator tests select elements directly instead of using descendant selectors.#75058
Conversation
| * The button that opens a node's submenu. | ||
| */ | ||
| public processNodeChildElements(entityID: string, selector: string): ReactWrapper { | ||
| public processNodeSubmenuButton( |
There was a problem hiding this comment.
This no longer relies on the DOM structure.
There was a problem hiding this comment.
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 🤷♂️
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
}
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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( |
There was a problem hiding this comment.
Node's have 2 buttons, one to select it, one to open its submenu. This is the one that selects it.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
I see what you mean. Related idea: perhaps we could have a selectNodeViaButtonClick method.
| 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, |
There was a problem hiding this comment.
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/)
| }} | ||
| tabIndex={-1} | ||
| title={eventModel.processNameSafeVersion(event)} | ||
| data-test-subj="resolver:node:primary-button" |
There was a problem hiding this comment.
thoughts on this pattern?
There was a problem hiding this comment.
👍 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
|
Pinging @elastic/endpoint-data-visibility-team (Team:Endpoint Data Visibility) |
|
Pinging @elastic/endpoint-app-team (Feature:Resolver) |
| /** nodeID for the related node */ entityID: string | ||
| ): ReactWrapper { | ||
| return this.domNodes( | ||
| `${processNodeElementSelector({ entityID })} [data-test-subj="${selector}"]` |
There was a problem hiding this comment.
❔ 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.
There was a problem hiding this comment.
How exactly would removing a wrapper div change the semantics?
There was a problem hiding this comment.
The wrapper gets an aria-selected attribute. is that what you're thinking about?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
📏
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.
There was a problem hiding this comment.
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.
| tabIndex={-1} | ||
| title={eventModel.processNameSafeVersion(event)} | ||
| data-test-subj="resolver:node:primary-button" | ||
| data-test-resolver-node-id={nodeID} |
…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.
* 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) ...
…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>
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