Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs React、TypeScript&;使用Jest进行RxJS测试不起作用_Reactjs_Typescript_Testing_Rxjs_Jestjs - Fatal编程技术网

Reactjs React、TypeScript&;使用Jest进行RxJS测试不起作用

Reactjs React、TypeScript&;使用Jest进行RxJS测试不起作用,reactjs,typescript,testing,rxjs,jestjs,Reactjs,Typescript,Testing,Rxjs,Jestjs,我在ReactTypeScript中有一个简单的按钮组件,我使用fromEvent方法将点击事件转换为RxJs的可观察包装,它在RxJs中被定义为fromEvent(el:HTMLElement,eventType:string) type NullableObservarbel = Observable<any> | null type NUllabe = HTMLElement | null export const makeObservable = (el:NUlla

我在
React
TypeScript
中有一个简单的按钮组件,我使用
fromEvent
方法将点击事件转换为
RxJs
的可观察包装,它在RxJs中被定义为
fromEvent(el:HTMLElement,eventType:string)

type NullableObservarbel = Observable<any> | null
type NUllabe = HTMLElement | null

    export const makeObservable = (el:NUllabe, eventType:string):NullableObservarbel => el ? fromEvent(el, eventType) : null;
type Props = {
    interval?: number // timee interval in millisecond
    label?:string
}

const Button:SFC<Props> = ({label}:Props) => {
    const btn = useRef(null)
    useEffect(() => {
        if(btn.current !== null){
            const observable = makeObservable(btn.current, 'click')
        }
    }, [])
    return <button ref={btn}>{label}</button>
}
最大的问题是我无法从
wrapper
获取
HTMLElement
类型,所以我只使用
find
按钮并将结果作为元素传递,但是

expect(observable instanceof observable)。toBe(true)
如果我将
null
作为
el
的参数传递给
makeObservable
,则此行始终传递事件


请帮助我正确测试这些场景。

您可以尝试使用
测试库/react
而不是使用
浅层
,我已将
数据testid=“btn”
属性添加到您的组件中,然后从我使用的测试开始
testing library/react
渲染按钮,然后获取按钮的
HTMLElement
,我使用了这个
testid
属性

它在测试和浏览器中正常工作,请检查源代码

Button.tsx

import React, { SFC, useRef, useEffect, useState, RefObject} from 'react'
import {fromEvent, Observable} from 'rxjs'
import {map, debounceTime} from 'rxjs/operators'

type NullableObservarbel = Observable<any> | null;
type NUllabe = HTMLButtonElement | null; // more precise type
export const makeObservable = (el:NUllabe, eventType:string):NullableObservarbel => el ? fromEvent(el, eventType) : null;

type Props = {
    interval?: number // timee interval in millisecond
    label?:string
}

export type Result = [RefObject<HTMLButtonElement>, number]

// decoupled it from Button function body because you can test this later.
export const useEls = ():Result => {
    const btn: RefObject<HTMLButtonElement> = useRef(null)
    const [count, updateCount] = useState<number>(0)
    useEffect(() => {
        const el = btn ? btn.current : null
        if(el){
            updateCount(1)
            let _count = count
            const observerble =  makeObservable(el, 'click');
            if(observerble){
                observerble.pipe(
                    map(e => _count++),
                    //debounceTime(400)
                ).subscribe(c => updateCount(c))
            }
        }
    }, [])
    return [btn, count]
} 

const Button:SFC<Props> = (props:Props) => {
    const [btn, count] = useEls()
    return <button data-testid="btn" ref={btn}>Hello {count}</button>
}


export default Button
import React,{SFC,useRef,useffect,useState,reobject}来自“React”
从“rxjs”导入{fromEvent,Observable}
从'rxjs/operators'导入{map,debounceTime}

键入NullableObservarbel=Observable

谢谢,是否也可以测试我的挂钩,您已经提到了
//将其与按钮函数体解耦,因为您可以稍后进行测试。
在代码中,如果可能,如何测试?
import React, { SFC, useRef, useEffect, useState, RefObject} from 'react'
import {fromEvent, Observable} from 'rxjs'
import {map, debounceTime} from 'rxjs/operators'

type NullableObservarbel = Observable<any> | null;
type NUllabe = HTMLButtonElement | null; // more precise type
export const makeObservable = (el:NUllabe, eventType:string):NullableObservarbel => el ? fromEvent(el, eventType) : null;

type Props = {
    interval?: number // timee interval in millisecond
    label?:string
}

export type Result = [RefObject<HTMLButtonElement>, number]

// decoupled it from Button function body because you can test this later.
export const useEls = ():Result => {
    const btn: RefObject<HTMLButtonElement> = useRef(null)
    const [count, updateCount] = useState<number>(0)
    useEffect(() => {
        const el = btn ? btn.current : null
        if(el){
            updateCount(1)
            let _count = count
            const observerble =  makeObservable(el, 'click');
            if(observerble){
                observerble.pipe(
                    map(e => _count++),
                    //debounceTime(400)
                ).subscribe(c => updateCount(c))
            }
        }
    }, [])
    return [btn, count]
} 

const Button:SFC<Props> = (props:Props) => {
    const [btn, count] = useEls()
    return <button data-testid="btn" ref={btn}>Hello {count}</button>
}


export default Button
import React from 'react'
import Button, {makeObservable} from './Button'
import {Observable} from 'rxjs'
import {map, debounceTime} from 'rxjs/operators'
import {render, fireEvent} from '@testing-library/react'

describe('Observable', () => {
    it('should create observable', () => {
        const {getByTestId} = render(<Button/>)
        const el = getByTestId('btn') as HTMLButtonElement
        const observable = makeObservable(el, 'click')
        expect(observable instanceof Observable).toBe(true)
    })

    it('should return false', () => {
        const observable = makeObservable(null, 'click')
        expect(observable instanceof Observable).toBe(false)
    })

    it('Should subscribe observable', (done) => {
        const {getByTestId} = render(<Button/>)
        const el = getByTestId('btn') as HTMLButtonElement
        const observerble =  makeObservable(el, 'click');
        if(observerble){
            let count = 1
            observerble
                .pipe(
                    map(e => count++),
                    debounceTime(400) // delay clicks if you want
                )
                .subscribe(s => {
                    expect(s).toEqual(6)// test just inside the subscription
                    done();
                })
            fireEvent.click(el)
            fireEvent.click(el)
            fireEvent.click(el)
            fireEvent.click(el)
            fireEvent.click(el)
            fireEvent.click(el)
        }
    })
})