-
Notifications
You must be signed in to change notification settings - Fork 843
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
[EuiContextMenuPanel] Convert flakey Jest focus/keyboard tests to Cypress #5261
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import React from 'react'; | ||
import { mount } from '@cypress/react'; | ||
|
||
import { EuiContextMenuItem } from './context_menu_item'; | ||
import { EuiContextMenuPanel } from './context_menu_panel'; | ||
|
||
describe('EuiContextMenuPanel', () => { | ||
describe('focus behavior', () => { | ||
it('is set on the first focusable element by default if there are no items and hasFocus is true', () => { | ||
mount( | ||
<EuiContextMenuPanel> | ||
<button data-test-subj="button">Hello world</button> | ||
</EuiContextMenuPanel> | ||
); | ||
|
||
cy.focused().should('have.attr', 'data-test-subj', 'button'); | ||
}); | ||
|
||
it('is not set on anything if hasFocus is false', () => { | ||
mount( | ||
<EuiContextMenuPanel hasFocus={false}> | ||
<button data-test-subj="button">Hello world</button> | ||
</EuiContextMenuPanel> | ||
); | ||
|
||
cy.focused().should('not.exist'); | ||
}); | ||
}); | ||
|
||
describe('keyboard navigation of items', () => { | ||
const items = [ | ||
<EuiContextMenuItem key="A" data-test-subj="itemA"> | ||
Option A | ||
</EuiContextMenuItem>, | ||
<EuiContextMenuItem key="B" data-test-subj="itemB"> | ||
Option B | ||
</EuiContextMenuItem>, | ||
<EuiContextMenuItem key="C" data-test-subj="itemC"> | ||
Option C | ||
</EuiContextMenuItem>, | ||
]; | ||
|
||
describe('up/down keys', () => { | ||
beforeEach(() => { | ||
mount(<EuiContextMenuPanel items={items} />); | ||
cy.wait(100); // Intermittent flake workaround: without this, the first downarrow key does not always focus into the menu items as expected | ||
}); | ||
|
||
it('focuses the panel by default', () => { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. FUN FACT: Did you know that if you blindly copy/paste Jest tests into Cypress and don't remove the Posting this so others hopefully don't make the same mistake as me in the future lol |
||
cy.focused().should('have.attr', 'class', 'euiContextMenuPanel'); | ||
}); | ||
|
||
it('down arrow key focuses the first menu item', () => { | ||
cy.get('body').type('{downarrow}'); | ||
|
||
cy.focused().should('have.attr', 'data-test-subj', 'itemA'); | ||
}); | ||
|
||
it('subsequently, down arrow key focuses the next menu item', () => { | ||
cy.get('body').type('{downarrow}'); | ||
cy.get('body').type('{downarrow}'); | ||
|
||
cy.focused().should('have.attr', 'data-test-subj', 'itemB'); | ||
}); | ||
|
||
it('up arrow key wraps to last menu item', () => { | ||
cy.get('body').type('{uparrow}'); | ||
|
||
cy.focused().should('have.attr', 'data-test-subj', 'itemC'); | ||
}); | ||
|
||
it('down arrow key wraps to first menu item', () => { | ||
cy.get('body').type('{uparrow}'); | ||
cy.get('body').type('{downarrow}'); | ||
|
||
cy.focused().should('have.attr', 'data-test-subj', 'itemA'); | ||
}); | ||
|
||
it('subsequently, up arrow key focuses the previous menu item', () => { | ||
cy.get('body').type('{uparrow}'); | ||
cy.get('body').type('{uparrow}'); | ||
|
||
cy.focused().should('have.attr', 'data-test-subj', 'itemB'); | ||
}); | ||
}); | ||
|
||
describe('left/right arrow keys', () => { | ||
it("right arrow key shows next panel with focused item's index", () => { | ||
const showNextPanelHandler = cy.stub(); | ||
mount( | ||
<EuiContextMenuPanel | ||
items={items} | ||
showNextPanel={showNextPanelHandler} | ||
/> | ||
); | ||
|
||
cy.get('body') | ||
.type('{downarrow}') | ||
.type('{rightarrow}') | ||
.then(() => { | ||
expect(showNextPanelHandler).to.be.called; | ||
}); | ||
}); | ||
|
||
it('left arrow key shows previous panel', () => { | ||
const showPreviousPanelHandler = cy.stub(); | ||
mount( | ||
<EuiContextMenuPanel | ||
items={items} | ||
showPreviousPanel={showPreviousPanelHandler} | ||
/> | ||
); | ||
|
||
cy.get('body') | ||
.type('{downarrow}') | ||
.type('{leftarrow}') | ||
.then(() => { | ||
expect(showPreviousPanelHandler).to.be.called; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NB: |
||
}); | ||
}); | ||
}); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,7 @@ | |
*/ | ||
|
||
import React from 'react'; | ||
import { render, mount, ReactWrapper } from 'enzyme'; | ||
import { render, mount } from 'enzyme'; | ||
import { findTestSubject, requiredProps } from '../../test'; | ||
|
||
import { EuiContextMenuPanel, SIZES } from './context_menu_panel'; | ||
|
@@ -279,129 +279,7 @@ describe('EuiContextMenuPanel', () => { | |
}); | ||
}); | ||
|
||
describe('behavior', () => { | ||
describe('focus', () => { | ||
it('is set on the first focusable element by default if there are no items and hasFocus is true', async () => { | ||
const component = mount( | ||
<EuiContextMenuPanel> | ||
<button data-test-subj="button" /> | ||
</EuiContextMenuPanel> | ||
); | ||
|
||
await tick(20); | ||
|
||
expect(findTestSubject(component, 'button').getDOMNode()).toBe( | ||
document.activeElement | ||
); | ||
}); | ||
|
||
it('is not set on anything if hasFocus is false', () => { | ||
const component = mount( | ||
<EuiContextMenuPanel hasFocus={false}> | ||
<button data-test-subj="button" /> | ||
</EuiContextMenuPanel> | ||
); | ||
|
||
expect(findTestSubject(component, 'button').getDOMNode()).not.toBe( | ||
document.activeElement | ||
); | ||
}); | ||
}); | ||
|
||
describe('keyboard navigation of items', () => { | ||
let component: ReactWrapper; | ||
let showNextPanelHandler: jest.Mock; | ||
let showPreviousPanelHandler: jest.Mock; | ||
|
||
beforeEach(() => { | ||
showNextPanelHandler = jest.fn(); | ||
showPreviousPanelHandler = jest.fn(); | ||
|
||
component = mount( | ||
<EuiContextMenuPanel | ||
items={items} | ||
showNextPanel={showNextPanelHandler} | ||
showPreviousPanel={showPreviousPanelHandler} | ||
/> | ||
); | ||
}); | ||
|
||
it('focuses the panel by default', async () => { | ||
await tick(20); | ||
|
||
expect(component.getDOMNode()).toBe(document.activeElement); | ||
}); | ||
|
||
it('down arrow key focuses the first menu item', async () => { | ||
component.simulate('keydown', { key: keys.ARROW_DOWN }); | ||
|
||
await tick(20); | ||
expect(findTestSubject(component, 'itemA').getDOMNode()).toBe( | ||
document.activeElement | ||
); | ||
}); | ||
|
||
it('subsequently, down arrow key focuses the next menu item', async () => { | ||
component.simulate('keydown', { key: keys.ARROW_DOWN }); | ||
component.simulate('keydown', { key: keys.ARROW_DOWN }); | ||
|
||
await tick(20); | ||
expect(findTestSubject(component, 'itemB').getDOMNode()).toBe( | ||
document.activeElement | ||
); | ||
}); | ||
|
||
it('down arrow key wraps to first menu item', async () => { | ||
component.simulate('keydown', { key: keys.ARROW_UP }); | ||
component.simulate('keydown', { key: keys.ARROW_DOWN }); | ||
|
||
await tick(20); | ||
expect(findTestSubject(component, 'itemA').getDOMNode()).toBe( | ||
document.activeElement | ||
); | ||
}); | ||
|
||
it('up arrow key focuses the last menu item', async () => { | ||
component.simulate('keydown', { key: keys.ARROW_UP }); | ||
|
||
await tick(20); | ||
expect(findTestSubject(component, 'itemC').getDOMNode()).toBe( | ||
document.activeElement | ||
); | ||
}); | ||
|
||
it('subsequently, up arrow key focuses the previous menu item', async () => { | ||
component.simulate('keydown', { key: keys.ARROW_UP }); | ||
component.simulate('keydown', { key: keys.ARROW_UP }); | ||
|
||
await tick(20); | ||
expect(findTestSubject(component, 'itemB').getDOMNode()).toBe( | ||
document.activeElement | ||
); | ||
}); | ||
|
||
it('up arrow key wraps to last menu item', async () => { | ||
component.simulate('keydown', { key: keys.ARROW_DOWN }); | ||
component.simulate('keydown', { key: keys.ARROW_UP }); | ||
|
||
await tick(20); | ||
expect(findTestSubject(component, 'itemC').getDOMNode()).toBe( | ||
document.activeElement | ||
); | ||
}); | ||
Comment on lines
-383
to
-391
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This test felt redundant to me with lines 364-371 so I removed it in favor of just one test 🤷♀️ |
||
|
||
it("right arrow key shows next panel with focused item's index", () => { | ||
component.simulate('keydown', { key: keys.ARROW_DOWN }); | ||
component.simulate('keydown', { key: keys.ARROW_RIGHT }); | ||
expect(showNextPanelHandler).toHaveBeenCalledWith(0); | ||
}); | ||
|
||
it('left arrow key shows previous panel', () => { | ||
component.simulate('keydown', { key: keys.ARROW_LEFT }); | ||
expect(showPreviousPanelHandler).toHaveBeenCalledTimes(1); | ||
}); | ||
}); | ||
}); | ||
// @see Cypress context_menu_panel.spec.tsx for focus & keyboard nav testing | ||
|
||
describe('updating items and content', () => { | ||
describe('updates to items', () => { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added
Hello world
text here to make the button focus more obvious in the Cypress browser real-time preview