Browse Source

[NO JIRA] Event - Change from KeyboardCodes to KeyboardKeys

tags/9.6.0.59041
Guillaume Peoc'h 1 year ago
parent
commit
921cf12efe
33 changed files with 190 additions and 204 deletions
  1. 5
    5
      server/sonar-web/src/main/js/app/components/nav/component/branch-like/Menu.tsx
  2. 5
    5
      server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/Menu-test.tsx
  3. 5
    5
      server/sonar-web/src/main/js/apps/account/notifications/ProjectModal.tsx
  4. 5
    5
      server/sonar-web/src/main/js/apps/code/components/Search.tsx
  5. 2
    2
      server/sonar-web/src/main/js/apps/component-measures/components/Breadcrumbs.tsx
  6. 2
    2
      server/sonar-web/src/main/js/apps/component-measures/components/__tests__/Breadcrumbs-test.tsx
  7. 4
    4
      server/sonar-web/src/main/js/apps/component-measures/drilldown/FilesView.tsx
  8. 5
    5
      server/sonar-web/src/main/js/apps/component-measures/drilldown/__tests__/FilesView-test.tsx
  9. 6
    6
      server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx
  10. 17
    17
      server/sonar-web/src/main/js/apps/issues/components/__tests__/IssuesApp-test.tsx
  11. 4
    4
      server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx
  12. 5
    5
      server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsApp-test.tsx
  13. 3
    3
      server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerTabs.tsx
  14. 8
    8
      server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewerTabs-test.tsx
  15. 5
    5
      server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/AssigneeSelection.tsx
  16. 8
    8
      server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/AssigneeSelection-test.tsx
  17. 5
    5
      server/sonar-web/src/main/js/apps/settings/components/SettingsSearch.tsx
  18. 9
    9
      server/sonar-web/src/main/js/apps/settings/components/__tests__/SettingsSearch-test.tsx
  19. 3
    3
      server/sonar-web/src/main/js/apps/settings/components/inputs/SimpleInput.tsx
  20. 4
    4
      server/sonar-web/src/main/js/apps/settings/components/inputs/__tests__/SimpleInput-test.tsx
  21. 7
    7
      server/sonar-web/src/main/js/components/common/MultiSelect.tsx
  22. 4
    4
      server/sonar-web/src/main/js/components/common/SelectList.tsx
  23. 7
    7
      server/sonar-web/src/main/js/components/common/__tests__/MultiSelect-test.tsx
  24. 6
    6
      server/sonar-web/src/main/js/components/common/__tests__/SelectList-test.tsx
  25. 2
    2
      server/sonar-web/src/main/js/components/controls/EscKeydownHandler.tsx
  26. 2
    2
      server/sonar-web/src/main/js/components/controls/SearchBox.tsx
  27. 2
    2
      server/sonar-web/src/main/js/components/controls/__tests__/EscKeydownHandler-test.tsx
  28. 24
    24
      server/sonar-web/src/main/js/components/hoc/__tests__/withKeyboardNavigation-test.tsx
  29. 5
    5
      server/sonar-web/src/main/js/components/hoc/withKeyboardNavigation.tsx
  30. 7
    7
      server/sonar-web/src/main/js/components/issue/popups/CommentPopup.tsx
  31. 3
    3
      server/sonar-web/src/main/js/components/issue/popups/__tests__/CommentPopup-test.tsx
  32. 3
    12
      server/sonar-web/src/main/js/helpers/keycodes.ts
  33. 8
    13
      server/sonar-web/src/main/js/helpers/testUtils.ts

+ 5
- 5
server/sonar-web/src/main/js/app/components/nav/component/branch-like/Menu.tsx View File

@@ -28,7 +28,7 @@ import {
isPullRequest,
isSameBranchLike
} from '../../../../../helpers/branch-like';
import { KeyboardCodes } from '../../../../../helpers/keycodes';
import { KeyboardKeys } from '../../../../../helpers/keycodes';
import { translate } from '../../../../../helpers/l10n';
import { getBranchLikeUrl } from '../../../../../helpers/urls';
import { BranchLike, BranchLikeTree } from '../../../../../types/branch-like';
@@ -110,16 +110,16 @@ export class Menu extends React.PureComponent<Props, State> {
};

