cloudfour / cloudfour/pleasantest
Issue clicking buttons that get their size from an inner image
- Dominant language
- TypeScript
- Stars
- 175
- Forks
- 2
- Avg merge
- 1m
- Merged PRs (30d)
- 1
Description
I'm running into issues writing a test for a "Media Selector" component. It looks like this:

It's a set of buttons, with each button containing an image.
Here's the component markup:
```tsx
import { CheckMark } from '../../icons/check-mark';
import { MediaSelectorItem } from './media-selector-item';
import './media-selector.scss';
export function MediaSelector({
selectedItem,
items,
onChange,
}: {
selectedItem: MediaSelectorItem;
items: MediaSelectorItem[];
onChange: (value: MediaSelectorItem) => void;
}) {
return (
{items.map((item: MediaSelectorItem) => {
// If a custom aspect ratio has been passed in, apply it
const imageStyles = item.aspectRatio
? { '--api-x_media-aspect-ratio': item.aspectRatio }
: {};
return (
onChange(item)}
>
);
})}
);
}
```
And here's my test:
```tsx
import { withBrowser, PleasantestUtils } from 'pleasantest';
async function setup(utils: PleasantestUtils) {
await utils.runJS(`
import { render } from 'preact';
import { useState } from 'preact/hooks';
import { Root } from '../root/root';
import { MediaSelector } from './media-selector';
// Preact's render function doesn't clear this properly
document.body.innerHTML = '';
function MediaSelectorExample() {
const items = [
{
src: 'https://cloudinary-marketing-res.cloudinary.com/image/upload/h_160/sneakers-wide.jpg',
alt: 'sneakers',
value: 'sneakers-wide'
},
{
src: 'https://cloudinary-marketing-res.cloudinary.com/image/upload/h_160/car.jpg',
alt: 'car',
value: 'car'
}
];
const [option, setOption] = useState(items[0]);
return (
);
}
render((
), document.body);
`);
}
test(
'Confirm the buttons are pressed correctly',
withBrowser(async ({ utils, screen, user }) => {
await setup(utils);
const firstItem = await screen.getByRole('button', {
name: 'sneakers',
});
const secondItem = await screen.getByRole('button', {
name: 'car',
});
// We set the first item as selected
await expect(firstItem).toHaveAttribute('aria-pressed', 'true');
await expect(secondItem).toHaveAttribute('aria-pressed', 'false');
// I'm not sure why this is necessary.
// I'm opening a Pleasantest issue to discuss.
await new Promise((resolve) => setTimeout(resolve, 500));
// Clicking the first item should do nothing. It's already selected
await user.click(firstItem, { force: true, targetSize: false });
// The first item should still be pressed
await expect(firstItem).toHaveAttribute('aria-pressed', 'true');
await expect(secondItem).toHaveAttribute('aria-pressed', 'false');
// Clicking the second item should select it
await user.click(secondItem, { force: true, targetSize: false });
// The user clicked the second item. It should be selected
await expect(secondItem).toHaveAttribute('aria-pressed', 'true');
await expect(firstItem).toHaveAttribute('aria-pressed', 'false');
})
);
```
This test is passing, but only because I've put a 500ms timeout in the middle of it. If I remove this, then I can't click the buttons.
I ran into a few different issues:
- First off it said the buttons were too small or not visibly.
- I figured this was because the image hadn't loaded and the button had no width. I added an aspect ratio to the image CSS but it still didn't work
- Then I added `{ force: true, targetSize: false }`. At this point it worked _sometimes_ but failed other times with a different error:
- Then it said the buttons are "either not clickable or not an HTMLElement"
- At this point I added the timeout and it fixed it.
I'm not sure what's going on. This is a private repo but you should have access. Here's the PR: https://github.com/cloudfour/cld-api-explorer/pull/9
Let me know if you need more info or would like to troubleshoot together.
Thanks!
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.