fetch 在测试环境中从不调用 .then 或 .catch

Posted

技术标签:

【中文标题】fetch 在测试环境中从不调用 .then 或 .catch【英文标题】:fetch is never calling .then nor .catch in testing environment 【发布时间】:2021-12-19 10:03:41 【问题描述】:

我有以下网络组件:

import React,  useCallback, useState  from 'react'
import  ErrorBoundary  from 'react-error-boundary'
import  useFocusEffect  from '@react-navigation/native'
import styled from 'styled-components/native'
import  useEduConnect, useEduConnectClient  from '../../../IdCheckContext'

import  EduConnectErrorBoundary  from '../../../errors/eduConnect/EduConnectErrorBoundary'
import  ErrorTrigger  from '../../../errors/ErrorTrigger'
import  EduConnectError, EduConnectErrors  from '../../../errors/eduConnect'
import  PageWithHeader  from '../../layout/PageWithHeader'
import  IdCardMagnifyingGlassIcon  from '../../icons/IdCardMagnifyingGlass'
import  getSpacing  from '../../../ui/utils'
import  ButtonPrimary, Spacer, Typo  from '../../../ui/components'
import  ColorsEnum  from '../../../theme/colors'

export const EduConnectForm = () => 
  const eduConnectClient = useEduConnectClient()
  const allowEduConnect = useEduConnect()
  const [error, setError] = useState<EduConnectError | null>(allowEduConnect ? null : new EduConnectError(EduConnectErrors.unavailable))

  const checkIfEduConnectIsAvailable = useCallback(() => 
    if (allowEduConnect === false) 
      setError(new EduConnectError(EduConnectErrors.unavailable))
    
  , [allowEduConnect])

  const openEduConnect = useCallback(() => 
    function setWebView() 
      eduConnectClient?.getAccessToken().then((value) => 
        console.log('value', value, `$eduConnectClient.getLoginUrl()?redirect=false`)
        const request: RequestInit = 
          headers: 
            Authorization: `Bearer $value`,
           as unknown as Record<string, string>,
          mode: 'cors',
          credentials: 'include',
        
        fetch(`$eduConnectClient.getLoginUrl()?redirect=false`, request)
          .catch((err) => 
            console.log(1)
            console.error(err)
            setError(err)
          ) // should be 401 or something, will display default error
          .then((response) => 
            console.log(JSON.stringify(response))
            // @ts-ignore fix response typing
            if ('status' in response && response.status === 200) 
              const finalURL = response?.headers?.get('educonnect-redirect')
              if (finalURL) 
                globalThis.window.open(finalURL, '_blank')
              
            
          )
      )
        .catch((err) => 
          console.log(1)
          console.error(err)
          setError(err)
        )
    
    setWebView()
  , [eduConnectClient])

  useFocusEffect(
    useCallback(() => 
      openEduConnect()
      checkIfEduConnectIsAvailable()
    , [checkIfEduConnectIsAvailable, openEduConnect])
  )

  if (error) 
    throw error
  

  return (
    <ErrorBoundary FallbackComponent=EduConnectErrorBoundary>
      <PageWithHeader
        title="Mon identité"
        scrollChildren=
          <>
            <Center>
              <IdCardMagnifyingGlassIcon size=getSpacing(47) />
            </Center>

            <Typo.ButtonText color=ColorsEnum.GREY_DARK>`Identification`</Typo.ButtonText>
            <Spacer.Column numberOfSpaces=4 />

            <Typo.Body color=ColorsEnum.GREY_DARK>
              `Pour procéder à ton identification, nous allons te demander de te connecter à ÉduConnect. Muni toi de ton identifiant et de ton mot de passe ÉduConnect. Dès que tu as bien complété le parcours, reviens sur ce site pour terminer ton inscription et découvrir toutes les offres du pass Culture !`
            </Typo.Body>

            <Spacer.Column numberOfSpaces=8 />
          </>
        
        bottomChildren=
          <ButtonPrimary
            title=`Ouvrir un onglet ÉduConnect`
            onPress=openEduConnect
          />
        
      />
      <ErrorTrigger error=error />
    </ErrorBoundary>
  )



const Center = styled.View(
  alignSelf: 'center',
)

在本地,fetch 请求成功并打开一个新选项卡。在测试环境中,它从不调用.catch.then。我希望至少打电话给这两个中的一个。

这是我在testing 环境中的网络开发人员选项卡:

这是我在testing 环境中的控制台开发人员选项卡:

有什么线索吗?

【问题讨论】:

【参考方案1】:

这是由于缺少允许客户端读取标头以防止 XSS 攻击所必需的Access-Control-Expose-Headers

为了让客户端能够访问其他标头,服务器必须使用 Access-Control-Expose-Headers 标头列出它们。

mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers

【讨论】:

以上是关于fetch 在测试环境中从不调用 .then 或 .catch的主要内容,如果未能解决你的问题,请参考以下文章

如何在 fetch 的 then() 中捕获 json 文本

在没有 this 的情况下在 fetch 承诺中调用函数

我如何在 fetch 调用中解析简单的 json 响应

React Native fetch .then 不执行代码,具体取决于内容

如何在fetch then / response函数中访问请求对象

fetch().then() 返回内容类型和正文 [重复]