2016-06-30 2 views
19

내가 (경로가 활성 상태 인 경우 '활성'클래스가 추가 링크 래퍼) 구성 요소가 반응 매우 간단있어 조롱하는? 나의 유일한 시도는 :어떻게 반응 라우터 컨텍스트

import NavLink from '../index'; 

import expect from 'expect'; 
import { mount } from 'enzyme'; 
import React from 'react'; 

describe('<NavLink />',() => { 
    it('should add active class',() => { 
    const renderedComponent = mount(<NavLink to="/home" />, { router: { pathname: '/home' } }); 
    expect(renderedComponent.hasClass('active')).toEqual(true); 
    }); 
}); 

TypeError: Cannot read property 'isActive' of undefined을 반환합니다. 확실히 일부 라우터 조롱이 필요하지만, 나는 그것을 쓰는 방법을 모른다.

답변

16
( https://github.com/airbnb/enzyme/pull/62 다음) 내가 훨씬 더 간단하게 뭔가를 작성하는 관리 답변에 대한

감사 @Elon Szopos하지만 : 나는 Link을 평가하지 않기 위해 shallowmount을 변경해야

import NavLink from '../index'; 

import expect from 'expect'; 
import { shallow } from 'enzyme'; 
import React from 'react'; 

describe('<NavLink />',() => { 
    it('should add active class',() => { 
    const context = { router: { isActive: (a, b) => true } }; 
    const renderedComponent = shallow(<NavLink to="/home" />, { context }); 
    expect(renderedComponent.hasClass('active')).toEqual(true); 
    }); 
}); 

나에게 오류를 제공 반응 라우터와 연결된 TypeError: router.createHref is not a function.

나는 단지 "실제"반응 라우터를 가지고 있지만 개체를 ​​만드는 방법을 모릅니다. 당신은 그 정확한 목적

에 대한 https://github.com/pshrmn/react-router-test-context을 사용할 수 있습니다

+1

shallow에 전달되는 "컨텍스트"주위의 중괄호에 주목하십시오. 처음에는 그 내용을 놓쳤으며, 왜 작동하지 않는지 알아 내려고했습니다. –

5

컨텍스트에 의존하는 테스트 구성 요소는 약간 까다로울 수 있습니다. 제가 한 것은 테스트에서 사용한 래퍼를 작성하는 것입니다. 여기

import React, { PropTypes } from 'react' 

export default class WithContext extends React.Component { 
    static propTypes = { 
    children: PropTypes.any, 
    context: PropTypes.object 
    } 

    validateChildren() { 
    if (this.props.children === undefined) { 
     throw new Error('No child components were passed into WithContext') 
    } 
    if (this.props.children.length > 1) { 
     throw new Error('You can only pass one child component into WithContext') 
    } 
    } 

    render() { 
    class WithContext extends React.Component { 
     getChildContext() { 
     return this.props.context 
     } 

     render() { 
     return this.props.children 
     } 
    } 

    const context = this.props.context 

    WithContext.childContextTypes = {} 

    for (let propertyName in context) { 
     WithContext.childContextTypes[propertyName] = PropTypes.any 
    } 

    this.validateChildren() 

    return (
     <WithContext context={this.props.context}> 
     {this.props.children} 
     </WithContext> 
    ) 
    } 
} 

당신은 샘플 구문을 볼 수 있습니다 :

당신은 아래의 래퍼 찾을 수

<WithContext context={{ location: {pathname: '/Michael/Jackson/lives' }}}> 
    <MoonwalkComponent /> 
    </WithContext> 

    <WithContext context={{ router: { isActive: true }}}> 
    <YourTestComponent /> 
    </WithContext> 

을 그리고 당신은 예상대로 작동합니다.

3

"중복 라우터의 context.router 구조 반응 의사 컨텍스트 객체를 생성합니다.이 효소 얕은 단위 테스트에 유용합니다." 당신이 <MemoryRouter>을 사용할 수 있습니다 V4 라우터를 반응 들어

그것을 설치 한 후

describe('my test',() => { 
    it('renders',() => { 
    const context = createRouterContext() 
    const wrapper = shallow(<MyComponent />, { context }) 
    }) 
}) 
11

처럼 뭔가를 할 수있을 것입니다. AVA와 효소와 예 :

import React from 'react'; 
import PropTypes from 'prop-types'; 
import test from 'ava'; 
import { mount } from 'enzyme'; 
import sinon from 'sinon'; 
import { MemoryRouter as Router } from 'react-router-dom'; 

const mountWithRouter = node => mount(<Router>{node}</Router>); 

test('submits form directly', t => { 
    const onSubmit = sinon.spy(); 
    const wrapper = mountWithRouter(<LogInForm onSubmit={onSubmit} />); 
    const form = wrapper.find('form'); 
    form.simulate('submit'); 

    t.true(onSubmit.calledOnce); 
}); 
+4

랩핑 된 구성 요소의 소품을 업데이트 할 때까지 작동합니다. 'setProps()'호출은 이제 루트 구성 요소 ('MemoryRouter')에서만 작동합니다. –

+0

구성 요소를 테스트하는 보편적 인 방법을 찾을 수 없다고 생각합니다. 그러나 위의 예에서는 속성을 인라인으로 설정할 수 있습니다. 'onSubmit'처럼. – walteronassis

0

당신은 mount & shallow의 차이를 알아야합니다. official documentation가 얕은 렌더링 설명 :

반작용위한 단위 테스트를 작성 얕은 렌더링은 도움이 될 수있다. 얕은 렌더링을 사용하면 구성 요소를 "한 단계 깊숙이"렌더링 할 수 있으며 은 자식 구성 요소의 동작에 대해 걱정하지 않고 렌더링 메서드가 반환하는 내용을 설명합니다.이 구성 요소는 인스턴스화되지 않았거나 렌더링되었습니다. 여기에는 DOM이 필요하지 않습니다.

그런 다음, 복잡하지 않고, 어느 상황 :

const renderedComponent = shallow(<NavLink to="/home" />); 

대신

const renderedComponent = mount(<NavLink to="/home" />, { router: { pathname: '/home' } }); 

의 그것은 작동합니다!

관련 문제