@@ -14,7 +14,7 @@ exports[`rendering should render the list of templates: Permission Template 1: u | |||
exports[`rendering should render the list of templates: Permission Template 2: admin 1`] = `"0 user(s)0 group(s)"`; | |||
exports[`rendering should render the list of templates: Permission Template 2: codeviewer 1`] = `"permission_templates.project_creatorspermission_templates.project_creators.explanationpermission_templates.project_creators.explanation0 user(s)0 group(s)"`; | |||
exports[`rendering should render the list of templates: Permission Template 2: codeviewer 1`] = `"permission_templates.project_creatorspermission_templates.project_creators.explanation0 user(s)0 group(s)"`; | |||
exports[`rendering should render the list of templates: Permission Template 2: issueadmin 1`] = `"0 user(s)0 group(s)"`; | |||
@@ -22,4 +22,4 @@ exports[`rendering should render the list of templates: Permission Template 2: s | |||
exports[`rendering should render the list of templates: Permission Template 2: securityhotspotadmin 1`] = `"0 user(s)0 group(s)"`; | |||
exports[`rendering should render the list of templates: Permission Template 2: user 1`] = `"permission_templates.project_creatorspermission_templates.project_creators.explanationpermission_templates.project_creators.explanation0 user(s)0 group(s)"`; | |||
exports[`rendering should render the list of templates: Permission Template 2: user 1`] = `"permission_templates.project_creatorspermission_templates.project_creators.explanation0 user(s)0 group(s)"`; |
@@ -56,6 +56,7 @@ export default function DocumentationTooltip(props: DocumentationTooltipProps) { | |||
return; | |||
} | |||
if (event.target === last(linksRef.current)) { | |||
event.preventDefault(); | |||
nextSelectableNode.current?.focus(); | |||
return; | |||
} |
@@ -46,10 +46,6 @@ | |||
margin-left: 0; | |||
} | |||
.location-index.is-leading:not(:first-child) { | |||
margin-left: -22px; | |||
} | |||
.location-index[tabindex] { | |||
cursor: pointer; | |||
} |
@@ -29,6 +29,7 @@ const ui = { | |||
body: byRole('body'), | |||
beforeLink: byRole('link', { name: 'Interactive element before' }), | |||
helpIcon: byTestId('help-tooltip-activator'), | |||
helpLink: byRole('link', { name: 'Icon' }), | |||
linkInTooltip: byRole('link', { name: 'Label' }), | |||
linkInTooltip2: byRole('link', { name: 'opens_in_new_window Label2' }), | |||
afterLink: byRole('link', { name: 'Interactive element after' }), | |||
@@ -43,19 +44,19 @@ it('should correctly navigate through TAB', async () => { | |||
await user.tab(); | |||
expect(ui.helpIcon.get()).toHaveFocus(); | |||
await user.tab(); | |||
expect(ui.linkInTooltip.getAll().at(1)).toHaveFocus(); | |||
expect(ui.linkInTooltip.get()).toHaveFocus(); | |||
await user.tab(); | |||
expect(ui.linkInTooltip2.getAll().at(1)).toHaveFocus(); | |||
expect(ui.linkInTooltip2.get()).toHaveFocus(); | |||
// Looks like RTL tab event ignores any custom focuses during the events phase, | |||
// unless preventDefault is specified | |||
await user.tab(); | |||
expect(ui.helpIcon.get()).toHaveFocus(); | |||
await user.tab({ shift: true }); | |||
expect(await ui.afterLink.find()).toHaveFocus(); | |||
await user.tab({ shift: true }); | |||
await user.tab(); | |||
await user.tab(); | |||
await user.tab({ shift: true }); | |||
expect(await ui.afterLink.find()).toHaveFocus(); | |||
expect(await ui.beforeLink.find()).toHaveFocus(); | |||
}); | |||
function renderDocumentationTooltip(props: Partial<DocumentationTooltipProps> = {}) { | |||
@@ -81,7 +82,11 @@ function renderDocumentationTooltip(props: Partial<DocumentationTooltipProps> = | |||
}, | |||
]} | |||
{...props} | |||
/> | |||
> | |||
<Link to="/" target="_blank"> | |||
Icon | |||
</Link> | |||
</DocumentationTooltip> | |||
<Link to="/" target="_blank"> | |||
Interactive element after | |||
</Link> |
@@ -430,7 +430,7 @@ export class TooltipInner extends React.Component<TooltipProps, State> { | |||
// can mess up buttons that need a tooltip). | |||
'aria-describedby': this.id, | |||
})} | |||
{!isVisible && this.renderOverlay()} | |||
{!isVisible && <TooltipPortal>{this.renderOverlay()}</TooltipPortal>} | |||
{isVisible && ( | |||
<EscKeydownHandler onKeydown={this.closeTooltip}> | |||
<TooltipPortal> |
@@ -66,40 +66,23 @@ it('should open & close', () => { | |||
wrapper.find('#tooltip').simulate('pointerenter'); | |||
jest.runOnlyPendingTimers(); | |||
wrapper.update(); | |||
expect(wrapper.find('TooltipPortal').exists()).toBe(true); | |||
expect(onShow).toHaveBeenCalled(); | |||
wrapper.find('#tooltip').simulate('pointerleave'); | |||
jest.runOnlyPendingTimers(); | |||
wrapper.update(); | |||
expect(wrapper.find('TooltipPortal').exists()).toBe(false); | |||
expect(onHide).toHaveBeenCalled(); | |||
onShow.mockReset(); | |||
onHide.mockReset(); | |||
wrapper.find('#tooltip').simulate('focus'); | |||
expect(wrapper.find('TooltipPortal').exists()).toBe(true); | |||
expect(onShow).toHaveBeenCalled(); | |||
wrapper.find('#tooltip').simulate('blur'); | |||
expect(wrapper.find('TooltipPortal').exists()).toBe(false); | |||
expect(onHide).toHaveBeenCalled(); | |||
}); | |||
it('should not open when pointer goes away quickly', () => { | |||
const onShow = jest.fn(); | |||
const onHide = jest.fn(); | |||
const wrapper = shallowRenderTooltipInner({ onHide, onShow }); | |||
wrapper.find('#tooltip').simulate('pointerenter'); | |||
wrapper.find('#tooltip').simulate('pointerleave'); | |||
jest.runOnlyPendingTimers(); | |||
wrapper.update(); | |||
expect(wrapper.find('TooltipPortal').exists()).toBe(false); | |||
}); | |||
it('should not render tooltip without overlay', () => { | |||
const wrapper = shallowRenderTooltip(); | |||
expect(wrapper.type()).toBe('div'); |
@@ -22,16 +22,18 @@ exports[`should render 1`] = ` | |||
onPointerEnter={[Function]} | |||
onPointerLeave={[Function]} | |||
/> | |||
<div | |||
aria-hidden={true} | |||
className="tooltip-inner sw-font-sans hidden" | |||
id="tooltip-1" | |||
role="tooltip" | |||
> | |||
<span | |||
id="overlay" | |||
/> | |||
</div> | |||
<TooltipPortal> | |||
<div | |||
aria-hidden={true} | |||
className="tooltip-inner sw-font-sans hidden" | |||
id="tooltip-1" | |||
role="tooltip" | |||
> | |||
<span | |||
id="overlay" | |||
/> | |||
</div> | |||
</TooltipPortal> | |||
</Fragment> | |||
`; | |||