Skip to content

Commit 714475b

Browse files
committed
fix: Update simple test page
1 parent 3e2c01a commit 714475b

File tree

3 files changed

+115
-36
lines changed

3 files changed

+115
-36
lines changed

pages/tooltip/simple.page.tsx

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ export default function TooltipSimple() {
4444
const linkRef = useRef<HTMLDivElement>(null);
4545
const codeRef = useRef<HTMLDivElement>(null);
4646

47+
// Password input
48+
const [showPassword, setShowPassword] = useState(false);
49+
const passwordRef = useRef<HTMLInputElement>(null);
50+
4751
return (
4852
<article>
4953
<h1>Tooltip</h1>
@@ -435,6 +439,55 @@ export default function TooltipSimple() {
435439
</div>
436440
</SpaceBetween>
437441
</section>
442+
443+
<section id="aria-describedby-example">
444+
<h3>ARIA Described-by Example</h3>
445+
<div
446+
style={{ display: 'inline-block' }}
447+
onMouseEnter={() => setShowPassword(true)}
448+
onMouseLeave={() => setShowPassword(false)}
449+
>
450+
<label htmlFor="password-input" style={{ display: 'block', marginBottom: '4px' }}>
451+
Password:
452+
</label>
453+
<input
454+
ref={passwordRef}
455+
id="password-input"
456+
type="password"
457+
placeholder="Enter password"
458+
style={{
459+
padding: '8px',
460+
border: '1px solid #ccc',
461+
borderRadius: '4px',
462+
}}
463+
onFocus={() => setShowPassword(true)}
464+
onBlur={() => setShowPassword(false)}
465+
/>
466+
{showPassword && (
467+
<Tooltip
468+
content={
469+
<div>
470+
<p>
471+
<strong>Password Rules:</strong>
472+
</p>
473+
<ul style={{ margin: 0, paddingLeft: '16px' }}>
474+
<li>Minimum of 8 characters</li>
475+
<li>
476+
Include at least one lowercase letter, one uppercase letter, one number and one special
477+
character
478+
</li>
479+
<li>Unique to this website</li>
480+
</ul>
481+
</div>
482+
}
483+
getTrack={() => passwordRef.current}
484+
position="bottom"
485+
onEscape={() => setShowPassword(false)}
486+
trackKey="password-rules"
487+
/>
488+
)}
489+
</div>
490+
</section>
438491
</SpaceBetween>
439492
</ScreenshotArea>
440493
</article>

src/tooltip/__integ__/tooltip.test.ts

Lines changed: 57 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,60 @@
33
import { BasePageObject } from '@cloudscape-design/browser-test-tools/page-objects';
44
import useBrowser from '@cloudscape-design/browser-test-tools/use-browser';
55

6-
import createWrapper from '../../../../lib/components/test-utils/selectors';
7-
8-
import tooltipStyles from '../../../../lib/components/tooltip/styles.selectors.js';
9-
10-
test(
11-
'should not close any wrapping modals when the tooltip detects an Escape keypress',
12-
useBrowser(async browser => {
13-
await browser.url('/#/light/modal/with-tooltip');
14-
const page = new BasePageObject(browser);
15-
16-
const openButtonSelector = createWrapper().findButton().toSelector();
17-
await page.waitForVisible(openButtonSelector);
18-
await page.click(openButtonSelector);
19-
20-
const modal = createWrapper().findModal();
21-
const slider = modal.findContent().findSlider();
22-
await page.waitForVisible(slider.toSelector());
23-
24-
// Slider on the page is set at 50% on purpose. `hoverElement` will move the
25-
// mouse to the center of the track where the "thumb" is.
26-
await page.hoverElement(slider.findNativeInput().toSelector());
27-
await page.waitForVisible(`.${tooltipStyles.root}`);
28-
29-
// Press once to close the tooltip
30-
await page.keys(['Escape']);
31-
await expect(page.isDisplayed(`.${tooltipStyles.root}`)).resolves.toBe(false);
32-
await expect(page.isDisplayed(modal.toSelector())).resolves.toBe(true);
33-
34-
// Press again to close the modal
35-
await page.keys(['Escape']);
36-
await expect(page.isDisplayed(modal.toSelector())).resolves.toBe(false);
37-
})
38-
);
6+
import tooltipStyles from '../../../lib/components/tooltip/styles.selectors.js';
7+
8+
class TooltipPageObject extends BasePageObject {
9+
async waitForTooltip() {
10+
console.log('Waiting for tooltip with selector:', `.${tooltipStyles.root}`);
11+
await this.waitForVisible(`.${tooltipStyles.root}`);
12+
}
13+
14+
isTooltipVisible() {
15+
return this.isDisplayed(`.${tooltipStyles.root}`);
16+
}
17+
18+
getTooltipContent() {
19+
return this.getText(`.${tooltipStyles.root}`);
20+
}
21+
}
22+
23+
describe('Tooltip', () => {
24+
test(
25+
'shows tooltip on hover, checks content and closes with escape',
26+
useBrowser(async browser => {
27+
await browser.url('/#/light/tooltip/simple');
28+
const page = new TooltipPageObject(browser);
29+
30+
// Wait for page to load
31+
await page.waitForVisible('[data-testid="hover-button"]');
32+
33+
// // Test hover
34+
await page.hoverElement('[data-testid="hover-button"]');
35+
36+
// await page.waitForTooltip();
37+
await expect(page.isTooltipVisible()).resolves.toBe(true);
38+
console.log('JJAAAA');
39+
40+
const content = await page.getTooltipContent();
41+
expect(content).toBe('Tooltip positioned on top');
42+
console.log(content);
43+
44+
await browser.keys('Escape');
45+
await expect(page.isTooltipVisible()).resolves.toBe(false);
46+
47+
// await expect(page.isTooltipVisible()).resolves.toBe(false);
48+
49+
// Verify content is not accessible when tooltip is hidden
50+
// await expect(page.getTooltipContent()).resolves.toBe('');
51+
// expect(content).toBe('Expected tooltip text');
52+
// // Move away to hide tooltip
53+
// await page.hoverElement('body');
54+
// await expect(page.isTooltipVisible()).resolves.toBe(false);
55+
56+
// // Test keyboard focus
57+
// await page.click('[data-testid="hover-button"]');
58+
// await page.waitForTooltip();
59+
// await expect(page.isTooltipVisible()).resolves.toBe(true);
60+
})
61+
);
62+
});

src/tooltip/internal.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,19 +34,21 @@ export default function InternalTooltip({
3434
}: InternalTooltipComponentProps) {
3535
const baseProps = getBaseProps(restProps);
3636
const trackRef = React.useRef<HTMLElement | SVGElement | null>(null);
37-
const tooltipId = React.useMemo(() => generateTooltipId(), []);
37+
const tooltipId = React.useMemo(() => {
38+
return trackKey ? `tooltip-${trackKey}` : generateTooltipId();
39+
}, [trackKey]);
3840

3941
// Update the ref with the current tracked element
4042
React.useEffect(() => {
4143
const element = getTrack();
4244
trackRef.current = element;
4345
// Add aria-describedby to the tracked element for accessibility
44-
if (element) {
46+
if (element && element.nodeType === Node.ELEMENT_NODE) {
4547
element.setAttribute('aria-describedby', tooltipId);
4648
}
4749
return () => {
4850
// Clean up aria-describedby when tooltip unmounts
49-
if (element) {
51+
if (element && element.nodeType === Node.ELEMENT_NODE) {
5052
element.removeAttribute('aria-describedby');
5153
}
5254
};

0 commit comments

Comments
 (0)