I am doing a Component Test on a simple react component, which I want to render and then do some tests on.
The problem is that cy.get()
does not seem to find the component based on a data-testid
attribute.
I tested it with a simple div
and the div
can be found just fine.
I also noticed when inspecting the DOM
in the cypress runner, that the Component is not being rendered, but the contents of it are. Basically there is no <MockComponent>
it.only("renders and finds Component", () => {
cy.mount(
<ApolloProvider client={client}>
<MockComponent data-testid='mock-component' {...someData} />
<div data-testid='my-div'></div>
</ApolloProvider>
);
cy.get("[data-testid='my-div']").should('exist'); //this works
cy.get("[data-testid='mock-component']").should('exist'); //this doesn't
});
How can I get the <MockComponent>
in cypress, so that I can run tests on it?
You can't add data-id attributes directly to the the React component and have it appear on the DOM content.
All attributes (data or otherwise) that you put on MockComponent
are passed in as props to your component. This is standard for React.
So, if you examine props
inside MockComponent
, it will have a property named data-testid
with a value of mock-component
.
You will have to convert that into an attribute inside MockComponent
, on one of it's rendered elements.
Note that MockComponent
never appear in the DOM, just it's rendered children.
For example, explicitly:
const MockComponent = (props) => {
return (
<div data-testid={props["data-testid"]}>
<span>this is mock component</span>
</div>
)
}
...
cy.get("[data-testid='mock-component']") // passes
The <div>
inside MockComponent's return value is the "outer" element rendered to DOM, so that's where you need the data-id.
Or you can do it implicitly. Since someData
is part of your component API, you can split it off and assume the remainder will be utilized as attributes (without actually knowing what they are).
const MockComponent = (props) => {
const {someData, ...rest} = props;
const [data, setData] = useState(someData);
return (
<div {...rest}>
<span>this is mock component</span>
</div>
)
}
...
cy.get("[data-testid='mock-component']") // passes
One more way is to add a child to MockComponent
, which must be a real element.
All child elements are passed as props.children
, and you must render them inside the return value.
const MockComponent = (props) => {
const {someData} = props
const [data, setData] = useState(someData);
return (
<div>
<span>this is mock component</span>
{props.children}
</div>
)
}
...
cy.mount(
<MockComponent {...someData} >
<span data-testid='mock-component-child' ></span>
</MockComponent>
);
cy.get("[data-testid='mock-component-child']") // passes
.parent() // outer element of MockComponent