Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
view-container / src / models / test / StyleSheetManager.test.tsx
Size: Mime:
// @flow
/* eslint-disable react/no-multi-comp */
import React from 'react'
import PropTypes from 'prop-types'
import { renderToString } from 'react-dom/server'
import { render } from 'react-dom'
import { shallow, mount } from 'enzyme'
import StyleSheetManager from '../StyleSheetManager'
import StyleSheet from '../StyleSheet'
import ServerStyleSheet from '../ServerStyleSheet'
import { resetStyled, expectCSSMatches } from '../../test/utils'
import Frame from 'react-frame-component'

let styled

describe('StyleSheetManager', () => {
  beforeEach(() => {
    // $FlowFixMe
    document.body.innerHTML = ''
    // $FlowFixMe
    document.head.innerHTML = ''

    styled = resetStyled(true)
  })

  it('should use given stylesheet instance', () => {
    const sheet = new ServerStyleSheet()
    const Title = styled.h1`color: palevioletred;`
    renderToString(
      <StyleSheetManager sheet={sheet.instance}>
        <Title />
      </StyleSheetManager>
    )
    expect(sheet.getStyleTags().includes(`palevioletred`)).toEqual(true)
  })

  it('should render its child', () => {
    const target = document.head
    const Title = styled.h1`color: palevioletred;`
    const child = <Title />
    const renderedComp = shallow(
      <StyleSheetManager target={target}>
        {child}
      </StyleSheetManager>
    )
    expect(renderedComp.contains(child)).toEqual(true)
  })

  it('should append style to given target', () => {
    const target = document.body
    const Title = styled.h1`color: palevioletred;`
    class Child extends React.Component {
      componentDidMount() {
        // $FlowFixMe
        const styles = target.querySelector('style').textContent
        expect(styles.includes(`palevioletred`)).toEqual(true)
      }
      render() { return <Title /> }
    }
    mount(
      <StyleSheetManager target={target}>
        <Child />
      </StyleSheetManager>
    )
  })

  it('should append style to given target in iframe', () => {
    const iframe = document.createElement('iframe')
    const app = document.createElement('div')
    // $FlowFixMe
    document.body.appendChild(iframe)
    // $FlowFixMe
    iframe.contentDocument.body.appendChild(app)
    const target = iframe.contentDocument.head
    const Title = styled.h1`color: palevioletred;`
    class Child extends React.Component {
      componentDidMount() {
        // $FlowFixMe
        const styles = target.querySelector('style').textContent
        expect(styles.includes(`palevioletred`)).toEqual(true)
      }
      render() { return <Title /> }
    }
    mount(
      <StyleSheetManager target={target}>
        <Child />
      </StyleSheetManager>,
      { attachTo: app }
    )
  })

  it('should apply styles to appropriate targets for nested StyleSheetManagers', () => {
    const ONE = styled.h1`
      color: red;
    `
    const TWO = styled.h2`
      color: blue;
    `
    const THREE = styled.h3`
      color: green;
    `
    mount(
      <div>
        <ONE/>
        <StyleSheetManager target={document.head}>
          <div>
            <TWO />
            <StyleSheetManager target={document.body}>
              <THREE />
            </StyleSheetManager>
          </div>
        </StyleSheetManager>
      </div>
    )

    // $FlowFixMe
    expect(document.head.innerHTML).toMatchSnapshot()
    // $FlowFixMe
    expect(document.body.innerHTML).toMatchSnapshot()
  })

  // https://github.com/styled-components/styled-components/issues/1634
  it('should inject styles into two parallel contexts', async () => {
    const Title = styled.h1`
      color: palevioletred;
    `

    // Injects the stylesheet into the document available via context
    const SheetInjector = ({ children }, { document }) => (
      <StyleSheetManager target={document.head}>{children}</StyleSheetManager>
    )
    SheetInjector.contextTypes = {
      document: PropTypes.any,
    }

    class Child extends React.Component {
      static contextTypes = {
        document: PropTypes.any,
      }

      componentDidMount() {
        // $FlowFixMe
        const styles = this.context.document.querySelector('style').textContent
        expect(styles.includes(`palevioletred`)).toEqual(true)
        this.props.resolve()
      }
      render() {
        return <Title />
      }
    }

    const div = document.body.appendChild(document.createElement('div'))

    let promiseA, promiseB
    promiseA = new Promise((resolveA, reject) => {
      promiseB = new Promise((resolveB, reject) => {
        try {
          // Render two iframes. each iframe should have the styles for the child injected into their head
          render(
            <div>
              <Frame>
                <SheetInjector>
                  <Child resolve={resolveA} />
                </SheetInjector>
              </Frame>
              <Frame>
                <SheetInjector>
                  <Child resolve={resolveB} />
                </SheetInjector>
              </Frame>
            </div>,
            div
          )
        } catch (e) {
          reject(e)
          div.parentElement.removeChild(div)
        }
      })
    })
    await Promise.all([promiseA, promiseB])
    div.parentElement.removeChild(div)
  })


  describe('ssr', () => {
    it('should extract CSS outside the nested StyleSheetManager', () => {
      const sheet = new ServerStyleSheet()
      const ONE = styled.h1`
        color: red;
      `
      const TWO = styled.h2`
        color: blue;
      `
      class Wrapper extends React.Component {
        state = {
          targetRef: null
        }
        render() {
          return (
            <div ref={(el) => { this.setState({ targetRef: el }) }}>
              {this.state.targetRef && <StyleSheetManager target={this.state.targetRef}>
                <TWO />
              </StyleSheetManager>}
            </div>
          )
        }
      }

      const html = renderToString(
        <StyleSheetManager sheet={sheet.instance}>
          <div>
            <ONE />
            <Wrapper />
          </div>
        </StyleSheetManager>
      )
      const css = sheet.getStyleTags()

      expect(html).toMatchSnapshot()
      expect(css).toMatchSnapshot()
    })
  })
})