2016-03-22 33 views
17

Tôi đang thử nghiệm một thành phần kế thừa ngữ cảnh từ thành phần gốc, mà không tải/hiển thị mọi thứ từ gốc xuống. Tôi đã thử và tìm kiếm các ví dụ về cách giả lập bối cảnh nhưng không thể tìm thấy bất cứ điều gì (ít nhất là không sử dụng jest).React js - Làm thế nào để thử bối cảnh khi thử nghiệm thành phần

Dưới đây là một ví dụ đơn giản về những gì tôi đang cố gắng đạt được.

Có cách nào đơn giản để tôi có thể thử phản ứngEl.context cho thử nghiệm không?

/** 
* Root Element that sets up & shares context 
*/ 
class Root extends Component { 
    getChildContext() { 
    return { 
     language: { text: 'A String'} 
    }; 
    } 

    render() { 
    return (
     <div> 
     <ElWithContext /> 
     </div> 
    ); 
    } 
} 

Root.childContextTypes = { language: React.PropTypes.object }; 

/** 
* Child Element which uses context 
*/ 
class ElWithContext extends React.Component{ 
    render() { 
    const {language} = this.context; 
    return <p>{language.text}</p> 
    } 
} 

ElWithContext.contextTypes = { language: React.PropTypes.object } 



/** 
* Example test where context is unavailable. 
*/ 
let el = React.createElement(ElWithContext) 

element = TestUtils.renderIntoDocument(el); 
// ERROR: undefined is not an object (evaluating 'language.text') 

describe("ElWithContext",() => { 
    it('should contain textContent from context',() => { 
    const node = ReactDOM.findDOMNode(element); 
    expect(node.textContent).to.equal('A String'); 
    }); 
}) 
+0

đã thấy mô-đun NPM này ?: https://www.npmjs.com/package/react-stub-context – JordanHendrix

+0

Cảm ơn @Omarjmh, tôi đã thấy rằng mặc dù giả định nó được sử dụng đùa vì sự thí dụ. Nhưng tôi nghĩ rằng giả định có thể không chính xác. – patnz

Trả lời

3

Tôi đã đi với giải pháp tạo thành phần gói có ngữ cảnh. Bạn không chắc chắn nếu điều này là một phương pháp tuyệt vời nhưng đang làm việc cho tôi ngay bây giờ:

/** 
* Helper function to wrap component with a component that has context 
*/ 
function wrapWithContext(context, contextTypes, children, React){ 

    const wrapperWithContext = React.createClass({ 
     childContextTypes: contextTypes, 
     getChildContext: function() { return context }, 
     render: function() { return React.createElement('div', null, children) } 
    }); 

    return React.createElement(wrapperWithContext); 
} 

/** 
* Usage 
*/ 

// in setup function of test framework 
const el = React.createElement(ElWithContext); 

const context = { language: { text: 'A String' } }; 
const contextTypes = { language: React.PropTypes.object }; 
const wrapper = wrapWithContext(context, contextTypes, [el], React); 
const ElWithContext = TestUtils.renderIntoDocument(wrapper); 

// do tests 
describe('ElWithContext',() => { 
    it('should contain textContent from context',() => { 
     const node = ReactDOM.findDOMNode(element); 
     expect(node.textContent).to.equal('A String'); 
    }); 
}) 
10

tôi đã đi vào các vấn đề tương tự như bạn đã làm và phát hiện ra hai cách để làm điều đó.

Cách thứ nhất là bản sao cơ bản theo cách của riêng bạn: Tạo trình bao bọc xung quanh thành phần của tôi và chèn nó với ngữ cảnh động. Tôi đặt mã nguồn dưới đây cho những người quan tâm, bởi vì nó là ES6 không giống như ví dụ của bạn. Nhưng nó chỉ là để hiển thị như thế nào nó sẽ được thực hiện trong ES6 và Tôi KHÔNG khuyên bất cứ ai sử dụng nó (tôi đã không thực sự kiểm tra nó bản thân mình).

src/testUtils/mockWithContext.js

import React, { Component } from 'react'; 
import wrapDisplayName from 'recompose/wrapDisplayName'; 
import hoistStatics from 'recompose/hoistStatics'; 

export const defaultContext = { 
    permissions: [ 

    ], 
    user: { 
    id: '1', 
    display_name: 'Default user', 
    email: '<your.email>[email protected]', // Trick with "+" for infinite aliases using gmail. 
    username: 'default_user', 
    created: '2016-08-01T15:50:13.246Z', 
    }, 
}; 

export const defaultContextType = { 
    permissions: React.PropTypes.array, 
    user: React.PropTypes.shape({ 
    id: React.PropTypes.string.isRequired, 
    display_name: React.PropTypes.string.isRequired, 
    email: React.PropTypes.string.isRequired, 
    username: React.PropTypes.string.isRequired, 
    created: React.PropTypes.string.isRequired, 
    }), 
}; 

/** 
* HOC for context 
*/ 
const withContext = ({ context = defaultContext, contextType = defaultContextType }) => (WrappedComponent) => { 
    class WithContext extends Component { 
    getChildContext() { 
     return context; 
    } 

    render() { 
     return <WrappedComponent {...this.props} />; 
    } 
    } 

    WithContext.displayName = wrapDisplayName(WrappedComponent, 'WithContext'); 
    WithContext.WrappedComponent = WrappedComponent; 
    WithContext.childContextTypes = contextType; 

    return WithContext; 
}; 

export default hoistStatics(withContext); 

Như tôi đã nói, tôi đã viết nó, nhưng không kiểm tra nó bởi vì tôi tìm thấy một cách tốt hơn làm bối cảnh tiêm chích khi cố gắng viết các thử nghiệm cho mô hình này.

Sử dụng thư viện Enzyme, được xây dựng để hỗ trợ kiểm tra thành phần React, có khả năng shallow/mount/static hiển thị thành phần của bạn, cho mục đích thử nghiệm. Và mỗi phương pháp trong số này cho phép đối số thứ hai: ngữ cảnh.

SimpleComponent.js

const SimpleComponent = React.createClass({ 
    contextTypes: { 
    name: React.PropTypes.string, 
    }, 
    render() { 
    return <div>{this.context.name}</div>; 
    }, 
}); 

SimpleComponent.test.js

const context = { name: 'foo' }; 
const wrapper = mount(<SimpleComponent />, { context }); 
expect(wrapper.text()).to.equal('foo'); 
wrapper.setContext({ name: 'bar' }); 
expect(wrapper.text()).to.equal('bar'); 
wrapper.setContext({ name: 'baz' }); 
expect(wrapper.text()).to.equal('baz'); 

Khá thẳng về phía trước. Tôi đã không sử dụng nó nhưng nó trông giống như những gì tôi (và bạn) muốn làm. Tôi đoán tôi sẽ phải tự mình thực hiện việc vứt rác.

http://airbnb.io/enzyme/docs/api/ReactWrapper/setContext.html

Các vấn đề liên quan