UNPKG

6.07 kBMarkdownView Raw
1# reselector
2
3[![Travis branch](https://img.shields.io/travis/lttb/reselector/master.svg?style=flat)](https://travis-ci.org/lttb/reselector)
4[![Coverage Status branch](https://img.shields.io/coveralls/lttb/reselector/master.svg?style=flat)](https://img.shields.io/coveralls/lttb/reselector/master.svg?branch=master)
5[![npm version](https://img.shields.io/npm/v/reselector.svg?style=flat)](https://www.npmjs.com/package/reselector)
6[![npm license](https://img.shields.io/npm/l/reselector.svg?style=flat)](https://www.npmjs.com/package/reselector)
7
8## Installation
9
10```sh
11npm install --save-dev reselector
12```
13
14## Usage
15
16You can use it as a babel-plugin or as the runtime function, or both.
17
18### babel-plugin
19
20Add `reselector` to the plugin list in `.babelrc` for your client code. For example:
21
22```js
23{
24 presets: ['react'],
25 env: {
26 test: {
27 plugins: [
28 'reselector/babel',
29 ],
30 },
31 },
32}
33```
34
35### Find Components in the DOM
36
37Use `select` function to build any css selector by React Components.
38
39Just a simple example with [jest](https://facebook.github.io/jest/)
40
41```jsx
42import React from 'react'
43import {render} from 'react-dom'
44import {select} from 'reselector'
45
46const Text = ({children}) => <p>{children}</p>
47
48const Button = ({children}) => (
49 <button>
50 <Text>{children}</Text>
51 </button>
52)
53
54describe('Button', () => {
55 beforeEach(() => document.body.innerHTML = '<div id="app" />')
56
57 it('should render a text', () => {
58 const text = 'hello world!'
59 render(<Button>{text}</Button>, window.app)
60
61 const node = document.querySelector(select`${Button} > ${Text}`)
62 expect(node.textContent).toBe(text)
63 })
64})
65```
66
67### enzyme
68
69It also works with libraries like [enzyme](https://github.com/airbnb/enzyme) out of the box.
70
71```jsx
72import {render} from 'enzyme'
73
74import Button from './Button'
75import Text from './Text'
76
77describe('Button', () => {
78 it('should render a text', () => {
79 const text = 'hello world!'
80 const wrapper = render(<Button>{text}</Button>)
81
82 expect(wrapper.find(select`${Button} > ${Text}`).text()).toBe(text)
83 })
84})
85```
86
87#### Babel
88
89If you have a chanсe to transpile components with this plugin for your unit tests/autotests, you can import React Component as is.
90
91```jsx
92import {select} from 'reselector'
93
94import MyComponent from './MyComponent'
95import MyButton from './MyButton'
96
97/**
98 * [data-dadad] [data-czczx]
99 */
100console.log(select`${MyComponent} ${MyButton}`)
101
102/**
103 * .myClassName > [data-czczx]
104 */
105console.log(select`.myClassName > ${MyButton}`)
106```
107
108#### Runtime (just node.js, without babel)
109
110It may be useful for autotests (for example, with PageObjects) when you don't need to transpile code. Just use `resolve` or `resolveBy` functions to get Components' selector.
111
112```jsx
113const {resolve, select} = require('reselector')
114
115const {MyComponent} = resolve(require.resolve('./MyComponent'))
116const {MyButton} = resolve(require.resolve('./MyButton'))
117
118/**
119 * [data-dadad] [data-czczx]
120 */
121console.log(select`${MyComponent} ${MyButton}`)
122
123/**
124 * .myClassName > [data-czczx]
125 */
126console.log(select`.myClassName > ${MyButton}`)
127```
128
129```jsx
130const {resolveBy, select} = require('reselector')
131
132const resolve = resolveBy(require.resolve)
133
134const {MyComponent} = resolve('./MyComponent')
135const {MyButton} = resolve('./MyButton')
136
137/**
138 * [data-dadad] [data-czczx]
139 */
140console.log(select`${MyComponent} ${MyButton}`)
141
142/**
143 * .myClassName > [data-czczx]
144 */
145console.log(select`.myClassName > ${MyButton}`)
146```
147
148## How it works
149
150This plugin tries to find all React Component declarations and to add `data-{hash}` attribute with the uniq hash-id to the Component's root node. It also saves this hash as the static property for the Component, so `get` function uses this property to build a selector.
151
152
153## Configuration
154
155You can provide some options via `reselector.config.js`, rc-files or in `package.json`.
156
157### prefix
158
159{**string**} By default, it's `data-`. So this plugin generates attributes like `data-c7b7156f`.
160
161But you can define your own prefix, for example
162
163```js
164module.exports = {prefix: ''}
165```
166
167With that, you'll get just a `{hash}` attribute on nodes like `<button c7b7156f />`.
168
169### env
170
171{**boolean**} Be default, `false`. Just set it on `true` to control attributes appending by `process.env.RESELECTOR`. So it will no append hashes at runtime when `process.env.RESELECTOR !== 'true'`.
172
173For example:
174
175```js
176module.exports = {env: true}
177```
178
179### syntaxes
180
181{**string[]**} By default, this plugin works with these syntax list:
182
183```
184@babel/plugin-syntax-async-generators
185@babel/plugin-syntax-class-properties
186@babel/plugin-syntax-decorators
187@babel/plugin-syntax-dynamic-import
188@babel/plugin-syntax-export-default-from
189@babel/plugin-syntax-export-namespace-from
190@babel/plugin-syntax-flow
191@babel/plugin-syntax-function-bind
192@babel/plugin-syntax-import-meta
193@babel/plugin-syntax-jsx
194@babel/plugin-syntax-nullish-coalescing-operator
195@babel/plugin-syntax-numeric-separator
196@babel/plugin-syntax-object-rest-spread
197@babel/plugin-syntax-optional-catch-binding
198@babel/plugin-syntax-optional-chaining
199@babel/plugin-syntax-pipeline-operator
200@babel/plugin-syntax-throw-expressions
201```
202
203But you can declare your own syntax list, for example:
204
205```js
206// .reselectorrc.js
207
208module.exports = {
209 syntaxes: [
210 '@babel/plugin-syntax-async-generators',
211 '@babel/plugin-syntax-class-properties',
212 '@babel/plugin-syntax-decorators',
213 '@babel/plugin-syntax-dynamic-import',
214 '@babel/plugin-syntax-export-default-from',
215 '@babel/plugin-syntax-export-namespace-from',
216 '@babel/plugin-syntax-flow',
217 '@babel/plugin-syntax-function-bind',
218 '@babel/plugin-syntax-import-meta',
219 '@babel/plugin-syntax-jsx',
220 '@babel/plugin-syntax-nullish-coalescing-operator',
221 '@babel/plugin-syntax-numeric-separator',
222 '@babel/plugin-syntax-object-rest-spread',
223 '@babel/plugin-syntax-optional-catch-binding',
224 '@babel/plugin-syntax-optional-chaining',
225 '@babel/plugin-syntax-pipeline-operator',
226 '@babel/plugin-syntax-throw-expressions',
227 ],
228}
229```