如何正确测试React Native OAuth包装器组件?

时间:2019-07-28 19:26:31

标签: react-native testing oauth react-testing-library

我已经编写了一个React Native的“身份验证门户”组件,该组件与现有的OAuth门户链接并处理从重定向URI和后续令牌交换请求中获取身份验证代码。它似乎运行良好,但是显然我需要测试这个假设,因此我正在尝试编写单元/功能测试。我该怎么做呢?

我最初考虑将两个useEffect中使用的函数提取到单独的隔离函数中,并以authCode作为参数而不是从状态中提取并模拟此输入。 / p>

但是,我认为更好的策略是对组件进行整体测试,并仅模拟对axios发布请求的响应,将其与AsyncStorage中存储的内容进行比较,并模拟对请求的错误响应。测试错误处理。

这是一个好方法吗?

import axios from 'axios'
import AsyncStorage from '@react-native-community/async-storage'
import React, { useEffect, useState } from 'react'
import { Linking } from 'react-native'
import InAppBrowser from 'react-native-inappbrowser-reborn'
import { LoadingIndicator } from '../LoadingIndicator'

interface AuthPortalProps {
    client_id: string
    scopes: string[]
    client_secret: string
    redirect_uri: string
    onAuthComplete: () => void
    onError: () => void
}

interface ApiDataResponse {
    token_type: string
    expires_in: number
    access_token: string
    refresh_token: string
}

export const AuthPortal = ({
    client_id,
    scopes,
    client_secret,
    redirect_uri,
    onAuthComplete,
    onError,
}: AuthPortalProps) => {
    const [authCode, setAuthCode] = useState()

    const getAuthCodeFromRedirectUri = async (url: string) => {
        if (url.includes('code=')) {
            const regex = /[^=]+$/g
            const code = url.match(regex)!.toString()

            await setAuthCode(code)
        }
    }

    useEffect(() => {
        const getAuthCode = async () => {
            const url = `https://example.com/auth/?response_type=code&client_id=${client_id}&redirect_uri=${redirect_uri}&scope=${scopes}`

            if (!authCode) {
                try {
                    InAppBrowser.openAuth(url, redirect_uri).then(response => {
                        if (response.type === 'success' && response.url && response.url.includes('code=')) {
                            getAuthCodeFromRedirectUri(response.url)
                            Linking.openURL(redirect_uri)
                        }
                    })
                } catch (error) {
                    console.log('Error: ', error.message)
                    onError()
                }
            }
        }

        getAuthCode()
        return () => {
            InAppBrowser.closeAuth()
        }
    }, [authCode, client_id, onError, redirect_uri, scopes])

    useEffect(() => {
        const getAuthRefreshToken = async () => {
            if (authCode) {
                try {
                    const { data }: { data: ApiDataResponse } = await axios.post(
                        'https://example.com/auth',
                        {
                            grant_type: 'authorization_code',
                            client_id: `${client_id}`,
                            code: `${authCode}`,
                            client_secret: `${client_secret}`,
                            redirect_uri: `${redirect_uri}`,
                        }
                    )

                    await Promise.all([
                        AsyncStorage.setItem('access_token', data.access_token),
                        AsyncStorage.setItem('refresh_token', data.refresh_token),
                    ])
                    setTimeout(() => {
                        onAuthComplete()
                    }, 1000)
                } catch (error) {
                    if (error.response) {
                        console.log('Error: ', error.response)
                    } else if (error.request) {
                        console.log('Error: ', error.request)
                    } else {
                        console.log('Error: ', error.message)
                    }
                    onError()
                }
            }
        }

        getAuthRefreshToken()
    }, [authCode, client_id, client_secret, onAuthComplete, onError, redirect_uri])

    return <LoadingIndicator />
}

0 个答案:

没有答案