Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add setProps, setProp, and other cy.render methods (#4)
* WIP * Add setProp and setProps methods. Improve cy.render() + add docs * Add RenderWrapper type for cy * Add return types for RenderWrapper methods
- Loading branch information
Jon Quach
committed
May 1, 2019
1 parent
7375b89
commit ded92ac
Showing
13 changed files
with
392 additions
and
71 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,8 @@ | ||
import { pretty } from './utils/pretty.utils' | ||
import { getRootNode } from './utils/render.utils' | ||
import { getDocumentHTML } from './utils/render.utils' | ||
|
||
const debug = (...args) => { | ||
const root = getRootNode() as Element | ||
const other = Array.from(document.body.children).filter(node => node !== root) | ||
|
||
const html = root.innerHTML + other.map(node => node.outerHTML).join('') | ||
|
||
console.log(pretty(html), ...args) | ||
console.log(pretty(getDocumentHTML()), ...args) | ||
} | ||
|
||
export default debug |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import * as React from 'react' | ||
import ReactDOM from 'react-dom' | ||
import cleanUp from '../cleanUp' | ||
import domCleanUp from '../domCleanUp' | ||
import debug from '../debug' | ||
import { runAllTimers } from '../timers' | ||
import wrapWithProvider from './wrapWithProvider' | ||
import { createRootNode, getDocumentHTML } from '../utils/render.utils' | ||
import { isDefined } from '../utils/is.utils' | ||
|
||
class RenderWrapper { | ||
Component: any | ||
WrappedComponent: any | ||
initialProps: any | ||
root: HTMLElement | ||
|
||
constructor(Component: any) { | ||
this.setComponent(Component) | ||
this.mount(Component) | ||
|
||
return this | ||
} | ||
|
||
setComponent(Component) { | ||
this.Component = Component && Component.type ? <Component.type /> : null | ||
this.initialProps = Component && Component.props ? Component.props : {} | ||
} | ||
|
||
mount(Component = this.Component) { | ||
this.cleanUp() | ||
this.setComponent(Component) | ||
// Create the root node for ReactDOM to mount to | ||
this.root = createRootNode() | ||
document.body.appendChild(this.root) | ||
|
||
// Render the WrappedComponent into the root node | ||
this.WrappedComponent = wrapWithProvider(this.Component) | ||
|
||
runAllTimers() | ||
this.render(this.initialProps) | ||
|
||
return this | ||
} | ||
|
||
setProps(props = this.initialProps) { | ||
this.render(props) | ||
return this | ||
} | ||
|
||
setProp(prop, value) { | ||
if (!isDefined(prop)) { | ||
return this | ||
} | ||
|
||
this.setProps({ [prop]: value }) | ||
return this | ||
} | ||
|
||
debug() { | ||
debug() | ||
return this | ||
} | ||
|
||
html() { | ||
return getDocumentHTML() | ||
} | ||
|
||
cleanUp() { | ||
cleanUp() | ||
domCleanUp() | ||
return this | ||
} | ||
|
||
unmount() { | ||
this.cleanUp() | ||
return this | ||
} | ||
|
||
render(props) { | ||
const Component = this.WrappedComponent | ||
ReactDOM.render(<Component {...props} />, this.root) | ||
return this | ||
} | ||
} | ||
|
||
export default RenderWrapper |
2 changes: 1 addition & 1 deletion
2
src/__tests__/render.redux.test.js → src/render/__tests__/render.redux.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
import React from 'react' | ||
import { cy } from '../../index' | ||
|
||
describe('render', () => { | ||
let spy | ||
|
||
beforeEach(() => { | ||
spy = jest.spyOn(global.console, 'log').mockImplementation(() => {}) | ||
}) | ||
|
||
afterEach(() => { | ||
spy.mockRestore() | ||
}) | ||
|
||
test('Can render null', () => { | ||
expect(cy.render()).toBeTruthy() | ||
}) | ||
|
||
test('Can setProps after rendering', () => { | ||
const Base = ({ title }) => <span>{title}</span> | ||
const wrapper = cy.render(<Base title="Hello" />) | ||
|
||
expect(cy.get('span').text()).toBe('Hello') | ||
|
||
wrapper.setProps({ title: 'There' }) | ||
|
||
expect(cy.get('span').text()).toBe('There') | ||
}) | ||
|
||
test('Can setProps without props', () => { | ||
const Base = ({ title }) => <span>{title}</span> | ||
const wrapper = cy.render(<Base title="Hello" />) | ||
|
||
expect(cy.get('span').text()).toBe('Hello') | ||
|
||
wrapper.setProps() | ||
|
||
expect(cy.get('span').text()).toBe('Hello') | ||
}) | ||
|
||
test('Can setProp without props', () => { | ||
const Base = ({ title }) => <span>{title}</span> | ||
const wrapper = cy.render(<Base title="Hello" />) | ||
|
||
expect(cy.get('span').text()).toBe('Hello') | ||
|
||
wrapper.setProp() | ||
|
||
cy.debug() | ||
|
||
expect(cy.get('span').text()).toBe('Hello') | ||
}) | ||
|
||
test('Does not unmount previous Component', () => { | ||
const mountSpy = jest.fn() | ||
const unmountSpy = jest.fn() | ||
|
||
class Base extends React.Component { | ||
componentDidMount() { | ||
mountSpy() | ||
} | ||
|
||
componentWillUnmount() { | ||
unmountSpy() | ||
} | ||
|
||
render() { | ||
const { title } = this.props | ||
return <span>{title}</span> | ||
} | ||
} | ||
|
||
const wrapper = cy.render(<Base title="Hello" />) | ||
|
||
expect(mountSpy).toHaveBeenCalled() | ||
expect(unmountSpy).not.toHaveBeenCalled() | ||
expect(cy.get('span').text()).toBe('Hello') | ||
|
||
wrapper.setProps({ title: 'There' }) | ||
expect(cy.get('span').text()).toBe('There') | ||
expect(unmountSpy).not.toHaveBeenCalled() | ||
|
||
wrapper.setProp('title', 'Howdy') | ||
expect(cy.get('span').text()).toBe('Howdy') | ||
expect(unmountSpy).not.toHaveBeenCalled() | ||
}) | ||
|
||
test('Can retrieve document.body.innerHTML', () => { | ||
const wrapper = cy.render(<div>Hello</div>) | ||
|
||
expect(wrapper.html()).toBe('<div>Hello</div>') | ||
}) | ||
|
||
test('Can log (debug) innerHTML', () => { | ||
const wrapper = cy.render(<div>Hello</div>) | ||
|
||
wrapper.debug() | ||
|
||
expect(spy).toHaveBeenCalledWith('<div>Hello</div>') | ||
}) | ||
|
||
test('Can cleanUp document.body', () => { | ||
const wrapper = cy.render(<div>Hello</div>) | ||
|
||
expect(cy.get('div').exists()).toBeTruthy() | ||
|
||
wrapper.cleanUp() | ||
|
||
expect(cy.get('div').exists()).toBeFalsy() | ||
}) | ||
|
||
test('Can unmount component', () => { | ||
const wrapper = cy.render(<div>Hello</div>) | ||
|
||
expect(cy.get('div').exists()).toBeTruthy() | ||
|
||
wrapper.unmount() | ||
|
||
expect(cy.get('div').exists()).toBeFalsy() | ||
}) | ||
|
||
test('Can unmount + re-mount component', () => { | ||
const wrapper = cy.render(<div>Hello</div>) | ||
|
||
wrapper.unmount() | ||
expect(cy.get('div').exists()).toBeFalsy() | ||
|
||
wrapper.mount() | ||
expect(cy.get('div').exists()).toBeTruthy() | ||
}) | ||
|
||
test('Can unmount + mount another component', () => { | ||
const wrapper = cy.render(<div>Hello</div>) | ||
|
||
wrapper.unmount() | ||
expect(cy.get('div').exists()).toBeFalsy() | ||
|
||
wrapper.mount(<span>There</span>) | ||
expect(cy.get('div').exists()).not.toBeTruthy() | ||
expect(cy.get('span').exists()).toBeTruthy() | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
import render from './render' | ||
|
||
export default render |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
import RenderWrapper from './RenderWrapper' | ||
|
||
const render = (WrappedComponent = null) => { | ||
return new RenderWrapper(WrappedComponent) | ||
} | ||
|
||
export default render |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import * as React from 'react' | ||
import { MemoryRouter as Router } from 'react-router' | ||
import { Provider } from 'react-redux' | ||
import { getStore } from '../store' | ||
|
||
const wrapWithProvider = WrappedComponent => { | ||
const store = getStore() | ||
|
||
class WrappedWithProvider extends React.Component { | ||
render() { | ||
if (!WrappedComponent) return null | ||
|
||
return ( | ||
<Provider store={store}> | ||
<Router>{React.cloneElement(WrappedComponent, this.props)}</Router> | ||
</Provider> | ||
) | ||
} | ||
} | ||
|
||
return WrappedWithProvider | ||
} | ||
|
||
export default wrapWithProvider |
Oops, something went wrong.