在赛普拉斯中模拟来自下一个/导航的useRouter

问题描述 投票:0回答:1

我正在尝试在 cypress 中测试我的组件。该组件使用按钮中的 next/navigation 中的 useRouter 钩子推回到另一个页面。

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&#34;ll send a link to reset your password
      </Text>
      <form onSubmit={handleSubmit}>
        <input
          type="email"
          id="email"
          name="email"
          placeholder="[email protected]"
          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;

当我安装组件时,我收到来自 cypress 的错误

(未捕获的异常)错误:要安装不变的预期应用程序路由器

以下错误源自您的应用程序代码,而不是来自赛普拉斯。 不变的预期应用程序路由器将被安装

但是如果我注释掉“import useRouter”、“const router = useRouter()”行并删除“router.push("/login")”,那么组件就会挂载并且cypress不会抛出任何错误

我已经尝试过来自 cypress 文档的下一个/路由器和下一个/链接解决方案

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("[email protected]");

      // cy.get('button').click()

      // cy.get('@routerBack').should((mock) => {
      //   expect(mock).to.have.been.calledOnce
      // })
    })
  })

})

cypress 仍然抛出相同的“(未捕获异常)错误:不变的预期应用程序路由器要安装”错误,并且组件仍然无法安装。

我将行

import Router from 'next/router'
更改为
import Router from 'next/navigation'
并且 cypress 错误更改为

尝试存根未定义的属性“useRouter”

因为这个错误发生在每个钩子之前,我们将跳过当前套件中的剩余测试:删除 useRouter 钩子

typescript next.js cypress cypress-component-test-runner
1个回答
0
投票

未捕获的异常

Error: invariant expected app router to be mounted
可以通过将组件包装在
<AppRouterContext.Provider value={router}>
中来解决。

这是主要的修复,但还有一些次要的修复:

  • 测试中使用

    'next/router'
    ,但组件中使用
    "next/navigation"
    。两个地方的路由器应该是相同的。

  • 要从

    useRouter
    对象存根
    Router
    ,您需要使用
    命名默认导入
    import * as Router from "next/navigation"

    不是
    import Router from "next/navigation"

    这解决了错误
    Trying to stub property 'useRouter' of undefined

  • 断言中使用的别名应与存根中使用的名称相同。

    
    

  • 这是我对
NextJs 示例组件的测试

组件

calledOnce

测试

'use client' import { useRouter } from 'next/navigation' export default function Page() { const router = useRouter() return ( <button type="button" onClick={() => router.push('/dashboard')}> Dashboard </button> ) }

测试日志

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.