// @flow /* eslint-disable react/no-multi-comp */ import React from 'react' import { shallow, render, mount } from 'enzyme' import ThemeProvider, { CHANNEL_NEXT, CONTEXT_CHANNEL_SHAPE } from '../ThemeProvider' describe('ThemeProvider', () => { it('should not throw an error when no children are passed', () => { const result = shallow() expect(result.html()).toEqual(null) }) it('should accept a theme prop that\'s a plain object', () => { shallow() }) it('should render its child', () => { const child = (

Child!

) const renderedComp = shallow( { child } ) expect(renderedComp.contains(child)).toEqual(true) }) it('should merge its theme with an outer theme', (done) => { const outerTheme = { main: 'black' } const innerTheme = { secondary: 'black' } // Setup Child class Child extends React.Component { componentWillMount() { this.context[CHANNEL_NEXT].subscribe(theme => { expect(theme).toEqual({ ...outerTheme, ...innerTheme }) done() }) } render() { return null } } Child.contextTypes = { [CHANNEL_NEXT]: CONTEXT_CHANNEL_SHAPE, } render( ) }) it('should merge its theme with multiple outer themes', (done) => { const outerestTheme = { main: 'black' } const outerTheme = { main: 'blue' } const innerTheme = { secondary: 'black' } // Setup Child class Child extends React.Component { componentWillMount() { this.context[CHANNEL_NEXT].subscribe(theme => { expect(theme).toEqual({ ...outerestTheme, ...outerTheme, ...innerTheme }) done() }) } render() { return null } } Child.contextTypes = { [CHANNEL_NEXT]: CONTEXT_CHANNEL_SHAPE, } render( ) }) it('should be able to render two independent themes', (done) => { const themes = { one: { main: 'black', secondary: 'red' }, two: { main: 'blue', other: 'green' }, } let childRendered = 0 // Setup Child class Child extends React.Component { componentWillMount() { this.context[CHANNEL_NEXT].subscribe(theme => { // eslint-disable-next-line react/prop-types expect(theme).toEqual(themes[this.props.shouldHaveTheme]) childRendered++ // eslint-disable-line no-plusplus if (childRendered === Object.keys(themes).length) { done() } }) } render() { return null } } Child.contextTypes = { [CHANNEL_NEXT]: CONTEXT_CHANNEL_SHAPE, } render(
) }) it('ThemeProvider propagates theme updates through nested ThemeProviders', () => { const theme = { themed: true } const augment = outerTheme => Object.assign({}, outerTheme, { augmented: true }) const update = { updated: true } let actual const expected = { themed: true, augmented: true, updated: true } // Setup Child class Child extends React.Component { componentWillMount() { this.context[CHANNEL_NEXT].subscribe(receivedTheme => { actual = receivedTheme }) } render() { return null } } Child.contextTypes = { [CHANNEL_NEXT]: CONTEXT_CHANNEL_SHAPE, } const wrapper = mount( , ) wrapper.setProps({ theme: Object.assign({}, theme, update) }) expect(actual).toEqual(expected) }) })