Cypress组件测试与NextJS useRouter函数

bksxznpy  于 12个月前  发布在  其他
关注(0)|答案(2)|浏览(115)

我的Navbar组件依赖于nextjs/router提供的useRouter函数来设置活动链接的样式。
我尝试使用Cypress来测试这个行为,但我不确定应该如何组织它。Cypress似乎不喜欢getRoutePathname(),并且在我的测试环境中返回undefined。
下面是我尝试测试的组件:

import Link from 'next/link'
import { useRouter } from 'next/router'

function getRoutePathname() {
  const router = useRouter()
  return router.pathname
}

const Navbar = props => {
  const pathname = getRoutePathname()

  return (
    <nav>
      <div className="mr-auto">
        <h1>Cody Bontecou</h1>
      </div>
      {props.links.map(link => (
        <Link key={link.to} href={link.to}>
          <a
            className={`border-transparent border-b-2 hover:border-blue-ninja 
            ${pathname === link.to ? 'border-blue-ninja' : ''}`}
          >
            {link.text}
          </a>
        </Link>
      ))}
    </nav>
  )
}

export default Navbar

字符串
我有Cypress组件测试运行器的框架设置,并且在硬编码pathname时能够加载组件,但是一旦我依赖于useRouter,测试运行器就不再高兴了。

import { mount } from '@cypress/react'

import Navbar from '../../component/Navbar'

const LINKS = [
  { text: 'Home', to: '/' },
  { text: 'About', to: '/about' },
]

describe('<Navbar />', () => {
  it('displays links', () => {
    mount(<Navbar links={LINKS} />)
  })
})

gcxthw6b

gcxthw6b1#

理想情况下,Next.js的useRouter应该有一个提供程序来设置路由器对象,并将组件 Package 在mount的提供程序中。在不查看代码或Next.js提供的文档的情况下,这里有一个解决方案来模拟useRouterpathnamepush

import * as NextRouter from 'next/router'

// ...inside your test:

const pathname = 'some-path'
const push = cy.stub()
cy.stub(NextRouter, 'useRouter').returns({ pathname, push })

字符串
我添加了push,因为这是最常见的用例,您可能也需要它。

jei2mxaa

jei2mxaa2#

要解决这个问题,你必须模拟NextJS Navigation路由器:
1.在cypress的mocks文件夹中创建Next Router Mock组件:

import { AppRouterContext, AppRouterInstance } from "next/dist/shared/lib/app-router-context"

const createNextRouter = (params: Partial<AppRouterInstance>) => ({
  back: cy.spy().as("back"),
  forward: cy.spy().as("forward"),
  prefetch: cy.stub().as("prefetch").resolves(),
  push: cy.spy().as("push"),
  replace: cy.spy().as("replace"),
  refresh: cy.spy().as("refresh"),
  ...params,
})

interface MockNextRouterProps extends Partial<AppRouterInstance> {
  children: React.ReactNode
}

export const NextRouterMock = ({ children, ...props }: MockNextRouterProps) => {
  const router = createNextRouter(props as AppRouterInstance)

  return <AppRouterContext.Provider value={router}>{children}</AppRouterContext.Provider>
}

字符串
1.使用此模拟路由器 Package 您的组件:

describe('<Navbar />', () => {
  it('displays links', () => {

    mount(NextRouterMock>
            <Navbar links={LINKS} />
         </NextRouterMock>
    )
  })
})

相关问题