feat(fireEvent): make read-only event target properties definable
What:
This makes read-only properties of the target element like scrollWidth definable through fireEvent or createEvent.
Why:
Because as of now it's not possible to test events with read-only target properties. If a component for example makes use of scrollWidth to calculate the scroll width inside a scroll event and thus applied some sort of limit to the scroll, it can't be tested for that event.
For example, this test throws an error but passes after the changes in this PR.
it("scrolls the list to right", async () => {
render(<TestComponent length={20} />);
const list = screen.getByRole("list");
await act(async () => {
fireEvent.scroll(list, { target: { scrollWidth: 100, scrollLeft: 10 } });
});
expect(screen.getByText("List is scrolled")).toBeTruthy();
});
How:
By using Object.defineProperties and modifying the read-only target properties. The solution is the same as or similar to handling files but it's generic for all other properties as well.
Checklist:
- [x] Documentation added to the docs site
- [x] Tests
- [x] TypeScript definitions updated
- [x] Ready to be merged
This pull request is automatically built and testable in CodeSandbox.
To see build info of the built libraries, click here or the icon next to each commit SHA.
Latest deployment of this branch, based on commit b901f7ff9fc7b4cc938d8e3003be7b90e094de69:
| Sandbox | Source |
|---|---|
| react-testing-library-examples | Configuration |
I will add tests and other items on the checklist once I can get some sort of confirmation if this is all right. There may be a reason to keep the read-only target properties as is that I don't know of. So please let me know if this is fine so I can move forward.
Peace. :)
Codecov Report
Merging #1020 (b901f7f) into main (edffb7c) will not change coverage. The diff coverage is
100.00%.
@@ Coverage Diff @@
## main #1020 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 24 24
Lines 998 999 +1
Branches 326 326
=========================================
+ Hits 998 999 +1
| Flag | Coverage Δ | |
|---|---|---|
| node-12 | 100.00% <100.00%> (ø) |
|
| node-14 | 100.00% <100.00%> (ø) |
|
| node-16 | 100.00% <100.00%> (ø) |
Flags with carried forward coverage won't be shown. Click here to find out more.
| Impacted Files | Coverage Δ | |
|---|---|---|
| src/events.js | 100.00% <100.00%> (ø) |
:mega: We’re building smart automated test selection to slash your CI/CD build times. Learn more
I will add tests and other items on the checklist once I can get some sort of confirmation if this is all right. There may be a reason to keep the read-only target properties as is that I don't know of. So please let me know if this is fine so I can move forward.
Peace. :)
As far as I can tell, the an Element's scrollWidth property is read-only.
What does the rest of your code do to the scrollWidth? I would think it shouldn't change after emitting the event.
What does the rest of your code do to the scrollWidth?
The code just reads and uses the scrollWidth which comes from a scroll event emitted by the browser.
I would think it shouldn't change after emitting the event.
It doesn't. But I think the emitted event from the test (as shown in the example) should be able to specify it as part of the event itself. So the read-only usage of scrollWidth by the component under test can be tested.
What I am trying to test is this scroll behavior.
Before horizontal scroll, the left arrow is invisible:

After horizontal scroll, the component uses scrollLeft and scrollWidth to determine if there is sufficient scroll to show the left arrow:

For firing the event with this horizontal scroll, I need to specify scrollWidth and scrollLeft properties.