Component without forwardRef passes the test
I have a working Preact component and a working test in Vitest. Working minimized samples:
Component
import { ChangeEvent } from 'preact/compat';
export function DateInput({
value,
setValue,
label,
}: {
value: string;
setValue: (value: string) => void;
label: string;
}) {
const storeValue = (e: ChangeEvent): void => {
// console.log('event fired'); --> Fires
const elem: HTMLInputElement = e.currentTarget as HTMLInputElement;
setValue(elem.value);
};
return (
<>
<label htmlFor="test-id">{label}</label>
<input type="date" value={value} id="test-id" onChange={storeValue} />
</>
);
}
Test (passing)
it.only('should update state when date is changed', async () => {
const setValue = vi.fn();
const { container } = render(
<DateInput
value={m.valueOutput1} // "2024-01-30"
setValue={setValue}
label={m.customLabel} // "Test label:"
/>
);
const htmlInput: HTMLInputElement | null = queryByLabelText(
container as HTMLElement,
m.customLabel
);
if (htmlInput) {
await act(() => {
fireEvent.change(htmlInput, { target: { value: m.valueOutput2 } }); // "2024-01-31"
});
await waitFor(() => {
expect(setValue).toHaveBeenCalledOnce(); // Passing without forwardRef, failing with it
});
}
});
Adding forwardRef makes the exact same test not pass anymore
Updating the test as seen below makes the test fail with message:
AssertionError: expected "spy" to be called once, but got 0 times
201| await waitFor(() => {
202| expect(setValue).toHaveBeenCalledOnce();
| ^
203| });
Component adjusted with forwardRef
import { Ref } from 'preact';
import { ForwardedRef, forwardRef, ChangeEvent } from 'preact/compat';
export const DateInput = forwardRef(function DateInput(
{
value,
setValue,
label,
}: {
value: string;
setValue: (value: string) => void;
label: string;
},
ref: ForwardedRef<HTMLElement>
) {
const storeValue = (e: ChangeEvent): void => {
// console.log('event fired'); --> Does not fire anymore
const elem: HTMLInputElement = e.currentTarget as HTMLInputElement;
setValue(elem.value);
};
return (
<>
<label htmlFor="test-id">{label}</label>
<input
type="date"
value={value}
id="test-id"
onChange={storeValue}
ref={ref as Ref<HTMLInputElement>}
/>
</>
);
});
What I tried so far
- Googling for 4 hours didn't yield anything related exactly to my problem.
- I tried both with and without async functions in tests (
actandwaitFor) but nothing changed. - I verified (via logging all the steps) that all the operations in the test execute in the same order as written.
- Adding a
React.createRef()reference to the test component didn't solve my issue either. - It seems the
onChangeevent does not trigger at all while usingforwardRefbecause I never reach it, even when putting a breakpoint directly inside the event:
...
<input // <-- breakpoint here does trigger
type="date"
value={value}
id="test-id"
onChange={e => {
storeValue(e); // <-- breakpoint here does not trigger
}}
ref={ref as Ref<HTMLInputElement>}
/>
...