cavy
cavy copied to clipboard
[RFC] Add jsx pragma integration
Hi. First of all thank you for the cavy library. I started using it and I was thinking if can be possible to reduce the normal code impact, removing wrap functions, useCavy, HOC etc with a jsx pragma that replaces createElement with a simple wrap.
I already executed some test and created a custom jsx function like this:
// index.js of cavy-jsx
let testStore = null;
export function setTestStore(store) {
testStore = store;
}
export function cavyJsx(type, props, children) {
if ('cavyTestId' in props && testStore) {
const WrappedType = wrap(type);
const generateTestHook = cavy(testStore);
const newProps = {...props, ref: generateTestHook(props.cavyTestId)};
return React.createElement(WrappedType, newProps, children);
}
return React.createElement.apply(undefined, arguments);
}
//index.test.js
import { setTestStore } from "cavy-jsx";
const testHookStore = new TestHookStore();
setTestStore(testHookStore);
//LoginScreen.js
/** @jsx cavyJsx */
/** @jsxFrag React.Fragment */
import { cavyJsx } from 'cavy-jsx';
...
<TextInput
value={password}
cavyTestId="LoginScreen.PasswordInput"
onChangeText={setPassword}
/>
<TextInput
value={password}
cavyTestId="LoginScreen.PasswordInput"
onChangeText={setPassword}
/>
<Button
cavyTestId="LoginScreen.Button"
onPress={doLogin}
>
<Text>Login</Text>
</Button>
this way the code stays clean but cavy still works and can also wrap components automatically. I was also trying to configure @babel/plugin-transform-react-jsx to automatically inject the pragma with no success but i thing it can be feasible. The solution with the eplicit jsx pragma already works.
What do you thing?
@rams23 this is a really interesting approach, thank you for investigating and trying stuff out. Last time we explored this, we were looking at a possible Babel plugin but I quite like the JSX pragma idea.
We'll be exploring this further!
Thanks for the fast reply @jalada . I'll let you know what I can find and maybe submit a PR. The pragma is working but it must by spread everywhere. I'm trying to exploit @wordpress/babel-plugin-import-jsx-pragma and @babel/plugin-transform-react-jsx to directly inject it. Another thing that I'm trying to do is use declaration merging to add cavyTestId as default props (like children) to Component definition.
For anyone coming to this; see my comment on the PR for an update!
that's a great idea @rams23 @jalada @rams23 what do you think about reusing the standard "testID" prop instead of introducing a new additional prop? the benefit i see:
- not need to introduce new prop
- for existing code base already includes testing with react-testing or other - this would be the complementary without the need to change/add any code for adding cavy.
@orizens agreed, no reason why not. I'd really love one day for React Native to support querying for elements in the tree with the testID
prop directly without having to build a hack like this. But in the mean time, using a pragma to get access would be an option.