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 ea603f2583431..2a399b6844bd7 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,6 +45,23 @@ export class Simulator { */ private readonly sideEffectSimulator: SideEffectSimulator; + /** + * An `enzyme` supported CSS selector for process node elements. + */ + public static nodeElementSelector({ + entityID, + selected = false, + }: ProcessNodeElementSelectorOptions = {}): string { + let selector: string = baseNodeElementSelector; + if (entityID !== undefined) { + selector += `[data-test-resolver-node-id="${entityID}"]`; + } + if (selected) { + selector += '[aria-selected="true"]'; + } + return selector; + } + constructor({ dataAccessLayer, resolverComponentInstanceID, @@ -193,7 +210,7 @@ export class Simulator { * returns a `ReactWrapper` even if nothing is found, as that is how `enzyme` does things. */ public processNodeElements(options: ProcessNodeElementSelectorOptions = {}): ReactWrapper { - return this.domNodes(processNodeElementSelector(options)); + return this.domNodes(Simulator.nodeElementSelector(options)); } /** @@ -230,7 +247,7 @@ export class Simulator { */ public unselectedProcessNode(entityID: string): ReactWrapper { return this.processNodeElements({ entityID }).not( - processNodeElementSelector({ entityID, selected: true }) + Simulator.nodeElementSelector({ entityID, selected: true }) ); } @@ -265,6 +282,13 @@ export class Simulator { return this.resolveWrapper(() => this.domNodes(`[data-test-subj="${selector}"]`)); } + /** + * Given a `role`, return DOM nodes that have it. Use this to assert that ARIA roles are present as expected. + */ + public domNodesWithRole(role: string): ReactWrapper { + return this.domNodes(`[role="${role}"]`); + } + /** * Given a 'data-test-subj' selector, it will return the domNode */ @@ -318,7 +342,7 @@ export class Simulator { } } -const baseResolverSelector = '[data-test-subj="resolver:node"]'; +const baseNodeElementSelector = '[data-test-subj="resolver:node"]'; interface ProcessNodeElementSelectorOptions { /** @@ -330,20 +354,3 @@ interface ProcessNodeElementSelectorOptions { */ selected?: boolean; } - -/** - * An `enzyme` supported CSS selector for process node elements. - */ -function processNodeElementSelector({ - entityID, - selected = false, -}: ProcessNodeElementSelectorOptions = {}): string { - let selector: string = baseResolverSelector; - if (entityID !== undefined) { - selector += `[data-test-resolver-node-id="${entityID}"]`; - } - if (selected) { - selector += '[aria-selected="true"]'; - } - return selector; -} diff --git a/x-pack/plugins/security_solution/public/resolver/view/clickthrough.test.tsx b/x-pack/plugins/security_solution/public/resolver/view/clickthrough.test.tsx index dba1136193ee1..c781832dc8a3b 100644 --- a/x-pack/plugins/security_solution/public/resolver/view/clickthrough.test.tsx +++ b/x-pack/plugins/security_solution/public/resolver/view/clickthrough.test.tsx @@ -137,28 +137,32 @@ describe('Resolver, when analyzing a tree that has no ancestors and 2 children', it('should render 3 elements with "treeitem" roles, each owned by an element with a "tree" role', async () => { await expect( - simulator.map(() => ({ - nodesOwnedByTrees: simulator.testSubject('resolver:node').filterWhere((domNode) => { - /** - * This test verifies corectness w.r.t. the tree/treeitem roles - * From W3C: `Authors MUST ensure elements with role treeitem are contained in, or owned by, an element with the role group or tree.` - * - * https://www.w3.org/TR/wai-aria-1.1/#tree - * https://www.w3.org/TR/wai-aria-1.1/#treeitem - * - * w3c defines two ways for an element to be an "owned element" - * 1. Any DOM descendant - * 2. Any element specified as a child via aria-owns - * (see: https://www.w3.org/TR/wai-aria-1.1/#dfn-owned-element) - * - * In the context of Resolver (as of this writing) nodes/treeitems are children of the tree, - * but they could be moved out of the tree, provided that the tree is given an `aria-owns` - * attribute referring to them (method 2 above). - */ - return domNode.closest('[role="tree"]').length === 1; - }).length, - })) - ).toYieldEqualTo({ nodesOwnedByTrees: 3 }); + simulator.map(() => { + /** + * This test verifies corectness w.r.t. the tree/treeitem roles + * From W3C: `Authors MUST ensure elements with role treeitem are contained in, or owned by, an element with the role group or tree.` + * + * https://www.w3.org/TR/wai-aria-1.1/#tree + * https://www.w3.org/TR/wai-aria-1.1/#treeitem + * + * w3c defines two ways for an element to be an "owned element" + * 1. Any DOM descendant + * 2. Any element specified as a child via aria-owns + * (see: https://www.w3.org/TR/wai-aria-1.1/#dfn-owned-element) + * + * In the context of Resolver (as of this writing) nodes/treeitems are children of the tree, + * but they could be moved out of the tree, provided that the tree is given an `aria-owns` + * attribute referring to them (method 2 above). + */ + const tree = simulator.domNodesWithRole('tree'); + return { + // There should be only one tree. + treeCount: tree.length, + // The tree should have 3 nodes in it. + nodesOwnedByTrees: tree.find(Simulator.nodeElementSelector()).length, + }; + }) + ).toYieldEqualTo({ treeCount: 1, nodesOwnedByTrees: 3 }); }); it(`should show links to the 3 nodes (with icons) in the node list.`, async () => {