[Mock] missing some hooks from official mock
Description
When following the official guide for setting up the test environment, the mock is injected, but it does not cover the whole API of the library, more especially the parts defined under src/renderer and src/views.
I have a component using among other things useCanvasRef, that I use to invoke makeImageSnapshot() as illustrated here.
The tests break when using the official mock, as useCanvasRef is not defined.
TypeError: (0 , _reactNativeSkia.useCanvasRef) is not a function
This is the first hook I am facing an error with, but I noticed some other methods also failing:
-
useTouchHandler
TypeError: (0 , _reactNativeSkia.useTouchHandler) is not a function
-
useValue
TypeError: Cannot read properties of undefined (reading 'createValue')
Version
v0.1.137
Steps to reproduce
- Build a component using
useCanvasRef() - Build a test case for it
- Setup the environment as instructed
- Run the tests (I am using jest)
Result: test showing the following error
TypeError: (0 , _reactNativeSkia.useCanvasRef) is not a function
Snack, code example, screenshot, or link to a repository
An example component:
// TestComponent.tsx
import { Button, View } from 'react-native';
import { Canvas, SkImage, useCanvasRef } from '@shopify/react-native-skia';
const TestComponent: React.FC<{
onSnapshot?(snapshot: SkImage): void
}> = ({ onSnapshot }) => {
const canvas = useCanvasRef();
const onPress = () => {
const snapshot = canvas.current?.makeImageSnapshot();
onSnapshot?.(snapshot);
}
return (
<View>
<Canvas ref={canvas} style={{ width: 40, height: 40 }}>
<Rect x={10} y={10} width={20} height={20} color="red" />
</Canvas>
<Button title="snapshot" onPress={onPress} />
</View>
);
}
An example test case:
// TestComponent.test.tsx
import {fireEvent, render} from '@testing-library/react-native'
import TestComponent from '[...wherever...]';
describe('TestComponent', () => {
it('should take a snapshot', async () => {
const onSnapshot = jest.fn();
const {getByText} = render(<TestComponent onSnapshot={onSnapshot} />);
await fireEvent.press(getByText('snapshot'));
expect(onSnapshot).toHaveBeenCalled();
});
})
I am willing to contribute on the mock, but I am struggling a bit to understand:
- wether the
src/renderer/*subfolder is intentionally not exported from the mock? (... and should rather be mocked separately? 🤔) - same question about
src/views(e.g.useTouchHandler()) - why is
useValue()throwing, while the Skia methodcreateValue()is supposed to be mocked?
One thing that would help with the mock would be to load CanvasKit. Then you can test everything as you would have a full implementation of the module (this is what we have for our tests: https://github.com/Shopify/react-native-skia/blob/main/package/src/renderer/tests/documentation/getting-started/HelloWorld.spec.tsx#L51).
Do you know if it's possible to load a Mock asynchronously? (allowing us to use CanvasKit in the mock)
@flo-sch We also run tests for the example app at: https://github.com/Shopify/react-native-skia/blob/main/example/src/App.spec.tsx It would be fantastic if you could add failing tests there so we know that we got you covered.
Awesome, I missed those, will add tests there :)
Do you know if it's possible to load a Mock asynchronously? (allowing us to use CanvasKit in the mock)
I have no idea, never faced that scenario so far, but I guess I could try
I added some (intentionally failing) tests, took the already existing ExportableCanvas as component, but I could create a custom one as documented here if you prefer?
Do you know if it's possible to load a Mock asynchronously? (allowing us to use CanvasKit in the mock)
So, I tried writing a custom test environment extending the default "node" one, I think it might be a suitable option?
It provides a setup and a teardown function (which I am not sure we need here), both can be async, and I managed I think to load the Skia web API within setup().
However, one caveat is that jest itself cannot transpile such an environment, so I updated the example test script to use ts-node/register instead...
This is a bit cumbersome but works.
Let me know what you think about that approach? If that works, I was thinking we could potentially export the jest environment itself to simplify the setup in external projects?
PS: it does not fix the missing hooks of course.
Any update on this? I'm getting the same error in my jest tests.