2017-02-16 47 views
11

Próbuję dowiedzieć się, jak przetestować zdarzenie "onPress", korzystając z aplikacji Jest w aplikacji typu React-Native, dzięki czemu mogę się upewnić, że funkcja jest wywoływana.Jak zasymulować zdarzenie w teście na urządzeniu za pomocą Jest, Enzyme for React-Native

Przeszedłem przez dokumentację i Google, ale nie mogłem znaleźć dla niego rozwiązania w React-Native.

To co znalazłem, że ma pracować dla React-Native z enzyme:

const mockFunc = jest.fn(); 
const component = mount(<MyComponent onPress={mockFunc} />); 
component.simulate('press'); 
expect(mockFunc).toHaveBeenCalled(); 

Ale to nie działa. Wygląda na to, mount nie działa i mogę to wyjście:

ReferenceError: document is not defined

Próbowałem z shallow zamiast ale TouchableOpacity nie jest uzyskiwanie świadczonych kiedy patrzę na wyjściu funkcji ... i masz zgadliście , to też nie działa. Nie jestem pewien, co robić.

Czy ktoś znalazł sposób testowania zdarzeń na React-Native?

Dzięki

+1

Zakładam użyć enzym, więc 'p.simulate ('naciśnij');' powinno działać. –

+0

enzym 'mount' nie wydaje się działać z React-Native i nie chcę używać' shallow'. "ReferenceError: dokument nie jest zdefiniowany" – alexmngn

+0

Jaki typ zdarzenia próbujesz przetestować? Czy zmienia "stan"? Albo co próbują dokładnie przetestować? Więcej informacji na ten temat może pomóc. –

Odpowiedz

9

Enzym nie obsługuje reagować rodzimymi, ponieważ jest renderowane w różny sposób i nie używa DOM. Właśnie dlatego otrzymujesz błąd ReferenceError: document is not defined. Więcej informacji można znaleźć pod numerem this issue. Zespół React obecnie pracuje nad ujawnieniem metody .find() w react-test-renderer, aby symulować działania na komponentach. Wtedy powinno działać zarówno w trybie React/React-native, bez potrzeby środowiska DOM.

Istnieje hack, który możesz zrobić (i to właśnie zrobiliśmy w naszej firmie), który renderuje niestandardowy komponent, który rozszerza TouchableOpacity i mapuje onClick, aby zadzwonić pod numer onPress. Coś takiego:

const mockPressable = (name) => { 
    const RealComponent = require.requireActual(name); 

    class Component extends RealComponent { 

    render() { 
     return React.createElement(
     RealComponent.displayName || RealComponent.name, 
     { ...this.props, onClick: this.props.onPress }, 
     this.props.children 
    ); 
    } 

    } 

    return Component; 
}; 


jest.mock('TouchableOpacity',() => mockPressable('TouchableOpacity')); 

I w kodzie testowym zadzwonić component.simulate('click').

To jest hack i nie jestem pewien, jakie są tego konsekwencje, ale zadziałało w naszych przypadkach użycia.

+0

Dziękuję za odpowiedź! "Zespół React obecnie pracuje nad ujawnieniem metody .find() w rendererze testowania reagowania, aby symulować działania na komponentach." Jakiekolwiek źródło tego? – irrigator

+0

@irrigator Oto powiązane PR https://github.com/facebook/react/pull/7409 –

2

Jestem w stanie przeprowadzić testy, takie jak opisane w pytaniu w React Native. Oto o konfiguracji:

package.json

"scripts": { 
    ... 
    "test": "node_modules/jest/bin/jest.js", 
} 

"devDependencies": { 
    ... 
    "enzyme": "^3.1.0", 
    "enzyme-adapter-react-16": "^1.0.1", 
    "enzyme-to-json": "^3.1.2", 
    "jest": "^21.2.1", 
    "jest-enzyme": "^4.0.0", 
    "jest-expo": "~21.0.0", 
} 

"jest": { 
    "preset": "jest-expo", 
    "setupFiles": [ 
    "./test/jestSetup.js" 
    ], 
    "snapshotSerializers": [ 
    "./node_modules/enzyme-to-json/serializer" 
    ] 
} 

test/jestSetup.js

import { configure, shallow, render, mount } from 'enzyme' 
import Adapter from 'enzyme-adapter-react-16' 

configure({ adapter: new Adapter() }) 

// enzyme 
global.shallow = shallow 
global.render = render 
global.mount = mount 

Przykład Składnik:

import React from 'react' 
import { Button } from 'react-native' 

const CancelButton = (props) => 
    <Button 
    { ...props } 
    onPress={() => { props.navigation.goBack() } } 
    title="Cancel" 
    /> 

export { CancelButton } 

Przykład testowy

import React from 'react' 
import { CancelButton } from '../CancelButton' 

test('onPress',() => { 
    const goBackFunc = jest.fn() 

    const navigation = { 
    goBack: goBackFunc, 
    } 

    const component = shallow(
    <CancelButton 
     navigation={ navigation } 
    /> 
) 

    component.simulate('press') 
    expect(goBackFunc).toHaveBeenCalled() 
}) 

.babelrc

{ 
    "presets": ["babel-preset-expo"], 
    "env": { 
    "development": { 
     "plugins": ["transform-react-jsx-source"] 
    } 
    } 
} 
+0

Dzięki, z płytką jest dobrym rozwiązaniem, działa również dla mnie. Ale biegnij płytko, aby odłożyć na bok cykl życia reakcji natywnej. Chodzi o to, aby działał on przy użyciu 'mount' zamiast' shallow' – jose920405

0

Należy użyć shallow zamiast, wtedy nazywa .dive()

const mockFunc = jest.fn(); 
const component = shallow(<MyComponent onPress={mockFunc} />);  
component.dive().simulate('press'); 
expect(mockFunc).toHaveBeenCalled();