handleKeyDown = (event: React.KeyboardEvent) => {
switch (event.nativeEvent.code) {
case KeyboardCodes.Enter:
switch (event.nativeEvent.key) {
case KeyboardKeys.Enter:
event.preventDefault();
this.openHighlightedBranchLike();
break;
case KeyboardCodes.UpArrow:
case KeyboardKeys.UpArrow:
event.preventDefault();
this.highlightSiblingBranchlike(-1);
break;
case KeyboardCodes.DownArrow:
case KeyboardKeys.DownArrow:
event.preventDefault();
this.highlightSiblingBranchlike(+1);
break;

+ 5
- 5
server/sonar-web/src/main/js/app/components/nav/component/branch-like/__tests__/Menu-test.tsx View File

@@ -21,7 +21,7 @@ import { shallow } from 'enzyme';
import * as React from 'react';
import { Link } from 'react-router';
import SearchBox from '../../../../../../components/controls/SearchBox';
import { KeyboardCodes } from '../../../../../../helpers/keycodes';
import { KeyboardKeys } from '../../../../../../helpers/keycodes';
import {
mockPullRequest,
mockSetOfBranchAndPullRequest
@@ -93,14 +93,14 @@ it('should handle keyboard shortcut correctly', () => {

const { onKeyDown } = wrapper.find(SearchBox).props();

onKeyDown!(mockEvent({ nativeEvent: { code: KeyboardCodes.UpArrow } }));
onKeyDown!(mockEvent({ nativeEvent: { key: KeyboardKeys.UpArrow } }));
expect(wrapper.state().selectedBranchLike).toBe(branchLikes[3]);

onKeyDown!(mockEvent({ nativeEvent: { code: KeyboardCodes.DownArrow } }));
onKeyDown!(mockEvent({ nativeEvent: { code: KeyboardCodes.DownArrow } }));
onKeyDown!(mockEvent({ nativeEvent: { key: KeyboardKeys.DownArrow } }));
onKeyDown!(mockEvent({ nativeEvent: { key: KeyboardKeys.DownArrow } }));
expect(wrapper.state().selectedBranchLike).toBe(branchLikes[0]);

onKeyDown!(mockEvent({ nativeEvent: { code: KeyboardCodes.Enter } }));
onKeyDown!(mockEvent({ nativeEvent: { key: KeyboardKeys.Enter } }));
expect(push).toHaveBeenCalled();
});


+ 5
- 5
server/sonar-web/src/main/js/apps/account/notifications/ProjectModal.tsx View File

@@ -25,7 +25,7 @@ import { ResetButtonLink, SubmitButton } from '../../../components/controls/butt
import { DropdownOverlay } from '../../../components/controls/Dropdown';
import SearchBox from '../../../components/controls/SearchBox';
import SimpleModal from '../../../components/controls/SimpleModal';
import { KeyboardCodes } from '../../../helpers/keycodes';
import { KeyboardKeys } from '../../../helpers/keycodes';
import { translate } from '../../../helpers/l10n';
import { NotificationProject } from '../../../types/notifications';

@@ -63,16 +63,16 @@ export default class ProjectModal extends React.PureComponent<Props, State> {
}

handleKeyDown = (event: React.KeyboardEvent) => {
switch (event.nativeEvent.code) {
case KeyboardCodes.Enter:
switch (event.nativeEvent.key) {
case KeyboardKeys.Enter:
event.preventDefault();
this.handleSelectHighlighted();
break;
case KeyboardCodes.UpArrow:
case KeyboardKeys.UpArrow:
event.preventDefault();
this.handleHighlightPrevious();
break;
case KeyboardCodes.DownArrow:
case KeyboardKeys.DownArrow:
event.preventDefault();
this.handleHighlightNext();
break;

+ 5
- 5
server/sonar-web/src/main/js/apps/code/components/Search.tsx View File

@@ -24,7 +24,7 @@ import SearchBox from '../../../components/controls/SearchBox';
import { Location, Router, withRouter } from '../../../components/hoc/withRouter';
import DeferredSpinner from '../../../components/ui/DeferredSpinner';
import { getBranchLikeQuery } from '../../../helpers/branch-like';
import { KeyboardCodes } from '../../../helpers/keycodes';
import { KeyboardKeys } from '../../../helpers/keycodes';
import { translate } from '../../../helpers/l10n';
import { BranchLike } from '../../../types/branch-like';
import { ComponentMeasure } from '../../../types/types';
@@ -76,10 +76,10 @@ export class Search extends React.PureComponent<Props, State> {
}

handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
switch (event.nativeEvent.code) {
case KeyboardCodes.Enter:
case KeyboardCodes.UpArrow:
case KeyboardCodes.DownArrow:
switch (event.nativeEvent.key) {
case KeyboardKeys.Enter:
case KeyboardKeys.UpArrow:
case KeyboardKeys.DownArrow:
event.preventDefault();
event.currentTarget.blur();
break;

+ 2
- 2
server/sonar-web/src/main/js/apps/component-measures/components/Breadcrumbs.tsx View File

@@ -20,7 +20,7 @@
import * as React from 'react';
import { getBreadcrumbs } from '../../../api/components';
import { getBranchLikeQuery, isSameBranchLike } from '../../../helpers/branch-like';
import { KeyboardCodes } from '../../../helpers/keycodes';
import { KeyboardKeys } from '../../../helpers/keycodes';
import { BranchLike } from '../../../types/branch-like';
import { ComponentMeasure, ComponentMeasureIntern } from '../../../types/types';
import Breadcrumb from './Breadcrumb';
@@ -63,7 +63,7 @@ export default class Breadcrumbs extends React.PureComponent<Props, State> {
}

handleKeyDown = (event: KeyboardEvent) => {
if (event.code === KeyboardCodes.LeftArrow) {
if (event.key === KeyboardKeys.LeftArrow) {
event.preventDefault();
const { breadcrumbs } = this.state;
if (breadcrumbs.length > 1) {

+ 2
- 2
server/sonar-web/src/main/js/apps/component-measures/components/__tests__/Breadcrumbs-test.tsx View File

@@ -20,7 +20,7 @@
import { mount, shallow } from 'enzyme';
import * as React from 'react';
import { getBreadcrumbs } from '../../../../api/components';
import { KeyboardCodes } from '../../../../helpers/keycodes';
import { KeyboardKeys } from '../../../../helpers/keycodes';
import { keydown, waitAndUpdate } from '../../../../helpers/testUtils';
import Breadcrumbs from '../Breadcrumbs';

@@ -75,7 +75,7 @@ it('should correctly handle keyboard action', async () => {
const handleSelect = jest.fn();
const wrapper = shallowRender({ handleSelect });
await waitAndUpdate(wrapper);
keydown({ code: KeyboardCodes.LeftArrow });
keydown({ key: KeyboardKeys.LeftArrow });
expect(handleSelect).toHaveBeenCalled();
});


+ 4
- 4
server/sonar-web/src/main/js/apps/component-measures/drilldown/FilesView.tsx View File

@@ -23,7 +23,7 @@ import { Button } from '../../../components/controls/buttons';
import ListFooter from '../../../components/controls/ListFooter';
import { Alert } from '../../../components/ui/Alert';
import { isInput, isShortcut } from '../../../helpers/keyboardEventHelpers';
import { KeyboardCodes } from '../../../helpers/keycodes';
import { KeyboardKeys } from '../../../helpers/keycodes';
import { translate, translateWithParameters } from '../../../helpers/l10n';
import { formatMeasure, isDiffMetric, isPeriodBestValue } from '../../../helpers/measures';
import { scrollToElement } from '../../../helpers/scrolling';
@@ -96,13 +96,13 @@ export default class FilesView extends React.PureComponent<Props, State> {
if (isInput(event) || isShortcut(event)) {
return true;
}
if (event.code === KeyboardCodes.UpArrow) {
if (event.key === KeyboardKeys.UpArrow) {
event.preventDefault();
this.selectPrevious();
} else if (event.code === KeyboardCodes.DownArrow) {
} else if (event.key === KeyboardKeys.DownArrow) {
event.preventDefault();
this.selectNext();
} else if (event.code === KeyboardCodes.RightArrow) {
} else if (event.key === KeyboardKeys.RightArrow) {
event.preventDefault();
this.openSelected();
}

+ 5
- 5
server/sonar-web/src/main/js/apps/component-measures/drilldown/__tests__/FilesView-test.tsx View File

@@ -19,7 +19,7 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { KeyboardCodes } from '../../../../helpers/keycodes';
import { KeyboardKeys } from '../../../../helpers/keycodes';
import { mockMetric } from '../../../../helpers/testMocks';
import { keydown } from '../../../../helpers/testUtils';
import FilesView from '../FilesView';
@@ -86,16 +86,16 @@ it('should correctly bind key events for file navigation', () => {
components: FILES
});

keydown({ code: KeyboardCodes.DownArrow });
keydown({ key: KeyboardKeys.DownArrow });
expect(handleSelect).toBeCalledWith(FILES[0]);

keydown({ code: KeyboardCodes.UpArrow });
keydown({ key: KeyboardKeys.UpArrow });
expect(handleSelect).toBeCalledWith(FILES[2]);

keydown({ code: KeyboardCodes.RightArrow, ctrlKey: true });
keydown({ key: KeyboardKeys.RightArrow, ctrlKey: true });
expect(handleOpen).not.toBeCalled();

keydown({ code: KeyboardCodes.RightArrow });
keydown({ key: KeyboardKeys.RightArrow });
expect(handleOpen).toBeCalled();
});


+ 6
- 6
server/sonar-web/src/main/js/apps/issues/components/IssuesApp.tsx View File

@@ -47,7 +47,7 @@ import {
import handleRequiredAuthentication from '../../../helpers/handleRequiredAuthentication';
import { parseIssueFromResponse } from '../../../helpers/issues';
import { isInput, isShortcut } from '../../../helpers/keyboardEventHelpers';
import { KeyboardCodes, KeyboardKeys } from '../../../helpers/keycodes';
import { KeyboardKeys } from '../../../helpers/keycodes';
import { translate, translateWithParameters } from '../../../helpers/l10n';
import {
addSideBarClass,
@@ -274,8 +274,8 @@ export default class App extends React.PureComponent<Props, State> {
return;
}

switch (event.code) {
case KeyboardCodes.DownArrow: {
switch (event.key) {
case KeyboardKeys.DownArrow: {
event.preventDefault();
if (event.altKey) {
this.selectNextLocation();
@@ -284,7 +284,7 @@ export default class App extends React.PureComponent<Props, State> {
}
break;
}
case KeyboardCodes.UpArrow: {
case KeyboardKeys.UpArrow: {
event.preventDefault();
if (event.altKey) {
this.selectPreviousLocation();
@@ -293,7 +293,7 @@ export default class App extends React.PureComponent<Props, State> {
}
break;
}
case KeyboardCodes.LeftArrow: {
case KeyboardKeys.LeftArrow: {
event.preventDefault();
if (event.altKey) {
this.selectPreviousFlow();
@@ -302,7 +302,7 @@ export default class App extends React.PureComponent<Props, State> {
}
break;
}
case KeyboardCodes.RightArrow: {
case KeyboardKeys.RightArrow: {
event.preventDefault();
if (event.altKey) {
this.selectNextFlow();

+ 17
- 17
server/sonar-web/src/main/js/apps/issues/components/__tests__/IssuesApp-test.tsx View File

@@ -22,7 +22,7 @@ import * as React from 'react';
import { searchIssues } from '../../../../api/issues';
import { getRuleDetails } from '../../../../api/rules';
import handleRequiredAuthentication from '../../../../helpers/handleRequiredAuthentication';
import { KeyboardCodes, KeyboardKeys } from '../../../../helpers/keycodes';
import { KeyboardKeys } from '../../../../helpers/keycodes';
import { mockPullRequest } from '../../../../helpers/mocks/branch-like';
import { mockComponent } from '../../../../helpers/mocks/component';
import {
@@ -226,27 +226,27 @@ it('should correctly bind key events for issue navigation', async () => {

expect(wrapper.state('selected')).toBe(ISSUES[0].key);

keydown({ code: KeyboardCodes.DownArrow });
keydown({ key: KeyboardKeys.DownArrow });
expect(wrapper.state('selected')).toBe(ISSUES[1].key);

keydown({ code: KeyboardCodes.UpArrow });
keydown({ code: KeyboardCodes.UpArrow });
keydown({ key: KeyboardKeys.UpArrow });
keydown({ key: KeyboardKeys.UpArrow });
expect(wrapper.state('selected')).toBe(ISSUES[0].key);

keydown({ code: KeyboardCodes.DownArrow });
keydown({ code: KeyboardCodes.DownArrow });
keydown({ code: KeyboardCodes.DownArrow });
keydown({ code: KeyboardCodes.DownArrow });
keydown({ code: KeyboardCodes.DownArrow });
keydown({ code: KeyboardCodes.DownArrow });
keydown({ key: KeyboardKeys.DownArrow });
keydown({ key: KeyboardKeys.DownArrow });
keydown({ key: KeyboardKeys.DownArrow });
keydown({ key: KeyboardKeys.DownArrow });
keydown({ key: KeyboardKeys.DownArrow });
keydown({ key: KeyboardKeys.DownArrow });
expect(wrapper.state('selected')).toBe(ISSUES[3].key);

keydown({ code: KeyboardCodes.RightArrow, ctrlKey: true });
keydown({ key: KeyboardKeys.RightArrow, ctrlKey: true });
expect(push).not.toBeCalled();
keydown({ code: KeyboardCodes.RightArrow });
keydown({ key: KeyboardKeys.RightArrow });
expect(push).toBeCalledTimes(1);

keydown({ code: KeyboardCodes.LeftArrow });
keydown({ key: KeyboardKeys.LeftArrow });
expect(push).toBeCalledTimes(2);

addEventListenerSpy.mockReset();
@@ -433,19 +433,19 @@ describe('keydown event handler', () => {
expect(instance.setState).toHaveBeenCalledWith(enableLocationsNavigator);
});
it('should handle alt+↓', () => {
instance.handleKeyDown(mockEvent({ altKey: true, code: KeyboardCodes.DownArrow }));
instance.handleKeyDown(mockEvent({ altKey: true, key: KeyboardKeys.DownArrow }));
expect(instance.setState).toHaveBeenCalledWith(selectNextLocation);
});
it('should handle alt+↑', () => {
instance.handleKeyDown(mockEvent({ altKey: true, code: KeyboardCodes.UpArrow }));
instance.handleKeyDown(mockEvent({ altKey: true, key: KeyboardKeys.UpArrow }));
expect(instance.setState).toHaveBeenCalledWith(selectPreviousLocation);
});
it('should handle alt+←', () => {
instance.handleKeyDown(mockEvent({ altKey: true, code: KeyboardCodes.LeftArrow }));
instance.handleKeyDown(mockEvent({ altKey: true, key: KeyboardKeys.LeftArrow }));
expect(instance.setState).toHaveBeenCalledWith(selectPreviousFlow);
});
it('should handle alt+→', () => {
instance.handleKeyDown(mockEvent({ altKey: true, code: KeyboardCodes.RightArrow }));
instance.handleKeyDown(mockEvent({ altKey: true, key: KeyboardKeys.RightArrow }));
expect(instance.setState).toHaveBeenCalledWith(selectNextFlow);
});
it('should ignore if modal is open', () => {

+ 4
- 4
server/sonar-web/src/main/js/apps/security-hotspots/SecurityHotspotsApp.tsx View File

@@ -27,7 +27,7 @@ import withCurrentUserContext from '../../app/components/current-user/withCurren
import { Router } from '../../components/hoc/withRouter';
import { getLeakValue } from '../../components/measure/utils';
import { getBranchLikeQuery, isPullRequest, isSameBranchLike } from '../../helpers/branch-like';
import { KeyboardCodes, KeyboardKeys } from '../../helpers/keycodes';
import { KeyboardKeys } from '../../helpers/keycodes';
import { scrollToElement } from '../../helpers/scrolling';
import { getStandards } from '../../helpers/security-standard';
import { BranchLike } from '../../types/branch-like';
@@ -150,8 +150,8 @@ export class SecurityHotspotsApp extends React.PureComponent<Props, State> {
return;
}

switch (event.code) {
case KeyboardCodes.DownArrow: {
switch (event.key) {
case KeyboardKeys.DownArrow: {
event.preventDefault();
if (event.altKey) {
this.selectNextLocation();
@@ -160,7 +160,7 @@ export class SecurityHotspotsApp extends React.PureComponent<Props, State> {
}
break;
}
case KeyboardCodes.UpArrow: {
case KeyboardKeys.UpArrow: {
event.preventDefault();
if (event.altKey) {
this.selectPreviousLocation();

+ 5
- 5
server/sonar-web/src/main/js/apps/security-hotspots/__tests__/SecurityHotspotsApp-test.tsx View File

@@ -21,7 +21,7 @@ import { shallow } from 'enzyme';
import * as React from 'react';
import { getMeasures } from '../../../api/measures';
import { getSecurityHotspotList, getSecurityHotspots } from '../../../api/security-hotspots';
import { KeyboardCodes } from '../../../helpers/keycodes';
import { KeyboardKeys } from '../../../helpers/keycodes';
import { mockBranch, mockPullRequest } from '../../../helpers/mocks/branch-like';
import { mockComponent } from '../../../helpers/mocks/component';
import { mockHtmlElement } from '../../../helpers/mocks/dom';
@@ -465,7 +465,7 @@ describe('keyboard navigation', () => {
['selecting next locations, non-existent', 2, undefined]
])('should work when %s', (_, start, expected) => {
wrapper.setState({ selectedHotspotLocationIndex: start, selectedHotspot: hotspotsForLocation });
wrapper.instance().handleKeyDown(mockEvent({ altKey: true, code: KeyboardCodes.DownArrow }));
wrapper.instance().handleKeyDown(mockEvent({ altKey: true, key: KeyboardKeys.DownArrow }));

expect(wrapper.state().selectedHotspotLocationIndex).toBe(expected);
});
@@ -476,7 +476,7 @@ describe('keyboard navigation', () => {
['selecting previous locations, non-existent', 0, undefined]
])('should work when %s', (_, start, expected) => {
wrapper.setState({ selectedHotspotLocationIndex: start, selectedHotspot: hotspotsForLocation });
wrapper.instance().handleKeyDown(mockEvent({ altKey: true, code: KeyboardCodes.UpArrow }));
wrapper.instance().handleKeyDown(mockEvent({ altKey: true, key: KeyboardKeys.UpArrow }));

expect(wrapper.state().selectedHotspotLocationIndex).toBe(expected);
});
@@ -484,10 +484,10 @@ describe('keyboard navigation', () => {
it('should not change location index when locations are empty', () => {
wrapper.setState({ selectedHotspotLocationIndex: undefined, selectedHotspot: hotspots[0] });

wrapper.instance().handleKeyDown(mockEvent({ altKey: true, code: KeyboardCodes.UpArrow }));
wrapper.instance().handleKeyDown(mockEvent({ altKey: true, key: KeyboardKeys.UpArrow }));
expect(wrapper.state().selectedHotspotLocationIndex).toBeUndefined();

wrapper.instance().handleKeyDown(mockEvent({ altKey: true, code: KeyboardCodes.DownArrow }));
wrapper.instance().handleKeyDown(mockEvent({ altKey: true, key: KeyboardKeys.DownArrow }));
expect(wrapper.state().selectedHotspotLocationIndex).toBeUndefined();
});
});

+ 3
- 3
server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerTabs.tsx View File

@@ -21,7 +21,7 @@ import classNames from 'classnames';
import * as React from 'react';
import BoxedTabs from '../../../components/controls/BoxedTabs';
import { isInput, isShortcut } from '../../../helpers/keyboardEventHelpers';
import { KeyboardCodes } from '../../../helpers/keycodes';
import { KeyboardKeys } from '../../../helpers/keycodes';
import { translate } from '../../../helpers/l10n';
import { sanitizeString } from '../../../helpers/sanitize';
import { Hotspot } from '../../../types/security-hotspots';
@@ -90,10 +90,10 @@ export default class HotspotViewerTabs extends React.PureComponent<Props, State>
if (isInput(event) || isShortcut(event)) {
return true;
}
if (event.code === KeyboardCodes.LeftArrow) {
if (event.key === KeyboardKeys.LeftArrow) {
event.preventDefault();
this.selectNeighboringTab(-1);
} else if (event.code === KeyboardCodes.RightArrow) {
} else if (event.key === KeyboardKeys.RightArrow) {
event.preventDefault();
this.selectNeighboringTab(+1);
}

+ 8
- 8
server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewerTabs-test.tsx View File

@@ -20,7 +20,7 @@
import { mount, shallow } from 'enzyme';
import * as React from 'react';
import BoxedTabs, { BoxedTabsProps } from '../../../../components/controls/BoxedTabs';
import { KeyboardCodes } from '../../../../helpers/keycodes';
import { KeyboardKeys } from '../../../../helpers/keycodes';
import { mockHotspot, mockHotspotRule } from '../../../../helpers/mocks/security-hotspots';
import { mockEvent, mockUser } from '../../../../helpers/testMocks';
import HotspotViewerTabs, { TabKeys } from '../HotspotViewerTabs';
@@ -145,13 +145,13 @@ describe('keyboard navigation', () => {
const wrapper = shallowRender();

it.each([
['selecting next', 0, KeyboardCodes.RightArrow, 1],
['selecting previous', 1, KeyboardCodes.LeftArrow, 0],
['selecting previous, non-existent', 0, KeyboardCodes.LeftArrow, 0],
['selecting next, non-existent', 3, KeyboardCodes.RightArrow, 3]
])('should work when %s', (_, start, code, expected) => {
['selecting next', 0, KeyboardKeys.RightArrow, 1],
['selecting previous', 1, KeyboardKeys.LeftArrow, 0],
['selecting previous, non-existent', 0, KeyboardKeys.LeftArrow, 0],
['selecting next, non-existent', 3, KeyboardKeys.RightArrow, 3]
])('should work when %s', (_, start, key, expected) => {
wrapper.setState({ currentTab: wrapper.state().tabs[start] });
wrapper.instance().handleKeyboardNavigation(mockEvent({ code }));
wrapper.instance().handleKeyboardNavigation(mockEvent({ key }));

expect(wrapper.state().currentTab.key).toBe(tabList[expected]);
});
@@ -165,7 +165,7 @@ it("shouldn't navigate when ctrl or command are pressed with up and down", () =>
wrapper.setState({ currentTab: wrapper.state().tabs[0] });
wrapper
.instance()
.handleKeyboardNavigation(mockEvent({ code: KeyboardCodes.LeftArrow, metaKey: true }));
.handleKeyboardNavigation(mockEvent({ key: KeyboardKeys.LeftArrow, metaKey: true }));

expect(wrapper.state().currentTab.key).toBe(TabKeys.Code);
});

+ 5
- 5
server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/AssigneeSelection.tsx View File

@@ -20,7 +20,7 @@
import { debounce } from 'lodash';
import * as React from 'react';
import { searchUsers } from '../../../../api/users';
import { KeyboardCodes } from '../../../../helpers/keycodes';
import { KeyboardKeys } from '../../../../helpers/keycodes';
import { translate } from '../../../../helpers/l10n';
import { isUserActive, LoggedInUser, UserActive } from '../../../../types/users';
import AssigneeSelectionRenderer from './AssigneeSelectionRenderer';
@@ -104,16 +104,16 @@ export default class AssigneeSelection extends React.PureComponent<Props, State>
};

handleKeyDown = (event: React.KeyboardEvent) => {
switch (event.nativeEvent.code) {
case KeyboardCodes.Enter:
switch (event.nativeEvent.key) {
case KeyboardKeys.Enter:
event.preventDefault();
this.selectHighlighted();
break;
case KeyboardCodes.UpArrow:
case KeyboardKeys.UpArrow:
event.preventDefault();
this.highlightPrevious();
break;
case KeyboardCodes.DownArrow:
case KeyboardKeys.DownArrow:
event.preventDefault();
this.highlightNext();
break;

+ 8
- 8
server/sonar-web/src/main/js/apps/security-hotspots/components/assignee/__tests__/AssigneeSelection-test.tsx View File

@@ -20,7 +20,7 @@
import { shallow } from 'enzyme';
import * as React from 'react';
import { searchUsers } from '../../../../../api/users';
import { KeyboardCodes } from '../../../../../helpers/keycodes';
import { KeyboardKeys } from '../../../../../helpers/keycodes';
import { mockLoggedInUser, mockUser } from '../../../../../helpers/testMocks';
import { waitAndUpdate } from '../../../../../helpers/testUtils';
import { UserActive } from '../../../../../types/users';
@@ -35,7 +35,7 @@ it('should render correctly', () => {
});

it('should handle keydown', () => {
const mockEvent = (code: KeyboardCodes) => ({ preventDefault: jest.fn(), nativeEvent: { code } });
const mockEvent = (key: KeyboardKeys) => ({ preventDefault: jest.fn(), nativeEvent: { key } });
const suggestedUsers = [
mockUser({ login: '1' }) as UserActive,
mockUser({ login: '2' }) as UserActive,
@@ -45,29 +45,29 @@ it('should handle keydown', () => {
const onSelect = jest.fn();
const wrapper = shallowRender({ onSelect });

wrapper.instance().handleKeyDown(mockEvent(KeyboardCodes.UpArrow) as any);
wrapper.instance().handleKeyDown(mockEvent(KeyboardKeys.UpArrow) as any);
expect(wrapper.state().highlighted).toEqual({ login: '', name: 'unassigned' });

wrapper.setState({ suggestedUsers });

// press down to highlight the first
wrapper.instance().handleKeyDown(mockEvent(KeyboardCodes.DownArrow) as any);
wrapper.instance().handleKeyDown(mockEvent(KeyboardKeys.DownArrow) as any);
expect(wrapper.state().highlighted).toBe(suggestedUsers[0]);

// press up to loop around to last
wrapper.instance().handleKeyDown(mockEvent(KeyboardCodes.UpArrow) as any);
wrapper.instance().handleKeyDown(mockEvent(KeyboardKeys.UpArrow) as any);
expect(wrapper.state().highlighted).toBe(suggestedUsers[2]);

// press down to loop around to first
wrapper.instance().handleKeyDown(mockEvent(KeyboardCodes.DownArrow) as any);
wrapper.instance().handleKeyDown(mockEvent(KeyboardKeys.DownArrow) as any);
expect(wrapper.state().highlighted).toBe(suggestedUsers[0]);

// press down highlight the next
wrapper.instance().handleKeyDown(mockEvent(KeyboardCodes.DownArrow) as any);
wrapper.instance().handleKeyDown(mockEvent(KeyboardKeys.DownArrow) as any);
expect(wrapper.state().highlighted).toBe(suggestedUsers[1]);

// press enter to select the highlighted user
wrapper.instance().handleKeyDown(mockEvent(KeyboardCodes.Enter) as any);
wrapper.instance().handleKeyDown(mockEvent(KeyboardKeys.Enter) as any);
expect(onSelect).toBeCalledWith(suggestedUsers[1]);
});


+ 5
- 5
server/sonar-web/src/main/js/apps/settings/components/SettingsSearch.tsx View File

@@ -22,7 +22,7 @@ import lunr, { LunrIndex } from 'lunr';
import * as React from 'react';
import { InjectedRouter } from 'react-router';
import { withRouter } from '../../../components/hoc/withRouter';
import { KeyboardCodes } from '../../../helpers/keycodes';
import { KeyboardKeys } from '../../../helpers/keycodes';
import { ExtendedSettingDefinition } from '../../../types/settings';
import { Component, Dict } from '../../../types/types';
import {
@@ -124,16 +124,16 @@ export class SettingsSearch extends React.Component<Props, State> {
};

handleKeyDown = (event: React.KeyboardEvent) => {
switch (event.nativeEvent.code) {
case KeyboardCodes.Enter:
switch (event.nativeEvent.key) {
case KeyboardKeys.Enter:
event.preventDefault();
this.openSelected();
return;
case KeyboardCodes.UpArrow:
case KeyboardKeys.UpArrow:
event.preventDefault();
this.selectPrevious();
return;
case KeyboardCodes.DownArrow:
case KeyboardKeys.DownArrow:
event.preventDefault();
this.selectNext();
// keep this return to prevent fall-through in case more cases will be adder later

+ 9
- 9
server/sonar-web/src/main/js/apps/settings/components/__tests__/SettingsSearch-test.tsx View File

@@ -19,7 +19,7 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { KeyboardCodes } from '../../../../helpers/keycodes';
import { KeyboardKeys } from '../../../../helpers/keycodes';
import { mockComponent } from '../../../../helpers/mocks/component';
import { mockDefinition } from '../../../../helpers/mocks/settings';
import { mockRouter } from '../../../../helpers/testMocks';
@@ -98,11 +98,11 @@ describe('instance', () => {

it('should handle "enter" keyboard event', () => {
wrapper.setState({ selectedResult: undefined });
wrapper.instance().handleKeyDown(mockEvent({ nativeEvent: { code: KeyboardCodes.Enter } }));
wrapper.instance().handleKeyDown(mockEvent({ nativeEvent: { key: KeyboardKeys.Enter } }));
expect(router.push).not.toBeCalled();

wrapper.setState({ selectedResult: 'foo' });
wrapper.instance().handleKeyDown(mockEvent({ nativeEvent: { code: KeyboardCodes.Enter } }));
wrapper.instance().handleKeyDown(mockEvent({ nativeEvent: { key: KeyboardKeys.Enter } }));

expect(router.push).toBeCalledWith({
hash: '#foo',
@@ -113,27 +113,27 @@ describe('instance', () => {

it('should handle "down" keyboard event', () => {
wrapper.setState({ selectedResult: undefined });
wrapper.instance().handleKeyDown(mockEvent({ nativeEvent: { code: KeyboardCodes.DownArrow } }));
wrapper.instance().handleKeyDown(mockEvent({ nativeEvent: { key: KeyboardKeys.DownArrow } }));
expect(wrapper.state().selectedResult).toBeUndefined();

wrapper.setState({ selectedResult: 'foo' });
wrapper.instance().handleKeyDown(mockEvent({ nativeEvent: { code: KeyboardCodes.DownArrow } }));
wrapper.instance().handleKeyDown(mockEvent({ nativeEvent: { key: KeyboardKeys.DownArrow } }));
expect(wrapper.state().selectedResult).toBe('sonar.new_code_period');

wrapper.instance().handleKeyDown(mockEvent({ nativeEvent: { code: KeyboardCodes.DownArrow } }));
wrapper.instance().handleKeyDown(mockEvent({ nativeEvent: { key: KeyboardKeys.DownArrow } }));
expect(wrapper.state().selectedResult).toBe('sonar.new_code_period');
});

it('should handle "up" keyboard event', () => {
wrapper.setState({ selectedResult: undefined });
wrapper.instance().handleKeyDown(mockEvent({ nativeEvent: { code: KeyboardCodes.UpArrow } }));
wrapper.instance().handleKeyDown(mockEvent({ nativeEvent: { key: KeyboardKeys.UpArrow } }));
expect(wrapper.state().selectedResult).toBeUndefined();

wrapper.setState({ selectedResult: 'sonar.new_code_period' });
wrapper.instance().handleKeyDown(mockEvent({ nativeEvent: { code: KeyboardCodes.UpArrow } }));
wrapper.instance().handleKeyDown(mockEvent({ nativeEvent: { key: KeyboardKeys.UpArrow } }));
expect(wrapper.state().selectedResult).toBe('foo');

wrapper.instance().handleKeyDown(mockEvent({ nativeEvent: { code: KeyboardCodes.UpArrow } }));
wrapper.instance().handleKeyDown(mockEvent({ nativeEvent: { key: KeyboardKeys.UpArrow } }));
expect(wrapper.state().selectedResult).toBe('foo');
});
});

+ 3
- 3
server/sonar-web/src/main/js/apps/settings/components/inputs/SimpleInput.tsx View File

@@ -19,7 +19,7 @@
*/
import classNames from 'classnames';
import * as React from 'react';
import { KeyboardCodes } from '../../../../helpers/keycodes';
import { KeyboardKeys } from '../../../../helpers/keycodes';
import { DefaultSpecializedInputProps } from '../../utils';

export interface SimpleInputProps extends DefaultSpecializedInputProps {
@@ -32,9 +32,9 @@ export default class SimpleInput extends React.PureComponent<SimpleInputProps> {
};

handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.nativeEvent.code === KeyboardCodes.Enter && this.props.onSave) {
if (event.nativeEvent.key === KeyboardKeys.Enter && this.props.onSave) {
this.props.onSave();
} else if (event.nativeEvent.code === KeyboardCodes.Escape && this.props.onCancel) {
} else if (event.nativeEvent.key === KeyboardKeys.Escape && this.props.onCancel) {
this.props.onCancel();
}
};

+ 4
- 4
server/sonar-web/src/main/js/apps/settings/components/inputs/__tests__/SimpleInput-test.tsx View File

@@ -19,7 +19,7 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { KeyboardCodes } from '../../../../../helpers/keycodes';
import { KeyboardKeys } from '../../../../../helpers/keycodes';
import { mockSetting } from '../../../../../helpers/mocks/settings';
import { mockEvent } from '../../../../../helpers/testMocks';
import { change } from '../../../../../helpers/testUtils';
@@ -49,7 +49,7 @@ it('should handle enter', () => {
const onSave = jest.fn();
shallowRender({ onSave })
.instance()
.handleKeyDown(mockEvent({ nativeEvent: { code: KeyboardCodes.Enter } }));
.handleKeyDown(mockEvent({ nativeEvent: { key: KeyboardKeys.Enter } }));
expect(onSave).toBeCalled();
});

@@ -57,7 +57,7 @@ it('should handle esc', () => {
const onCancel = jest.fn();
shallowRender({ onCancel })
.instance()
.handleKeyDown(mockEvent({ nativeEvent: { code: KeyboardCodes.Escape } }));
.handleKeyDown(mockEvent({ nativeEvent: { key: KeyboardKeys.Escape } }));
expect(onCancel).toBeCalled();
});

@@ -66,7 +66,7 @@ it('should ignore other keys', () => {
const onCancel = jest.fn();
shallowRender({ onCancel, onSave })
.instance()
.handleKeyDown(mockEvent({ nativeEvent: { code: KeyboardCodes.LeftArrow } }));
.handleKeyDown(mockEvent({ nativeEvent: { key: KeyboardKeys.LeftArrow } }));
expect(onSave).not.toBeCalled();
expect(onCancel).not.toBeCalled();
});

+ 7
- 7
server/sonar-web/src/main/js/components/common/MultiSelect.tsx View File

@@ -22,7 +22,7 @@ import { difference } from 'lodash';
import * as React from 'react';
import SearchBox from '../../components/controls/SearchBox';
import { isShortcut } from '../../helpers/keyboardEventHelpers';
import { KeyboardCodes } from '../../helpers/keycodes';
import { KeyboardKeys } from '../../helpers/keycodes';
import { translateWithParameters } from '../../helpers/l10n';
import MultiSelectOption from './MultiSelectOption';

@@ -143,22 +143,22 @@ export default class MultiSelect extends React.PureComponent<PropsWithDefault, S
if (isShortcut(event)) {
return true;
}
switch (event.code) {
case KeyboardCodes.DownArrow:
switch (event.key) {
case KeyboardKeys.DownArrow:
event.stopPropagation();
event.preventDefault();
this.setState(this.selectNextElement);
break;
case KeyboardCodes.UpArrow:
case KeyboardKeys.UpArrow:
event.stopPropagation();
event.preventDefault();
this.setState(this.selectPreviousElement);
break;
case KeyboardCodes.LeftArrow:
case KeyboardCodes.RightArrow:
case KeyboardKeys.LeftArrow:
case KeyboardKeys.RightArrow:
event.stopPropagation();
break;
case KeyboardCodes.Enter:
case KeyboardKeys.Enter:
if (this.state.activeIdx >= 0) {
this.toggleSelect(this.getAllElements(this.props, this.state)[this.state.activeIdx]);
}

+ 4
- 4
server/sonar-web/src/main/js/components/common/SelectList.tsx View File

@@ -19,7 +19,7 @@
*/
import classNames from 'classnames';
import * as React from 'react';
import { KeyboardCodes } from '../../helpers/keycodes';
import { KeyboardKeys } from '../../helpers/keycodes';
import SelectListItem from './SelectListItem';

interface Props {
@@ -59,15 +59,15 @@ export default class SelectList extends React.PureComponent<Props, State> {
}

handleKeyDown = (event: KeyboardEvent) => {
if (event.code === KeyboardCodes.DownArrow) {
if (event.key === KeyboardKeys.DownArrow) {
event.preventDefault();
event.stopImmediatePropagation();
this.setState(this.selectNextElement);
} else if (event.code === KeyboardCodes.UpArrow) {
} else if (event.key === KeyboardKeys.UpArrow) {
event.preventDefault();
event.stopImmediatePropagation();
this.setState(this.selectPreviousElement);
} else if (event.code === KeyboardCodes.Enter) {
} else if (event.key === KeyboardKeys.Enter) {
event.preventDefault();
event.stopImmediatePropagation();
if (this.state.active != null) {

+ 7
- 7
server/sonar-web/src/main/js/components/common/__tests__/MultiSelect-test.tsx View File

@@ -19,7 +19,7 @@
*/
import { mount, shallow } from 'enzyme';
import * as React from 'react';
import { KeyboardCodes } from '../../../helpers/keycodes';
import { KeyboardKeys } from '../../../helpers/keycodes';
import { mockEvent } from '../../../helpers/testUtils';
import MultiSelect, { MultiSelectProps } from '../MultiSelect';

@@ -63,15 +63,15 @@ it('should render with the focus inside the search input', () => {
});

it.each([
[KeyboardCodes.DownArrow, 1, 1],
[KeyboardCodes.UpArrow, 1, 1],
[KeyboardCodes.LeftArrow, 1, 0]
])('should handle keyboard event: %s', (code, stopPropagationCalls, preventDefaultCalls) => {
[KeyboardKeys.DownArrow, 1, 1],
[KeyboardKeys.UpArrow, 1, 1],
[KeyboardKeys.LeftArrow, 1, 0]
])('should handle keyboard event: %s', (key, stopPropagationCalls, preventDefaultCalls) => {
const wrapper = shallowRender();

const stopPropagation = jest.fn();
const preventDefault = jest.fn();
const event = mockEvent({ preventDefault, stopPropagation, code });
const event = mockEvent({ preventDefault, stopPropagation, key });

wrapper.instance().handleKeyboard(event);

@@ -84,7 +84,7 @@ it('should handle keyboard event: enter', () => {

wrapper.instance().toggleSelect = jest.fn();

wrapper.instance().handleKeyboard(mockEvent({ code: KeyboardCodes.Enter }));
wrapper.instance().handleKeyboard(mockEvent({ key: KeyboardKeys.Enter }));

expect(wrapper.instance().toggleSelect).toBeCalled();
});

+ 6
- 6
server/sonar-web/src/main/js/components/common/__tests__/SelectList-test.tsx View File

@@ -19,7 +19,7 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { KeyboardCodes } from '../../../helpers/keycodes';
import { KeyboardKeys } from '../../../helpers/keycodes';
import { keydown } from '../../../helpers/testUtils';
import SelectList from '../SelectList';
import SelectListItem from '../SelectListItem';
@@ -54,15 +54,15 @@ it('should correclty handle user actions', () => {
));
const list = shallowRender({ items, onSelect }, children);
expect(list.state().active).toBe('seconditem');
keydown({ code: KeyboardCodes.DownArrow });
keydown({ key: KeyboardKeys.DownArrow });
expect(list.state().active).toBe('third');
keydown({ code: KeyboardCodes.DownArrow });
keydown({ key: KeyboardKeys.DownArrow });
expect(list.state().active).toBe('item');
keydown({ code: KeyboardCodes.UpArrow });
keydown({ key: KeyboardKeys.UpArrow });
expect(list.state().active).toBe('third');
keydown({ code: KeyboardCodes.UpArrow });
keydown({ key: KeyboardKeys.UpArrow });
expect(list.state().active).toBe('seconditem');
keydown({ code: KeyboardCodes.Enter });
keydown({ key: KeyboardKeys.Enter });
expect(onSelect).toBeCalledWith('seconditem');
list.instance().componentWillUnmount!();
});

+ 2
- 2
server/sonar-web/src/main/js/components/controls/EscKeydownHandler.tsx View File

@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import { KeyboardCodes } from '../../helpers/keycodes';
import { KeyboardKeys } from '../../helpers/keycodes';

interface Props {
children: React.ReactNode;
@@ -37,7 +37,7 @@ export default class EscKeydownHandler extends React.Component<Props> {
}

handleKeyDown = (event: KeyboardEvent) => {
if (event.code === KeyboardCodes.Escape) {
if (event.key === KeyboardKeys.Escape) {
this.props.onKeydown();
}
};

+ 2
- 2
server/sonar-web/src/main/js/components/controls/SearchBox.tsx View File

@@ -20,7 +20,7 @@
import classNames from 'classnames';
import { Cancelable, debounce } from 'lodash';
import * as React from 'react';
import { KeyboardCodes } from '../../helpers/keycodes';
import { KeyboardKeys } from '../../helpers/keycodes';
import { translate, translateWithParameters } from '../../helpers/l10n';
import SearchIcon from '../icons/SearchIcon';
import DeferredSpinner from '../ui/DeferredSpinner';
@@ -95,7 +95,7 @@ export default class SearchBox extends React.PureComponent<Props, State> {
};

handleInputKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.nativeEvent.code === KeyboardCodes.Escape) {
if (event.nativeEvent.key === KeyboardKeys.Escape) {
event.preventDefault();
this.handleResetClick();
}

+ 2
- 2
server/sonar-web/src/main/js/components/controls/__tests__/EscKeydownHandler-test.tsx View File

@@ -19,7 +19,7 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { KeyboardCodes } from '../../../helpers/keycodes';
import { KeyboardKeys } from '../../../helpers/keycodes';
import { keydown } from '../../../helpers/testUtils';
import EscKeydownHandler from '../EscKeydownHandler';

@@ -40,7 +40,7 @@ it('should correctly trigger the keydown handler when hitting Esc', () => {
const onKeydown = jest.fn();
shallowRender({ onKeydown });
jest.runAllTimers();
keydown({ code: KeyboardCodes.Escape });
keydown({ key: KeyboardKeys.Escape });
expect(onKeydown).toBeCalled();
});


+ 24
- 24
server/sonar-web/src/main/js/components/hoc/__tests__/withKeyboardNavigation-test.tsx View File

@@ -19,7 +19,7 @@
*/
import { mount, shallow } from 'enzyme';
import * as React from 'react';
import { KeyboardCodes } from '../../../helpers/keycodes';
import { KeyboardKeys } from '../../../helpers/keycodes';
import { mockComponent } from '../../../helpers/mocks/component';
import { keydown } from '../../../helpers/testUtils';
import { ComponentMeasure } from '../../../types/types';
@@ -64,32 +64,32 @@ it('should correctly bind key events for component navigation', () => {
})
);

keydown({ code: KeyboardCodes.DownArrow });
keydown({ key: KeyboardKeys.DownArrow });
expect(onHighlight).toBeCalledWith(COMPONENTS[2]);
expect(onSelect).not.toBeCalled();

keydown({ code: KeyboardCodes.UpArrow });
keydown({ code: KeyboardCodes.UpArrow });
keydown({ key: KeyboardKeys.UpArrow });
keydown({ key: KeyboardKeys.UpArrow });
expect(onHighlight).toBeCalledWith(COMPONENTS[0]);
expect(onSelect).not.toBeCalled();

keydown({ code: KeyboardCodes.UpArrow });
keydown({ key: KeyboardKeys.UpArrow });
expect(onHighlight).toBeCalledWith(COMPONENTS[2]);

keydown({ code: KeyboardCodes.DownArrow });
keydown({ key: KeyboardKeys.DownArrow });
expect(onHighlight).toBeCalledWith(COMPONENTS[0]);

keydown({ code: KeyboardCodes.RightArrow, metaKey: true });
keydown({ key: KeyboardKeys.RightArrow, metaKey: true });
expect(onSelect).not.toBeCalled();
keydown({ code: KeyboardCodes.RightArrow });
keydown({ key: KeyboardKeys.RightArrow });
expect(onSelect).toBeCalledWith(COMPONENTS[0]);

keydown({ code: KeyboardCodes.Enter });
keydown({ key: KeyboardKeys.Enter });
expect(onSelect).toBeCalledWith(COMPONENTS[0]);

keydown({ code: KeyboardCodes.LeftArrow, metaKey: true });
keydown({ key: KeyboardKeys.LeftArrow, metaKey: true });
expect(onGoToParent).not.toBeCalled();
keydown({ code: KeyboardCodes.LeftArrow });
keydown({ key: KeyboardKeys.LeftArrow });
expect(onGoToParent).toBeCalled();
});

@@ -106,18 +106,18 @@ it('should support not cycling through elements, and triggering a callback on re
})
);

keydown({ code: KeyboardCodes.DownArrow });
keydown({ key: KeyboardKeys.DownArrow });
expect(onHighlight).toBeCalledWith(COMPONENTS[0]);
keydown({ code: KeyboardCodes.DownArrow });
keydown({ code: KeyboardCodes.DownArrow });
keydown({ code: KeyboardCodes.DownArrow });
keydown({ key: KeyboardKeys.DownArrow });
keydown({ key: KeyboardKeys.DownArrow });
keydown({ key: KeyboardKeys.DownArrow });
expect(onHighlight).toBeCalledWith(COMPONENTS[2]);
expect(onEndOfList).toBeCalled();

keydown({ code: KeyboardCodes.UpArrow });
keydown({ code: KeyboardCodes.UpArrow });
keydown({ code: KeyboardCodes.UpArrow });
keydown({ code: KeyboardCodes.UpArrow });
keydown({ key: KeyboardKeys.UpArrow });
keydown({ key: KeyboardKeys.UpArrow });
keydown({ key: KeyboardKeys.UpArrow });
keydown({ key: KeyboardKeys.UpArrow });
expect(onHighlight).toBeCalledWith(COMPONENTS[0]);
});

@@ -138,19 +138,19 @@ it('should correctly bind key events for codeview navigation', () => {

expect(onHighlight).not.toBeCalled();

keydown({ code: KeyboardCodes.DownArrow });
keydown({ key: KeyboardKeys.DownArrow });
expect(onHighlight).not.toBeCalled();

keydown({ code: KeyboardCodes.UpArrow });
keydown({ key: KeyboardKeys.UpArrow });
expect(onHighlight).not.toBeCalled();

keydown({ code: KeyboardCodes.RightArrow });
keydown({ key: KeyboardKeys.RightArrow });
expect(onSelect).not.toBeCalled();

keydown({ code: KeyboardCodes.Enter });
keydown({ key: KeyboardKeys.Enter });
expect(onSelect).not.toBeCalled();

keydown({ code: KeyboardCodes.LeftArrow });
keydown({ key: KeyboardKeys.LeftArrow });
expect(onGoToParent).toBeCalled();
});


+ 5
- 5
server/sonar-web/src/main/js/components/hoc/withKeyboardNavigation.tsx View File

@@ -21,7 +21,7 @@ import * as React from 'react';
import PageActions from '../../components/ui/PageActions';
import { getComponentMeasureUniqueKey } from '../../helpers/component';
import { isInput, isShortcut } from '../../helpers/keyboardEventHelpers';
import { KeyboardCodes } from '../../helpers/keycodes';
import { KeyboardKeys } from '../../helpers/keycodes';
import { ComponentMeasure } from '../../types/types';
import { getWrappedDisplayName } from './utils';

@@ -54,16 +54,16 @@ export default function withKeyboardNavigation<P>(
if (isInput(event) || isShortcut(event)) {
return true;
}
if (event.code === KeyboardCodes.UpArrow) {
if (event.key === KeyboardKeys.UpArrow) {
event.preventDefault();
return this.skipIfFile(this.handleHighlightPrevious);
} else if (event.code === KeyboardCodes.DownArrow) {
} else if (event.key === KeyboardKeys.DownArrow) {
event.preventDefault();
return this.skipIfFile(this.handleHighlightNext);
} else if (event.code === KeyboardCodes.RightArrow || event.code === KeyboardCodes.Enter) {
} else if (event.key === KeyboardKeys.RightArrow || event.key === KeyboardKeys.Enter) {
event.preventDefault();
return this.skipIfFile(this.handleSelectCurrent);
} else if (event.code === KeyboardCodes.LeftArrow) {
} else if (event.key === KeyboardKeys.LeftArrow) {
event.preventDefault();
this.handleSelectParent();
return false; // always hijack left / Why did you put this @wouter?

+ 7
- 7
server/sonar-web/src/main/js/components/issue/popups/CommentPopup.tsx View File

@@ -21,7 +21,7 @@ import * as React from 'react';
import { Button, ResetButtonLink } from '../../../components/controls/buttons';
import { DropdownOverlay } from '../../../components/controls/Dropdown';
import { PopupPlacement } from '../../../components/ui/popups';
import { KeyboardCodes } from '../../../helpers/keycodes';
import { KeyboardKeys } from '../../../helpers/keycodes';
import { translate } from '../../../helpers/l10n';
import { IssueComment } from '../../../types/types';
import FormattingTips from '../../common/FormattingTips';
@@ -62,15 +62,15 @@ export default class CommentPopup extends React.PureComponent<CommentPopupProps,
};

handleKeyboard = (event: React.KeyboardEvent) => {
if (event.nativeEvent.code === KeyboardCodes.Enter && (event.metaKey || event.ctrlKey)) {
if (event.nativeEvent.key === KeyboardKeys.Enter && (event.metaKey || event.ctrlKey)) {
this.handleCommentClick();
} else if (
[
KeyboardCodes.UpArrow,
KeyboardCodes.DownArrow,
KeyboardCodes.LeftArrow,
KeyboardCodes.RightArrow
].includes(event.nativeEvent.code as KeyboardCodes)
KeyboardKeys.UpArrow,
KeyboardKeys.DownArrow,
KeyboardKeys.LeftArrow,
KeyboardKeys.RightArrow
].includes(event.nativeEvent.key as KeyboardKeys)
) {
// Arrow keys
event.stopPropagation();

+ 3
- 3
server/sonar-web/src/main/js/components/issue/popups/__tests__/CommentPopup-test.tsx View File

@@ -19,7 +19,7 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
import { KeyboardCodes } from '../../../../helpers/keycodes';
import { KeyboardKeys } from '../../../../helpers/keycodes';
import { mockEvent } from '../../../../helpers/testMocks';
import { click } from '../../../../helpers/testUtils';
import CommentPopup, { CommentPopupProps } from '../CommentPopup';
@@ -58,7 +58,7 @@ it('should handle ctrl+enter', () => {

wrapper
.instance()
.handleKeyboard(mockEvent({ ctrlKey: true, nativeEvent: { code: KeyboardCodes.Enter } }));
.handleKeyboard(mockEvent({ ctrlKey: true, nativeEvent: { key: KeyboardKeys.Enter } }));

expect(onComment).toBeCalled();
});
@@ -67,7 +67,7 @@ it('should stopPropagation for arrow keys events', () => {
const wrapper = shallowRender();

const event = mockEvent({
nativeEvent: { code: KeyboardCodes.UpArrow },
nativeEvent: { key: KeyboardKeys.UpArrow },
stopPropagation: jest.fn()
});
wrapper.instance().handleKeyboard(event);

+ 3
- 12
server/sonar-web/src/main/js/helpers/keycodes.ts View File

@@ -17,7 +17,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
export enum KeyboardCodes {

export enum KeyboardKeys {
LeftArrow = 'ArrowLeft',
UpArrow = 'ArrowUp',
RightArrow = 'ArrowRight',
@@ -33,17 +34,7 @@ export enum KeyboardCodes {
PageDown = 'PageDown',
PageUp = 'PageUp',
Space = 'Space',
Tab = 'Tab'
}

export enum KeyboardKeys {
Escape = 'Escape',
UpArrow = 'ArrowUp',
DownArrow = 'ArrowDown',
RightArrow = 'ArrowRight',
LeftArrow = 'ArrowLeft',
Enter = 'Enter',
Space = ' ',
Tab = 'Tab',
Alt = 'Alt',
KeyF = 'f',
KeyA = 'a',

+ 8
- 13
server/sonar-web/src/main/js/helpers/testUtils.ts View File

@@ -19,7 +19,7 @@
*/
import { ReactWrapper, ShallowWrapper } from 'enzyme';
import { setImmediate } from 'timers';
import { KeyboardCodes, KeyboardKeys } from './keycodes';
import { KeyboardKeys } from './keycodes';

export function mockEvent(overrides = {}) {
return {
@@ -74,20 +74,15 @@ export function change(
}
}

export const KEYCODE_MAP: { [code in KeyboardCodes]?: string } = {
[KeyboardCodes.Enter]: 'enter',
[KeyboardCodes.LeftArrow]: 'left',
[KeyboardCodes.UpArrow]: 'up',
[KeyboardCodes.RightArrow]: 'right',
[KeyboardCodes.DownArrow]: 'down'
export const KEYCODE_MAP: { [code in KeyboardKeys]?: string } = {
[KeyboardKeys.Enter]: 'enter',
[KeyboardKeys.LeftArrow]: 'left',
[KeyboardKeys.UpArrow]: 'up',
[KeyboardKeys.RightArrow]: 'right',
[KeyboardKeys.DownArrow]: 'down'
};

export function keydown(args: {
code?: KeyboardCodes;
key?: KeyboardKeys;
metaKey?: boolean;
ctrlKey?: boolean;
}): void {
export function keydown(args: { key?: KeyboardKeys; metaKey?: boolean; ctrlKey?: boolean }): void {
const event = new KeyboardEvent('keydown', args as KeyboardEventInit);
document.dispatchEvent(event);
}

Loading…
Cancel
Save