Closed danr-za closed 1 year ago
Hi @danr-za, Thanks for logging this. We are tantalizingly close to releasing the new component testing workflow with Cypress 10.0. After the 10.0 has been released we will revisit your issue and determine if it is still relevant post release.
CT tests do not accommodate route changes, that is an E2E concern. You should be able to stub the router, please check out our docs on the subject.
I just found this issue. I disagree with the position about testing URLs in component tests. I've been very excited by this feautre, I'm mainly using it for integration tests, ie testing the whole FE part of the app with intercepted endpoints. Long term I want to extend this to make the test code share-able between integration and e2e tests, but I'm not there yet.
Anyway, my point is that there is significant value in being able to see how the URL changes via SPA-router operations in component tests. I can confirm that the router itself works perfectly (I'm using a React app), I'm able to click on links and change the page, however I cannot validate the URL itself.
I realize this is a brand new feature (ie component testing) and I must comment the cypress team for an excellent job with it. Despite its "beta" status I have had virtually no issues using it. However, I strongly encourage you to continue expanding the feature set to add things like URL testing to it. Thank you.
I've found a pretty decent workaround in the meantime, which is a similar approach to how react-router does their own internal unit testing. It's also similar to how Kent Dodds tests custom react hooks.
Create a component that renders values from react router (e.g. the path, params, etc) to the DOM, then assert about those values in the DOM.
And if you don't want the values to be visible in tests (to avoid messing with the UI or screenshots) but still accessible to cypress, you can do something like
/**
* Renders invisible search params. Assert about the URL in component tests where location info is
* not accessible to Cypress by default. This is useful for components that rely on react-router,
* e.g. those that use searchParams internally.
*/
export function RenderSearchParams() {
const [searchParams] = useSearchParams();
const paramsObj = Object.fromEntries(searchParams.entries());
return (
<div id="search-params">
{Object.keys(paramsObj).map((key) => (
<span id={`${key}:${paramsObj[key]}`} />
))}
</div>
);
}
and then in your tests
// Mount the component inside a MemoryRouter with a specific URL
cy.mount(
<MemoryRouter initialEntries={['/?foo=bar&biz=baz']}>
<RenderSearchParams />
<SomeComponent />
</MemoryRouter>
)
// Assert about the URL
cy.get('#search-params').within(() => {
cy.get('#foo:bar')
cy.get('#biz:baz')
});
or whatever type of selectors you want, so long as the DOM elements are visually hidden but still rendered in the DOM. I'm actually using data-testid
attributes in conjunction with @testing-library matchers.
You can extract this into a custom command as well, e.g.
Cypress.Commands.add('mountRouterComponent', (component, route) => {
const wrapped = (
<MemoryRouter initialEntries={[route]}>
<RenderSearchParams />
{component}
</MemoryRouter>
);
return cy.mount(wrapped);
});
and then use it like
cy.mountRouterComponent(<SomeComponent />, '/?foo=bar&biz=baz')
It would be nice to natively get info about the URL, but this seems like an OK workaround.
Current behavior
I have a component that uses react-router for navigation and I am unable to test the URL. Currently, it always returns the test file asset path. Not sure this one is 100% related - https://github.com/cypress-io/cypress/issues/15106
Desired behavior
Should be able to get router's URL
Test code to reproduce
Cypress Version
9.6.0
Other
@cypress/react
- 5.12.4