diff options
author | Jay <jeremy.davis@sonarsource.com> | 2022-02-25 11:23:01 +0100 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2022-02-25 20:02:55 +0000 |
commit | 7f825acb518fcd15823d3fb279509816e25e1d85 (patch) | |
tree | 0c3afcaeb56134518651b189fff46ee67b441830 /server | |
parent | f87f174aa6c07d0d5f39f427f4a07978e7e6a53b (diff) | |
download | sonarqube-7f825acb518fcd15823d3fb279509816e25e1d85.tar.gz sonarqube-7f825acb518fcd15823d3fb279509816e25e1d85.zip |
SONAR-16008 Fix keyboad navigation conflict
Diffstat (limited to 'server')
2 files changed, 41 insertions, 44 deletions
diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerTabs.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerTabs.tsx index 63778962337..4d335618427 100644 --- a/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerTabs.tsx +++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/HotspotViewerTabs.tsx @@ -18,9 +18,9 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import classNames from 'classnames'; -import key from 'keymaster'; import * as React from 'react'; import BoxedTabs from '../../../components/controls/BoxedTabs'; +import { KeyboardCodes } from '../../../helpers/keycodes'; import { translate } from '../../../helpers/l10n'; import { sanitizeString } from '../../../helpers/sanitize'; import { Hotspot } from '../../../types/security-hotspots'; @@ -49,8 +49,6 @@ export enum TabKeys { FixRecommendation = 'fix' } -const HOTSPOT_KEYMASTER_SCOPE = 'hotspots-list'; - export default class HotspotViewerTabs extends React.PureComponent<Props, State> { constructor(props: Props) { super(props); @@ -87,20 +85,22 @@ export default class HotspotViewerTabs extends React.PureComponent<Props, State> this.unregisterKeyboardEvents(); } - registerKeyboardEvents() { - key.setScope(HOTSPOT_KEYMASTER_SCOPE); - key('left', HOTSPOT_KEYMASTER_SCOPE, () => { + handleKeyboardNavigation = (event: KeyboardEvent) => { + if (event.code === KeyboardCodes.LeftArrow) { + event.preventDefault(); this.selectNeighboringTab(-1); - return false; - }); - key('right', HOTSPOT_KEYMASTER_SCOPE, () => { + } else if (event.code === KeyboardCodes.RightArrow) { + event.preventDefault(); this.selectNeighboringTab(+1); - return false; - }); + } + }; + + registerKeyboardEvents() { + window.addEventListener('keydown', this.handleKeyboardNavigation); } unregisterKeyboardEvents() { - key.deleteScope(HOTSPOT_KEYMASTER_SCOPE); + window.removeEventListener('keydown', this.handleKeyboardNavigation); } handleSelectTabs = (tabKey: TabKeys) => { diff --git a/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewerTabs-test.tsx b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewerTabs-test.tsx index ffbc475c3da..50fbf5f4392 100644 --- a/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewerTabs-test.tsx +++ b/server/sonar-web/src/main/js/apps/security-hotspots/components/__tests__/HotspotViewerTabs-test.tsx @@ -22,29 +22,28 @@ import * as React from 'react'; import BoxedTabs, { BoxedTabsProps } from '../../../../components/controls/BoxedTabs'; import { KeyboardCodes } from '../../../../helpers/keycodes'; import { mockHotspot, mockHotspotRule } from '../../../../helpers/mocks/security-hotspots'; -import { mockUser } from '../../../../helpers/testMocks'; -import { KEYCODE_MAP, keydown } from '../../../../helpers/testUtils'; +import { mockEvent, mockUser } from '../../../../helpers/testMocks'; import HotspotViewerTabs, { TabKeys } from '../HotspotViewerTabs'; -jest.mock('keymaster', () => { - const key: any = (bindKey: string, _: string, callback: Function) => { - document.addEventListener('keydown', (event: KeyboardEvent) => { - const keymasterCode = event.code && KEYCODE_MAP[event.code as KeyboardCodes]; - if (keymasterCode && bindKey.split(',').includes(keymasterCode)) { - return callback(); - } - return true; - }); - }; - let scope = 'hotspots-list'; - - key.getScope = () => scope; - key.setScope = (newScope: string) => { - scope = newScope; - }; - key.deleteScope = jest.fn(); - - return key; +const originalAddEventListener = window.addEventListener; +const originalRemoveEventListener = window.removeEventListener; + +beforeEach(() => { + Object.defineProperty(window, 'addEventListener', { + value: jest.fn() + }); + Object.defineProperty(window, 'removeEventListener', { + value: jest.fn() + }); +}); + +afterEach(() => { + Object.defineProperty(window, 'addEventListener', { + value: originalAddEventListener + }); + Object.defineProperty(window, 'removeEventListener', { + value: originalRemoveEventListener + }); }); it('should render correctly', () => { @@ -146,13 +145,13 @@ describe('keyboard navigation', () => { const wrapper = shallowRender(); it.each([ - ['selecting next', 0, 1, 1], - ['selecting previous', 1, -1, 0], - ['selecting previous, non-existent', 0, -1, 0], - ['selecting next, non-existent', 3, 1, 3] - ])('should work when %s', (_, start, shift, expected) => { + ['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) => { wrapper.setState({ currentTab: wrapper.state().tabs[start] }); - wrapper.instance().selectNeighboringTab(shift); + wrapper.instance().handleKeyboardNavigation(mockEvent({ code })); expect(wrapper.state().currentTab.key).toBe(tabList[expected]); }); @@ -163,13 +162,11 @@ it('should navigate when up and down key are pressed', () => { <HotspotViewerTabs codeTabContent={<div>CodeTabContent</div>} hotspot={mockHotspot()} /> ); - const selectNeighboringTab = jest.spyOn(wrapper.instance(), 'selectNeighboringTab'); + expect(window.addEventListener).toBeCalled(); - keydown({ code: KeyboardCodes.LeftArrow }); - expect(selectNeighboringTab).toBeCalledWith(-1); + wrapper.unmount(); - keydown({ code: KeyboardCodes.RightArrow }); - expect(selectNeighboringTab).toBeCalledWith(1); + expect(window.removeEventListener).toBeCalled(); }); function shallowRender(props?: Partial<HotspotViewerTabs['props']>) { |