微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用带有 jest + MSW

如何解决如何使用带有 jest + MSW

我有一个组件,我很难弄清楚如何编写使用 Jest 和 MSW 的测试。

它是一个“AuthProvider”,用于初始化 keycloak-js 并呈现子项。

我编写了一个测试来检查 children 是否正确呈现。

我想测试以下场景:

  • 它应该渲染儿童(这个有效)
  • 它应该初始化keycloak(调用keycloak.init)
  • 它应该向我们的 SSO 端点发出一个 post 请求(在 MSW 中命中一个休息模拟)
  • 它应该使用“onReady”事件调用 onKeycloakEvent
  • 它应该调用 login
  • 它应该调用 onKeycloakTokens(带有预期的令牌)
  • 它应该设置 user(具有预期的用户名和角色)
  • 它应该设置 authToken(带有预期的令牌)
  • 当使用“onTokenExpired”事件调用 login 时,它应该调用 onKeycloakEvent

我已经安装并设置了 https://github.com/SectorLabs/keycloak-mock 以使用 nock 处理请求。

但是当涉及到如何等待这些事件被调用时,我完全陷入困境,因为 DOM 中没有任何变化。

一旦子节点渲染,测试立即通过,而无需等待 keycloak 甚至尝试初始化。

我将如何强制 jest 等待组件内部调用函数或 keycloak 初始化?

我试图模拟 keycloak.init 并期待 2 个断言,但没有成功。

import React,{ useState } from 'react'
import { ReactKeycloakProvider } from '@react-keycloak/web'
import keycloak from 'src/lib/keycloak'
import { IDP_HINT } from 'src/common/constants'
import { useAtom,useUpdateAtom,authTokenAtom,userAtom } from 'src/atoms'

type KeycloakAuthProviderProps = {
  children: React.ReactNode
}

const login = () => keycloak.login({ IDP_HINT })

const KeycloakAuthProvider = ({ children }: KeycloakAuthProviderProps) => {
  const [calledLogin,setCalledLogin] = useState(false)
  const [authToken,setAuthToken] = useAtom(authTokenAtom)
  const setUser = useUpdateAtom(userAtom)

  const onKeycloakEvent = (event: string,error: any) => {
    console.log('onKeycloakEvent',event)
    if (event === 'onReady') {
      if (keycloak && !calledLogin && !authToken) {
        // on first load,automatically attempt a keycloak login.
        login()
        setCalledLogin(true)
      }
    } else if (keycloak && event === 'onTokenExpired') {
      login()
    }
    if (error) console.error(error)
  }

  const onKeycloakTokens = (tokens: any) => {
    console.log('onKeycloakTokens',tokens)
    if (keycloak?.tokenParsed && keycloak.tokenParsed?.realm_access?.roles) {
      setUser({
        userName: keycloak.tokenParsed.preferred_username,roles: keycloak.tokenParsed.realm_access.roles,})
    }

    const authToken = tokens.token
    setAuthToken(authToken)
  }

  return (
    <ReactKeycloakProvider
      initOptions={{ flow: 'implicit',onLoad: 'check-sso' }}
      onEvent={onKeycloakEvent}
      onTokens={onKeycloakTokens}
      authClient={keycloak}
    >
      {children}
    </ReactKeycloakProvider>
  )
}

export default KeycloakAuthProvider

keycloak.init 模拟尝试(失败)

import React from 'react'
import { render,screen } from 'src/test/test-utils'

import AuthProvider from './AuthProvider'
import keycloak from './index'

// MISSING tests:
// - it should initialize keycloak (call keycloak.init)
// - it should make a post request to our SSO endpoint (hit a rest mock in MSW/nock)
// - it should call `onKeycloakEvent` with an "onReady" event
// - it should call `login`
// - it should call `onKeycloakTokens` (with expected tokens)
// - it should set `user` (with expected userName and roles)
// - it should set `authToken` (with expected token)
// - it should call `login` when `onKeycloakEvent` is called with an "onTokenExpired" event

test('AuthProvider initializes keycloak',() => {
    expect.assertions(2); // attempt to make keycloak wait for init

    keycloak.init = jest.fn() // mock keycloak.init

    render(
        <AuthProvider>
            <div>test</div>
        </AuthProvider>
    )

    const childElement = screen.getByText(/test/i)
    expect(childElement).toBeInTheDocument()
    expect(keycloak.init).toHaveBeenCalled(); // expect to have called keycloak
})

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。