I can get the componenets to work and do their stuff, but I don’t understand how to test the react-aria-components properly. I know that they have already been thoroughly tested by the creators of this library, but I want to make sure the componenets display the right things and fire the right events that I passed in as custom props.
Here is a basic example.
import { render, screen } from "@testing-library/react";
import { describe, it, expect } from "vitest";
import { Button } from "react-aria-components";
describe("Button Component", () => {
it("renders a regular button", () => {
render(<button>Click Me</button>);
const buttonElement = screen.getByRole("button");
expect(buttonElement).toBeInTheDocument();
});
it("renders a react-aria-button", () => {
render(<Button>Click Me</Button>);
const buttonElement = screen.getByRole("button");
expect(buttonElement).toBeInTheDocument();
});
});
I set up the testing environment and import the stuff I need, including the Button component from the library.
I then run 2 tests, both of which render a simple button. The first test renders a regular/manually created button, and the second one uses the <Button> component from the library.
The results:
TypeError: Cannot read properties of null (reading 'useContext')
❯ Button Component (2)
✓ renders a regular button (passed)
× renders a react-aria-button (failed)
...
Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
I then looked at the source code of the Button component, and realized I don’t want to rebuild the entire thing using only react-aria (not react-aria-components).
I also looked at the react docs on “Rules of Hooks”. I understand what the rule means, but I have no idea what I have to do in this situation.
Lets say I want to use my button in a little more complex manner:
export function Btn_profilePreviewIcons({
icons,
onClick = () => alert("No function provided"),
visibleIcon_COUNT = 1,
IS_open,
activeDigit,
aria_LABEL,
}) {
const [dance, setDance] = useState(false);
const handleDance = () => {
if (dance) return;
setDance(true);
setTimeout(() => {
setDance(false);
}, 1000);
};
const displayedIcons = icons ? icons.slice(0, visibleIcon_COUNT) : [];
const remainingTagsCount =
displayedIcons.length > 0 ? Math.max(0, icons.length - visibleIcon_COUNT) : 0;
return (
<Button
className={css["btn-show-icons"]}
data-open={IS_open}
onClick={() => {
onClick();
handleDance();
}}
data-dance={dance}
data-testid="btn-profile-preview-icons"
aria-label={aria_LABEL}
>
{activeDigit}
{icons &&
displayedIcons.map((icon) => (
<img
key={icon}
src={icon}
alt=""
className={css.icon}
data-testid="tag-preview-btn-icon"
/>
))}
{!icons && <p data-testid="no-tags">No tags</p>}
{remainingTagsCount > 0 && visibleIcon_COUNT && (
<>
{remainingTagsCount === 1 ? (
icons && (
<img
src={icons[visibleIcon_COUNT]}
alt=""
className={css.icon}
data-testid="tag-preview-btn-icon"
/>
)
) : (
<p data-testid="hidden-icon-count">+{remainingTagsCount}</p>
)}
</>
)}
</Button>
);
}
And I am only talking about unit testing. How in the world should I do integration tests with more complex components like a Date picker if I can’t implement them in my tests?
I’m a rookie. Would appreciate any help I could get.
Domas is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.