diff --git a/src/components/dropdown/dropdown.spec.tsx b/src/components/dropdown/dropdown.spec.tsx
new file mode 100644
index 00000000..fd60e98a
--- /dev/null
+++ b/src/components/dropdown/dropdown.spec.tsx
@@ -0,0 +1,70 @@
+import {act} from 'react-dom/test-utils';
+import {mount, ReactWrapper} from 'enzyme';
+import * as React from 'react';
+
+import {DropDown} from './dropdown';
+
+describe('DropDown', () => {
+ let wrapper: ReactWrapper | null;
+
+ afterEach(() => {
+ if (wrapper) {
+ wrapper.unmount();
+ wrapper = null;
+ }
+ });
+
+ const renderDropdown = (onSelect: () => void) => mount(
+ } isMenu={true}>
+
+ ,
+ );
+
+ it('selects the first item when pressing Enter inside an open dropdown', async () => {
+ const onSelect = jest.fn();
+ wrapper = renderDropdown(onSelect);
+
+ await act(async () => {
+ wrapper!.find('.argo-dropdown__anchor').simulate('click', {stopPropagation: () => {}});
+ await Promise.resolve();
+ });
+ wrapper.update();
+
+ const preventDefault = jest.fn();
+ const event: any = {key: 'Enter', target: wrapper.find('.argo-dropdown__anchor').getDOMNode(), preventDefault};
+
+ (wrapper.instance() as any).selectTopResult(event);
+
+ expect(onSelect).toHaveBeenCalledTimes(1);
+ expect(preventDefault).toHaveBeenCalled();
+ });
+
+ it('ignores Enter when the dropdown is closed or when the target is outside', async () => {
+ const onSelect = jest.fn();
+ wrapper = renderDropdown(onSelect);
+
+ const closedEvent: any = {key: 'Enter', target: wrapper.find('.argo-dropdown__anchor').getDOMNode(), preventDefault: jest.fn()};
+
+ (wrapper.instance() as any).selectTopResult(closedEvent);
+
+ expect(onSelect).not.toHaveBeenCalled();
+
+ await act(async () => {
+ wrapper!.find('.argo-dropdown__anchor').simulate('click', {stopPropagation: () => {}});
+ await Promise.resolve();
+ });
+ wrapper.update();
+
+ const outside = document.createElement('div');
+ document.body.appendChild(outside);
+ const outsideEvent: any = {key: 'Enter', target: outside, preventDefault: jest.fn()};
+
+ (wrapper.instance() as any).selectTopResult(outsideEvent);
+
+ expect(onSelect).not.toHaveBeenCalled();
+ outside.remove();
+ });
+});
diff --git a/src/components/dropdown/dropdown.tsx b/src/components/dropdown/dropdown.tsx
index 4f447385..89966ce4 100644
--- a/src/components/dropdown/dropdown.tsx
+++ b/src/components/dropdown/dropdown.tsx
@@ -72,6 +72,8 @@ export class DropDown extends React.Component {
if (this.state.opened && this.content && this.el) {
this.setState(this.refreshState());
}
+ }), fromEvent(document, 'keydown').pipe(filter((event) => event.key === 'Enter' || event.keyCode === 13)).subscribe((event) => {
+ this.selectTopResult(event);
})];
}
@@ -87,6 +89,21 @@ export class DropDown extends React.Component {
}
}
+ private selectTopResult(event: KeyboardEvent) {
+ if (!this.state.opened || !this.content || !this.el) {
+ return;
+ }
+ const target = event.target as Node;
+ if (target && !this.el.contains(target) && !this.content.contains(target)) {
+ return;
+ }
+ const firstItem = this.content.querySelector('li') as HTMLElement;
+ if (firstItem) {
+ event.preventDefault();
+ firstItem.click();
+ }
+ }
+
private refreshState() {
const anchor = this.el.querySelector('.argo-dropdown__anchor') as HTMLElement;
const {top, left} = anchor.getBoundingClientRect();