UNPKG

enzyme-page-object

Version:

A library to help write enzyme tests using the page-object pattern

355 lines (217 loc) 6.53 kB
Enzyme Page Object = A library to help write enzyme tests using the page-object pattern ## Installation NPM: ```shell $ npm install enzyme-page-object --save-dev ``` Yarn: ```shell $ yarn add enzyme-page-object --dev ``` ## Usage `enzyme-page-object` is a simple wrapper around `enzyme` with the goal of making tests a little more readable and managable. To use `enzyme-page-object`, create a `page` for the file you want to test and extend your `SpecificPage` class from `Page`. To create a page, just pass the following arguments to the constructor: - `shallow` or `mount`, depending on how you want to test your component - the react component - an options object Available options: - dive: (number of times to dive into shallow component) So, something like this: ```javascript new Page('shallow', <Component props={...props} />, { dive: 2 }) ``` **Note** Because this is a work in progress, not all aspects of Enzyme are currently represented. If you ever need to get to an underlying `enzyme` element, you can call `element` on the last returned `Page` object, and work with that as you would an `enzyme` object: ```javascript page.find('a').filter('.my-class').element // returns enzyme element ``` --- Examples = Given a file Logo.js: ```javascript // Logo.js import React from 'react' class Logo extends React.Component { render() { return ( <img src="/my/logo.png" /> ) } } export default Logo ``` And a test originally written without page objects: ```javascript // __tests__/Logo.test.js import React from 'react' import { shallow } from 'enzyme' import Logo from '../Logo' describe('rendering the logo', () => { it('renders the src /my/logo.png', () => { const wrapper = shallow(<Logo />) const result = wrapper.find('img').prop('src') expect(result).toBe('/my/logo.png') }) }) ``` You can write a page object: ```javascript // __tests__/pages/Logo.page.js import Page from 'enzyme-page-object' class LogoPage extends Page { constructor(component) { super('shallow', component) } get image() { return this.find('img').prop('src') } } export default LogoPage ``` And then convert your test to this: ```javascript // __tests__/Logo.test.js import React from 'react' import LogoPage from './pages/logo.page' import Logo from '../Logo' describe('rendering the logo', () => { it('renders the image /my/logo.png', () => { const page = new LogoPage(<Logo />) const result = page.image expect(result).toBe('/my/logo.png') }) }) ``` --- ## Sections A `Section` is part of a page that you may use in multiple places. It accepts a `Page`, or `type` and `component` to create a `Page`. It uses the given or created page as `context`. Given a Section: ```javascript import { Section } from 'enzyme-page-object' class MenuSection extends Section { get dashboard() { // context here is the given or created page return this.context.find('a').filter('dashboard').element } } ``` We can add the section to an existing page: ```javascript import Page from 'enzyme-page-object' import Home from './components/Home' // The page being tested class HomePage extends Page { get menu() { return new MenuSection({ page: this }) } } page = new HomePage('shallow', <Home />) const dashboard = page.menu.dashboard ``` Or use the section to generate a new page on the fly: ```javascript import Home from './components/Home' // The page being tested // Options (like `dive`) are passed to the Page automatically section = new MenuSection({ type: 'shallow', component: <Home />, dive: 1 }) const dashboard = section.dashboard ``` --- API = ### Page --- *constructor(type, component, options = {})* Returns a `Page` object. Accepts the following arguments: - Type: One of `mount` or `shallow` (Required) - Component: A React component that the `Page` will wrap (Required) - Options: an options object - `dive`: When shallow rendering, the dive option to pass to enzyme - `context`: The context to pass to a shallow rendered or mounted enzyme object --- *find(selector)* Calls enzyme `find()` using the selector given. Returns a `FoundElement` --- *getElement()* Calls enzyme `getElement()` --- ### Section --- *constructor({ page, type, component })* Returns a `Section` object. Accepts the following arguments: - Page: a `Page` context to be used for the section. If one is not provided, a new `Page` will be created. - Type: If no `Page` is provided, the type of `Page` to generate (shallow or mount) - Component: If no `Page` is provided, the React component to wrap the `Page` around --- ### FoundElement --- *constructor(element)* Returns `FoundElement` with `element` attached as property. --- *click(options)* Calls enzyme `simulate('click')`, passing the given options. Returns null. --- *change(value, options = {})* Calls enzyme `simulate('change')`. `value` will be merged into options, to result in a call like this: ```javascript // textfield.change('New Value') simulate('change', { target: { value: 'New Value' }}) // textfield.prop('value') // => 'New Value' ``` If the underlying element has a property for `checked` (as a checkbox would), `checked` is set instead: ```javascript // checkbox.change(false) simulate('change', { target: { checked: false }}) // checkbox.prop('checked') // => false ``` Returns null. --- *filter(selector) => self* Calls enzyme `filter(selector)`. Returns `self`. --- *find(selector) => self* Calls enzyme `find(selector)`. Returns `self`. --- *instance() => enzyme.instance()* Calls and returns enzyme `instance()`. --- *map(fn, wrap) => []* Calls enzyme `map(fn)`. If wrap is `true`, results are wrapped in `FoundElement`, else results are returned directly. Returns array. --- *prop(key) => enzyme.prop(key)* Calls and returns enzyme `prop(key)` --- *props() => enzyme.props()* Calls and returns enzyme `props()` --- *setContext() => self* Calls enzyme `setContext(context)`. Returns `self`. *state(key) => enzyme.state(key)* Calls and returns enzyme `state(key)` --- *text() => enzyme.text()* Calls and returns enzyme `text()` --- *type() => enzyme.type()* Calls and returns enzyme `type()` --- *update() => enzyme.update()* Calls enzyme `update()` --- Tests = Tests are written with Jest and can be run with: `npm run test` TODO = - Ensure parity to enzyme for shallow / mount - Mock enzyme to stop testing functionality that is not from enzyme-page-object License = MIT