2016-02-24 2 views
4

У меня была эта проблема в прошлом при использовании более старых версий реактивного маршрутизатора, которые я решил использовать: stubRouterContext + хакерский способ доступа экземпляр компонента (с использованием ссылок: https://github.com/reactjs/react-router/issues/1140#issuecomment-113174774)Как протестировать компонент React, который использует контекст, как в response-router 2.0, с Jest 0.8.x

Я думал, что это улучшится в будущем, но я столкнулся с одной и той же стеной с реактивным маршрутизатором 2.0 (я не говорю, что это проблема с реактивным маршрутизатором, но поскольку он использует контекст, это влияет на мои тесты). Таким образом, у меня есть компонент, который использует контекст, чтобы подтолкнуть новое состояние в URL this.context.router.push(...) который является способом идти https://github.com/reactjs/react-router/blob/master/upgrade-guides/v2.0.0.md#programmatic-navigation

Я говорю jest.dontMock('react-router'), но мой тест потерпит неудачу с:

TypeError: Cannot read property 'push' of undefined

Это происходит потому, что экземпляр, возвращаемый TestUtils.renderIntoDocument будет:

context: Object { router: undefined }

Теперь, какова настоящая проблема? Это шутка? Я уверен, что я не единственный, кто сталкивается с этим, и с stubRouterContext он больше не находится в official docs реактивного маршрутизатора, есть ли широкое решение для этого?

Как заставить тест работать? Что в основном имеет правильный контекст и возможность доступа ко всему из экземпляра компонента, возвращаемого TestUtils.renderIntoDocument.

Я использую реакцию 0.14.7, jest-cli 0.8.2 и реактивный маршрутизатор 2.0.

+0

У меня точно такая же проблема. Я отказался от тестирования PageComponents, потому что накладные расходы больше, чем стоимость, которую они приносят, но я, по крайней мере, хотел бы покрыть мои сухари и навигацию. На данный момент я пытаюсь сделать компонент с помощью TestUtils на основе тестовых маршрутов и объектов местоположения, похоже, является единственным жизнеспособным решением. Что у вас получилось? –

ответ

0

Вот настройки, которые я закончил с моими контекстными зависимыми компонентами (урезанными для простоты, конечно):

// dontmock.config.js contains jest.dontMock('components/Breadcrumbs') 
// to avoid issue with hoisting of import operators, which causes 
// jest.dontMock() to be ignored 

import dontmock from 'dontmock.config.js'; 
import React from "react"; 
import { Router, createMemoryHistory } from "react-router"; 
import TestUtils from "react-addons-test-utils"; 

import Breadcrumbs from "components/Breadcrumbs"; 

// Create history object to operate with in non-browser environment 
const history = createMemoryHistory("/products/product/12"); 

// Setup routes configuration. 
// JSX would also work, but this way it's more convenient to specify custom 
// route properties (excludes, localized labels, etc..). 
const routes = [{ 
    path: "/", 
    component: React.createClass({ 
    render() { return <div>{this.props.children}</div>; } 
    }), 
    childRoutes: [{ 
    path: "products", 
    component: React.createClass({ 
     render() { return <div>{this.props.children}</div>; } 
    }), 
    childRoutes: [{ 
     path: "product/:id", 
     component: React.createClass({ 
     // Render your component with contextual route props or anything else you need 
     // If you need to test different combinations of properties, then setup a separate route configuration. 
     render() { return <Breadcrumbs routes={this.props.routes} />; } 
     }), 
     childRoutes: [] 
    }] 
    }] 
}]; 

describe("Breadcrumbs component test suite:",() => { 
    beforeEach(function() { 
    // Render the entire route configuration with Breadcrumbs available on a specified route 
    this.component = TestUtils.renderIntoDocument(<Router routes={routes} history={history} />); 
    this.componentNode = ReactDOM.findDOMNode(this.component); 
    this.breadcrumbNode = ReactDOM.findDOMNode(this.component).querySelector(".breadcrumbs"); 
    }); 

    it("should be defined", function() { 
    expect(this.breadcrumbNode).toBeDefined(); 
    }); 

    /** 
    * Now test whatever you need to 
    */ 
0

Если бы то же беда, неопределенное this.context.history в модульных тестах.

Стек: React 0,14, реагируют-маршрутизатор 1.0, 1.14, историю жасмин 2.4

была решена следующим способом.

Для истории взаимодействия с маршрутизатором я использую «history/lib/createBrowserHistory», который позволяет использовать ссылки без хеша. Этот модуль является одноточечным. Это означает, что после его создания можно использовать все ваши приложения. Поэтому я решил выбросить История подмешать и использовать историю непосредственно из отдельных компонентов следующим образом:

// history.js 

import createBrowserHistory from 'history/lib/createBrowserHistory' 
export default createBrowserHistory() 


// app.js 

import React from 'react' 
import ReactDOM from 'react-dom' 
import { Router, Route, IndexRoute } from 'react-router' 

import history from './history' 
import Main from './Main' 

const Layout = React.createClass({ 
    render() { 
    return <div>{React.cloneElement(this.props.children)}</div> 
    } 
}) 

const routes = (
    <Route component={Layout} path='/'> 
    <IndexRoute component={Main} /> 
    </Route> 
) 

ReactDOM.render(
    <Router history={history}>{routes}</Router>, 
    document.getElementById('my-app') 
) 


// Main.js 

import React from 'react' 
import history from './history' 

const Main = React.createClass({ 
    next() { 
    history.push('/next_page') 
    }, 

    render() { 
    return <button onClick={this.next}>{'Go to next page'}</button> 
    } 
}) 

export default Main 

работает как шарм и могут быть проверены легко. Больше нет микшинов, больше нет контекста (по крайней мере, в данном конкретном случае). Я считаю, что такой же подход можно использовать для стандартной истории браузера браузера, но не проверял.

Смежные вопросы