I would like to be able to print the results of wrapper.find('some selector')
I am mounting a react component
wrapper = mount(
<SomeReactComponent />
);
And I am able to print the whole contents of wrapper with console.log(wrapper.debug()) but I was wondering if there is some way to print specific results. I tried console.log(wrapper.find('some selector').debug()) but nothing prints.
How can I print more specific parts of the html rendered in wrapper?
Since you are using mount method I guess that you are using enzyme for rendering.
In that case, you can use simple find that has one argument selector. That selector is regular query selector.
const wrapper = mount(<MyComponent />);
console.log(wrapper.find('.my-component').at(0).html())
NOTE:
If you have more components that have my-component it will return array of elements so it is needed to have that .at(0) to select one item.
html() will print out plain html code.
API Reference:
https://enzymejs.github.io/enzyme/docs/api/ReactWrapper/find.html
Related
I'm writing some tests for a React app using Testing Library. I want to check that some text appears, but I need to check it appears in a particular place because I know it already appears somewhere else.
The Testing Library documentation for queries says that the getByText query takes a container parameter, which I guessed lets you search within that container. I tried doing this, with the container and text parameters in the order specified in the docs:
const container = getByTestId('my-test-id');
expect(getByText(container, 'some text')).toBeTruthy();
and I get an error: matcher.test is not a function.
If I put the params the other way round:
const container = getByTestId('my-test-id');
expect(getByText('some text', container)).toBeTruthy();
I get a different error: Found multiple elements with the text: some text
Which means it's not searching inside the specified container.
I think I'm not understanding how getByText works. What am I doing wrong?
Better to use within for this sort of things:
render(<MyComponent />)
const { getByText } = within(screen.getByTestId('my-test-id'))
expect(getByText('some text')).toBeInTheDocument()
Another way to do this
import {render, screen} from '#testing-library/react';
...
render(<MyComponent />);
expect(screen.getByTestId('my-test-id')).toHaveTextContent('some text');
Note it is now recommended to use screen instead of the results of render.
(StackOverflow post the points to a KC Dobbs Article explaining why: react-testing-library - Screen vs Render queries)
This way you can be more precise, focusing in specific item:
expect(queryByTestId("helperText")?.textContent).toContain("Help me!");
What does putting an element inside Svelte Component mean?
Eg. this code:
const target = document.createElement('div');
// render the component in the new element
const sample = new Sample({ target });
Like, here, in the given linked code, author is doing that:
https://github.com/rspieker/jest-transform-svelte/blob/master/example/test/Sample.spec.js#L8
What does this do? Is it putting Svelte component inside a div? Is it a Svelte syntax to put the element inside the constructor of the Svelte component?
Yes, that snippet is initializing the Svelte component named Sample and rendering it within the target div. The target property of a Svelte component constructor's options parameter is the only required property.
For more information, check out Svelte's components documentation.
It is the place where in your document the component will be rendered. Normally you would use a very specific location like body or a div with a certain id.
In this case however you are not actually rendering a page but merely testing a component so it doesn't matter where the div is.
You can find more info on testing with Jest here https://jestjs.io/
I am using React Modal.
I'm doing something like this:
React.createClass({
render() {
return <ReactModal
isOpen={true}
>{content}</ReactModal>
}
});
Now {content} might have an input field inside. I know I can't use ref in this case. If I use getDOMNode, that can get me the wrapper, but I don't know of an easy way to find a child by class name. Am I supposed to use native code there?
React components are js objects only. In worst case if you want to access the child you can print the component in your browser console and expand it. You can see the child components, from there also you can access refs and all.
I'm creating a react file tree, and I have the tree setup as a React component. The tree can take a contents prop that is an array of either strings, or other <Tree /> components (this enables the nested file structure UI). These tree components can be nested indefinitely.
I need to register a click event on the children of the nested tree components, but I'm having trouble getting it to work beyond the first level of nesting. A simplified example of what I'm dealing with:
//In App - the top level component
const App = React.createClass({
_handleChildClick () {
console.log("this is where all child clicks should be handled");
},
render () {
return (
<Tree
handleChildClick={this._handleChildClick}
contents={[
<Tree />
]}
/>
);
}
});
//And in the tree component
<div onClick={this.props.handleChildClick}></div>
If you want to see more detail - here's the github repo.
I tried researching this question and saw people using {...this.props} but I'm not sure if that applies to my scenario - if it does, I couldn't get it to work.
Thanks for any help on this.
The reason why the click handling does not work beyond the first level is because your second level Tree component (the one inside the contents array) does not get the appropriate prop handleChildClick passed in. (BTW I think the convention is to call the prop onChildClick while the handler function is called handleChildClick - but I digress.)
Do I understand correctly that you actually want to inform each layer from the clicked component up to the top? For this to happen, you need to extend the props of the tree component that is inside the contents array - it needs to receive the click handler of its parent component. Of course, you cannot write this down statically, so it needs to be done dynamically:
Your Tree component, before actually rendering its children, should extend each of them with the component's click handler, which can be done using the function React.cloneElement (see API documentation and a more detailed discussion). Directly applying this to your component makes things a bit messy, because you are passing the component's children in a prop, so you need to figure out which prop to modify. A bit of a different layout would help you quite a lot here:
<Tree handleChildClick={this._handleChildClick}>
<Tree />
</Tree>
looks nicer IMHO and makes the structure much clearer. You can access the inner components via this.props.children, and cloneElement will be much simpler to use.
So, in your Tree component, you could have a render method like this:
render () {
const newChildren = this.props.children.map(child =>
React.cloneElement(child, {onChildClick: this._handleChildClick}));
return (
<div>{newChildren}</div>
);
}
Please note that this code will not work if you have a mixture of strings and Tree components, therefore my third and last suggestion would be to wrap those strings into a very thin component to allow for easier handling. Alternatively, you can of course do a type comparison inside the map.
I have a React component rendered directly on the "root" (document.body), I want to get this element using TestUtils but I do not want to keep a reference to this element. Is there any way to do that?
Basically I want something like this:
React.addons.TestUtils.findRenderedComponentWithType(document.body, MyReactClass);
But this does not work (passing null or undefined as the first parameter does not work either). I am left wondering if there is any "root" React Component Tree that I can get a reference to.
If it is for Unit test purpose, you don't need to do that, if you are testing the component MyReactClass, just do :
const props = {//some mocked props}
const element = TestUtils.renderIntoDocument(<MyReactClass {...props}/>);
element will contains the element.
Hope I correctly understood your question...