I'm currently conducting a Cypress test on my component. This specific component utilizes the useRouter hook from next/navigation within a button to navigate back to another page.
import { useRouter } from "next/navigation";
import { VStack, Heading, Text, Button, Box, HStack } from "@chakra-ui/react";
const ForgotPassword = () => {
const [usersEmails, setUsersEmails] = useState<String[]>([]);
const [email, setEmail] = useState("");
const [error, setError] = useState(false);
const router = useRouter()
useEffect(() => {
const fetchEmails = async () => {
const { error, data } = await supabase.from("users").select("email");
if (error) {
console.log(error);
} else {
const emailArray = data.map((user) => user.email);
setUsersEmails(emailArray);
}
};
fetchEmails();
}, [supabase]);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
};
return (
<HStack h="100vh">
<Box>
<VStack w="full" maxW="md">
<Heading as="h3" size="lg" color="#006bb2" alignSelf="flex-start">
Forgot Password
</Heading>
<Text mb="15px">
Enter your email and we"ll send a link to reset your password
</Text>
<form onSubmit={handleSubmit}>
<input
type="email"
id="email"
name="email"
placeholder="<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="54312c3539243831143139353d387a373b39">[email protected]</a>"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
{error && (
<Text mt="5px" color="red">
We cannot find your email
</Text>
)}
<button>
Submit
</button>
</form>
<Button
leftIcon={<ArrowBackIcon />}
color="gray.500"
_hover={{ color: "#006bb2", cursor: "pointer" }}
variant="link"
onClick={() => router.push("/login")}
>
Back to Login
</Button>
</VStack>
</Box>
</HStack>
);
};
export default ForgotPassword;
Upon mounting the component, I encountered an error in Cypress:
(uncaught exception)Error: invariant expected app router to be mounted
The aforementioned error originates from the application code, not Cypress. invariant expected app router to be mounted
If I remove the "import useRouter" line, comment out "const router = useRouter()", and eliminate "router.push("/login")", then the component successfully mounts without any errors from Cypress.
I attempted the next/router & next/link solution mentioned in Cypress docs
import React from 'react'
import ForgotPassword from './page'
import Router from 'next/router'
describe('Testing the forgot password component', () => {
context('stubbing out `useRouter` hook', () => {
let router
beforeEach(() => {
router = {
push: cy.stub().as('router:push')
}
cy.stub(Router, 'useRouter').returns(router)
})
it('checks if user email exits in db', () => {
cy.mount(<ForgotPassword />)
cy.get('input[name="email"]').type("<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="dbb1b4b3b5bfb4be9bbea3bab6abb7bef5b8b4b6">[email protected]</a>");
// cy.get('button').click()
// cy.get('@routerBack').should((mock) => {
// expect(mock).to.have.been.calledOnce
// })
})
})
})
Despite attempting these adjustments, Cypress continues to throw the same error "(uncaught exception)Error: invariant expected app router to be mounted," resulting in the failure to mount the component.
To address this issue, I modified the line import Router from 'next/router'
to
import Router from 'next/navigation'
, subsequently transforming the Cypress error into:
Trying to stub property 'useRouter' of undefined
Due to this error occurring during a before-each hook, the remaining tests in the current suite are being skipped: stubbing out useRouter hook