https://github.com/yandex/reselector
Use React Components in css selectors
https://github.com/yandex/reselector
autotesting babel-plugin css-selector react
Last synced: 6 months ago
JSON representation
Use React Components in css selectors
- Host: GitHub
- URL: https://github.com/yandex/reselector
- Owner: yandex
- License: other
- Created: 2018-01-29T23:22:49.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2023-11-01T15:38:29.000Z (almost 2 years ago)
- Last Synced: 2024-05-22T22:44:43.187Z (over 1 year ago)
- Topics: autotesting, babel-plugin, css-selector, react
- Language: JavaScript
- Homepage: https://npm.im/reselector
- Size: 2.83 MB
- Stars: 44
- Watchers: 10
- Forks: 10
- Open Issues: 21
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# reselector
[](https://travis-ci.org/lttb/reselector)
[](https://img.shields.io/coveralls/lttb/reselector/master.svg?branch=master)
[](https://www.npmjs.com/package/reselector)
[](https://www.npmjs.com/package/reselector) [](https://greenkeeper.io/)## Installation
```sh
npm install --save-dev reselector
```## Usage
You can use it as a babel-plugin or as the runtime function, or both.
### babel-plugin
Add `reselector` to the plugin list in `.babelrc` for your client code. For example:
```js
{
presets: ['react'],
env: {
test: {
plugins: [
'reselector/babel',
],
},
},
}
```### Find Components in the DOM
Use `select` function to build any css selector by React Components.
Just a simple example with [jest](https://facebook.github.io/jest/)
```jsx
import React from 'react'
import {render} from 'react-dom'
import {select} from 'reselector'const Text = ({children}) =>
{children}
const Button = ({children}) => (
{children}
)describe('Button', () => {
')
beforeEach(() => document.body.innerHTML = 'it('should render a text', () => {
const text = 'hello world!'
render({text}, window.app)const node = document.querySelector(select`${Button} > ${Text}`)
expect(node.textContent).toBe(text)
})
})
```### enzyme
It also works with libraries like [enzyme](https://github.com/airbnb/enzyme) out of the box.
```jsx
import {render} from 'enzyme'import Button from './Button'
import Text from './Text'describe('Button', () => {
it('should render a text', () => {
const text = 'hello world!'
const wrapper = render({text})expect(wrapper.find(select`${Button} > ${Text}`).text()).toBe(text)
})
})
```#### Babel
If you have a chanсe to transpile components with this plugin for your unit tests/autotests, you can import React Component as is.
```jsx
import {select} from 'reselector'import MyComponent from './MyComponent'
import MyButton from './MyButton'/**
* [data-tid="dadad"] [data-tid="czczx"]
*/
console.log(select`${MyComponent} ${MyButton}`)/**
* .myClassName > [data-tid="czczx"]
*/
console.log(select`.myClassName > ${MyButton}`)
```#### Runtime (just node.js, without babel)
It 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.
```jsx
const {resolve, select} = require('reselector')const {MyComponent} = resolve(require.resolve('./MyComponent'))
const {MyButton} = resolve(require.resolve('./MyButton'))/**
* [data-tid="dadad"] [data-tid="czczx"]
*/
console.log(select`${MyComponent} ${MyButton}`)/**
* .myClassName > [data-tid="czczx"]
*/
console.log(select`.myClassName > ${MyButton}`)
```With `resolveBy`:
```jsx
const {resolveBy, select} = require('reselector')const resolve = resolveBy(require.resolve)
const {MyComponent} = resolve('./MyComponent')
const {MyButton} = resolve('./MyButton')/**
* [data-tid="dadad"] [data-tid="czczx"]
*/
console.log(select`${MyComponent} ${MyButton}`)/**
* .myClassName > [data-tid="czczx"]
*/
console.log(select`.myClassName > ${MyButton}`)
```## How it works
This 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.
## Configuration
You can provide some options via `reselector.config.js`, rc-files or in `package.json`.
### name
{**string** = 'data-tid'} Test-attribute name, should not be empty.
You can define your own attribute name, for example
```js
module.exports = {name: 'my-test-id'}
```With that, you'll get attributes on nodes like ``.
### env
{**boolean** = 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'`.
For example:
```js
module.exports = {env: true}
```### envName
{**string** = `process.env.BABEL_ENV || process.env.NODE_ENV || 'development'`}
### syntaxes
{**string[]**} By default, this plugin works with these syntax list:
```
@babel/plugin-syntax-async-generators
@babel/plugin-syntax-class-properties
@babel/plugin-syntax-decorators
@babel/plugin-syntax-dynamic-import
@babel/plugin-syntax-export-default-from
@babel/plugin-syntax-export-namespace-from
@babel/plugin-syntax-flow
@babel/plugin-syntax-function-bind
@babel/plugin-syntax-import-meta
@babel/plugin-syntax-jsx
@babel/plugin-syntax-nullish-coalescing-operator
@babel/plugin-syntax-numeric-separator
@babel/plugin-syntax-object-rest-spread
@babel/plugin-syntax-optional-catch-binding
@babel/plugin-syntax-optional-chaining
@babel/plugin-syntax-pipeline-operator
@babel/plugin-syntax-throw-expressions
```But you can declare your own syntax list, for example:
```js
// .reselectorrc.jsmodule.exports = {
syntaxes: [
'@babel/plugin-syntax-async-generators',
'@babel/plugin-syntax-class-properties',
'@babel/plugin-syntax-decorators',
'@babel/plugin-syntax-dynamic-import',
'@babel/plugin-syntax-export-default-from',
'@babel/plugin-syntax-export-namespace-from',
'@babel/plugin-syntax-flow',
'@babel/plugin-syntax-function-bind',
'@babel/plugin-syntax-import-meta',
'@babel/plugin-syntax-jsx',
'@babel/plugin-syntax-nullish-coalescing-operator',
'@babel/plugin-syntax-numeric-separator',
'@babel/plugin-syntax-object-rest-spread',
'@babel/plugin-syntax-optional-catch-binding',
'@babel/plugin-syntax-optional-chaining',
'@babel/plugin-syntax-pipeline-operator',
'@babel/plugin-syntax-throw-expressions',
],
}
```###Custom configuration
You also can change base configuration in your .reselectorrc.js. Example:
```js
// .reselectorrc.jsmodule.exports = function configurate(baseConfig) {
const tsxSyntax = [
'@babel/plugin-syntax-typescrypt',
{
isTSX: true
}
]return Object.assign(baseConfig, {
syntaxes: baseConfig.syntaxes.concat([tsxSyntax])
})
}
```