+
+
)
var $root = $r(elements) // renders and returns a wrapped instance
@@ -27,8 +49,13 @@ $r($root[0]) // |
//-- simple selector syntax --
$root.find('.fun-div') //class
$root.find('div') // tag name
+
$root.find(MyInput) // component type
+// complex selectors
+$root.find('div.foo > span:has(div.bar)')
+$root.find($.s`${MyList} > li.foo`)
+
$root.find(':dom') // all dom nodes
$root.find(':composite') // all non DOM components
@@ -61,7 +88,7 @@ $root.find(MyInput).trigger('change', { target: { value: 6 }}) // triggers onCha
### Shallow rendering
-We can use an even more powerful selector syntax will shallow rendering
+To query shallow rendered Components use the `'react-testutil-query/shallow'` import
```js
var $ = require('react-testutil-query/shallow');
@@ -89,7 +116,6 @@ $root.find('.my-list').children('.foo').length // 2
$root.find('div li[aria-label="list item"]').length // 1
-// you can even use es6 template strings to write
// selectors for your custom components
$root.find($.s`${BasicList} > li.foo`).length // 2
diff --git a/lib/README.md b/lib/README.md
new file mode 100644
index 0000000..b4728b3
--- /dev/null
+++ b/lib/README.md
@@ -0,0 +1,106 @@
+React TestUtils utils
+========
+
+A simple jquery like api wrapper for the React TestUtils to make them a bit friendlier to use.
+
+Updates for react 0.14, works with Stateless Components and you can scry and filter on DOM components
+as well.
+
+### Traditional DOM rendering
+
+```js
+var $r = require('react-testutil-query')
+
+var elements = (
+
+
+
+
+
+ )
+
+var $root = $r(elements) // renders and returns a wrapped instance
+
+$r($root) // | calling it again won't rerender or rewrap
+$r($root[0]) // |
+
+//-- simple selector syntax --
+$root.find('.fun-div') //class
+$root.find('div') // tag name
+$root.find(MyInput) // component type
+
+$root.find(':dom') // all dom nodes
+$root.find(':composite') // all non DOM components
+
+$root.find() // everything! all descendents
+
+//-- like jquery you get an arraylike thing
+$root.find(MyInput).length // 2
+
+$root.find(MyInput).each( (component, idx) => /*do something */)
+
+// use the index or `get()` to unwrap the collection into a single component or real array
+$root.find('.fun-div')[0]
+
+
+$root.find(MyInput).first()
+$root.find(MyInput).last()
+
+// you can still get the implicit asserts for finding single components
+$root.find('.fun-div').only() // throws a TypeError .length === 0
+$root.single('.fun-div') // is the same thing
+
+
+// -- getting DOM nodes
+$root.single('.fun-div').dom() // returns the single DOM node
+$root.find(MyInput).dom() //returns an array of DOM nodes
+
+// -- events
+$root.find(MyInput).trigger('change', { target: { value: 6 }}) // triggers onChange for all of them
+```
+
+### Shallow rendering
+
+We can use an even more powerful selector syntax will shallow rendering
+
+```js
+var $ = require('react-testutil-query/shallow');
+
+let label = 'list item';
+
+let BasicList = props =>
+
+let DivList = ()=> (
+
+
+ hi 1
+ hi 2
+ hi 3
+
+
+)
+
+
+let $root = $(
li.foo').length // 2
+
+$root.find('.my-list').children('.foo').length // 2
+
+$root.find('div li[aria-label="list item"]').length // 1
+
+// you can even use es6 template strings to write
+// selectors for your custom components
+$root.find($.s`${BasicList} > li.foo`).length // 2
+
+//or for prop values
+$root.find($.s`li[aria-label=${label}]`).length // 1
+
+$root.find(BasicList)
+ .children()
+ .filter(element => element.props.className === 'foo')
+ .length // 2
+
+$root.find(BasicList).is('.my-list').length // true
+
+```
diff --git a/lib/package.json b/lib/package.json
new file mode 100644
index 0000000..81e4ca6
--- /dev/null
+++ b/lib/package.json
@@ -0,0 +1,30 @@
+{
+ "name": "react-testutil-query",
+ "version": "2.2.0",
+ "description": "small wrapper around react test utils so I don't have to write long method names",
+ "main": "index.js",
+ "repository": {
+ "type": "git",
+ "url": "https://github.com/jquense/react-testutil-query"
+ },
+ "keywords": [
+ "react",
+ "test",
+ "query"
+ ],
+ "author": "jquense",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com/jquense/react-testutil-query/issues"
+ },
+ "homepage": "https://github.com/jquense/react-testutil-query",
+ "peerDependencies": {
+ "react": ">=0.14.0-rc1",
+ "react-dom": ">=0.14.0-rc1"
+ },
+ "dependencies": {
+ "bill": "^1.0.4",
+ "dom-helpers": "^2.4.0",
+ "react-addons-test-utils": "^0.14.0-rc1"
+ }
+}
diff --git a/lib/shallow.js b/lib/shallow.js
new file mode 100644
index 0000000..a32f505
--- /dev/null
+++ b/lib/shallow.js
@@ -0,0 +1,155 @@
+'use strict';
+
+exports.__esModule = true;
+
+var _templateObject = _taggedTemplateLiteralLoose(['', ''], ['', '']);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
+
+function _taggedTemplateLiteralLoose(strings, raw) { strings.raw = raw; return strings; }
+
+var _react = require('react');
+
+var _react2 = _interopRequireDefault(_react);
+
+var _reactAddonsTestUtils = require('react-addons-test-utils');
+
+var _reactAddonsTestUtils2 = _interopRequireDefault(_reactAddonsTestUtils);
+
+var _bill = require('bill');
+
+var isRtq = function isRtq(item) {
+ return item && item.__isRTQ;
+};
+
+rtq.s = rtq.selector = _bill.selector;
+
+exports['default'] = rtq;
+
+function match(selector, tree, includeSelf) {
+ if (typeof selector === 'function') selector = _bill.selector(_templateObject, selector);
+
+ return _bill.match(selector, tree, includeSelf);
+}
+
+function render(element) {
+ var root = element;
+
+ if (!(typeof root.type === 'string' && root.type.toLowerCase() === root.type)) {
+ var renderer = _reactAddonsTestUtils2['default'].createRenderer();
+ renderer.render(element);
+ root = renderer.getRenderOutput();
+ }
+
+ return {
+ root: root,
+ setProps: function setProps(props) {
+ return render(_react.cloneElement(element, props));
+ }
+ };
+}
+
+function rtq(element) {
+ var context, rerender;
+
+ if (_reactAddonsTestUtils2['default'].isElement(element)) {
+ var _render = render(element);
+
+ var root = _render.root;
+ var setProps = _render.setProps;
+
+ element = context = root;
+ rerender = setProps;
+ } else if (isRtq(element)) {
+ context = element.root;
+ element = element.get();
+ //rerender = element._rerender
+ }
+
+ return new ShallowCollection(element, context, rerender);
+}
+
+var ShallowCollection = (function () {
+ function ShallowCollection(elements, root, rerender) {
+ _classCallCheck(this, ShallowCollection);
+
+ elements = [].concat(elements).filter(function (el) {
+ return _react.isValidElement(el);
+ });
+
+ var idx = -1;
+
+ while (++idx < elements.length) this[idx] = elements[idx];
+
+ this._rerender = rerender;
+ this.length = elements.length;
+ this.root = root;
+ }
+
+ ShallowCollection.prototype.setProps = function setProps(props) {
+ this._rerender && this._rerender(props);
+ return this;
+ };
+
+ ShallowCollection.prototype.each = function each(cb) {
+ var idx = -1,
+ len = this.length;
+ while (++idx < len) cb(this[idx], idx, this);
+ return this;
+ };
+
+ ShallowCollection.prototype.get = function get() {
+ var result = [];
+ this.each(function (el) {
+ return result.push(el);
+ });
+ return result;
+ };
+
+ ShallowCollection.prototype.reduce = function reduce(cb, initial) {
+ return new ShallowCollection([].reduce.call(this, cb, initial), this.root);
+ };
+
+ ShallowCollection.prototype.map = function map(cb) {
+ var result = [];
+ this.each(function (v, i, l) {
+ return result.push(cb(v, i, l));
+ });
+
+ return new ShallowCollection(result, this.root);
+ };
+
+ ShallowCollection.prototype.find = function find(selector) {
+ return this.reduce(function (result, element) {
+ return result.concat(match(selector, element));
+ }, []);
+ };
+
+ ShallowCollection.prototype.children = function children(selector) {
+ return this.reduce(function (result, element) {
+ return result.concat(element.props.children || []);
+ }, []).filter(selector);
+ };
+
+ ShallowCollection.prototype.filter = function filter(selector) {
+ if (!selector) return this;
+
+ if (typeof selector === 'function') return new ShallowCollection([].filter.call(this, selector), this.root);
+
+ var matches = match(selector, this.root);
+
+ return new ShallowCollection([].filter.call(this, function (el) {
+ return matches.indexOf(el) !== -1;
+ }), this.root);
+ };
+
+ ShallowCollection.prototype.is = function is(selector) {
+ return this.filter(selector).length === this.length;
+ };
+
+ return ShallowCollection;
+})();
+
+module.exports = exports['default'];
\ No newline at end of file
diff --git a/package.json b/package.json
index 7bba334..dbac6aa 100644
--- a/package.json
+++ b/package.json
@@ -6,7 +6,7 @@
"scripts": {
"test": "karma start --single-run",
"tdd": "karma start",
- "build": "babel src --out-dir lib",
+ "build": "babel src --out-dir lib && cpy ./README.md ./lib",
"release": "release"
},
"repository": {
@@ -32,6 +32,7 @@
"babel-core": "^5.8.25",
"babel-loader": "^5.3.2",
"chai": "^3.3.0",
+ "cpy": "^3.4.1",
"karma": "^0.13.10",
"karma-chai": "^0.1.0",
"karma-chrome-launcher": "^0.2.0",
@@ -49,7 +50,7 @@
"webpack": "^1.12.2"
},
"dependencies": {
- "bill": "^1.0.4",
+ "bill": "^1.1.0",
"dom-helpers": "^2.4.0",
"react-addons-test-utils": "^0.14.0-rc1"
},
diff --git a/src/index.js b/src/index.js
index 44dca98..ae076f9 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,37 +1,38 @@
-
-var React = require('react');
-var ReactDOM = require('react-dom')
-var ReactInstanceMap = require('react/lib/ReactInstanceMap')
-var utils = require('react-addons-test-utils')
-var findAll = require('./utils')
-var hasClass = require('dom-helpers/class/hasClass')
+import React from 'react';
+import ReactDOM from 'react-dom';
+import ReactInstanceMap from 'react/lib/ReactInstanceMap';
+import utils from 'react-addons-test-utils';
+import { match as _match, selector as sel } from './instance-selector';
+import hasClass from 'dom-helpers/class/hasClass';
var $r = module.exports = rtq
-let isRtq = item => item && item.__isRTQ
+let isRtq = item => item && item._isRTQ
+
rtq.react = React;
+rtq.s = rtq.selector = sel;
function rtq(element, mount, renderIntoDocument = (mount === true)) {
var context;
- if (!mount || mount === true) {
+ if (!mount || mount === true)
mount = document.createElement('div')
- }
- if (utils.isElement(element)) {
- context = mount
- element = render(element, mount, renderIntoDocument)
- }
- else if (utils.isDOMComponent(element) || utils.isCompositeComponent(element))
+ if (utils.isElement(element))
+ context = element = render(element, mount, renderIntoDocument)
+ else if (utils.isDOMComponent(element) || utils.isCompositeComponent(element)){
context = element
+ mount = rtq.dom(element).parentNode
+ }
else if (isRtq(element)) {
+ mount = element._mountPoint
context = element.context
element = element.get();
}
else
throw new TypeError('Wrong type: must either be ReactElement or a Component Instance')
- return new ComponentCollection(element, context)
+ return new ComponentCollection(element, context, mount)
}
function render(element, mountPoint, renderIntoDocument = false) {
@@ -57,162 +58,165 @@ function render(element, mountPoint, renderIntoDocument = false) {
return instance;
}
-function ComponentCollection(_components, context, selector){
- var components = _components == null ? [] : [].concat(_components)
- , idx = -1, len = components.length
+function match(selector, tree, includeSelf){
+ if (typeof selector === 'function')
+ selector = sel`${selector}`
- this._privateInstances = Object.create(null)
+ return _match(selector, tree, includeSelf)
+}
- while( ++idx < len ) {
- var component = components[idx]
+rtq.dom = function(component){
+ return component instanceof HTMLElement ? component : ReactDOM.findDOMNode(component)
+}
- // if this is a private instance, get the public one
- if (component.getPublicInstance) {
- this._privateInstances[idx] = component
- component = component.getPublicInstance();
- //stateless
- if (component === null)
- component = ReactDOM.findDOMNode(this._privateInstances[idx]._instance)
- }
- // if this a root Stateless component
- else if (component && component.__isRTQstatelessWrapper){
- let wrapperInstance = ReactInstanceMap.get(component);
- this._privateInstances[idx] = wrapperInstance._renderedComponent;
- component = ReactDOM.findDOMNode(component)
- }
- else {
- this._privateInstances[idx] = ReactInstanceMap.get(component) || component._reactInternalComponent
- }
+class ComponentCollection {
- this[idx] = component
- }
+ constructor(_components, context, mountPoint, selector){
+ var components = _components == null ? [] : [].concat(_components)
+ , idx = -1, len = components.length
- this.length = len
- this.context = context
- this.selector = selector
- this.__isRTQ = true
-}
+ this._privateInstances = Object.create(null)
+ while (++idx < len) {
+ var component = components[idx]
-rtq.dom = function(component){
- return component instanceof HTMLElement ? component : ReactDOM.findDOMNode(component)
-}
+ if (component.getPublicInstance) {
+ this._privateInstances[idx] = component
+ component = component.getPublicInstance();
-ComponentCollection.prototype = {
+ //stateless
+ if (component === null)
+ component = ReactDOM.findDOMNode(this._privateInstances[idx]._instance)
+ }
+ // if this a root Stateless component
+ else if (component && component.__isRTQstatelessWrapper){
+ let wrapperInstance = ReactInstanceMap.get(component);
+ this._privateInstances[idx] = wrapperInstance._renderedComponent;
+ component = ReactDOM.findDOMNode(component)
+ }
+ else {
+ this._privateInstances[idx] = ReactInstanceMap.get(component) || component._reactInternalComponent
+ }
+
+ this[idx] = component
+ }
- constructor: ComponentCollection,
+ this.length = len
+ this.context = context
+ this.selector = selector
+ this._mountPoint = mountPoint
+ this._isRTQ = true
+ }
+
+ _root(){
+ return this.context._reactInternalComponent || this.context
+ }
unmount(){
let inBody = !!this.context.parentNode;
+ ReactDOM.unmountComponentAtNode(this._mountPoint)
- ReactDOM.unmountComponentAtNode(this.context)
if (inBody)
- document.body.removeChild(this.context)
+ document.body.removeChild(this._mountPoint)
+
this.context = null
- },
+ }
setProps(newProps){
return this.mapInPlace(element => element.renderWithProps(newProps))
- },
+ }
each(cb, thisArg) {
var idx = -1, len = this.length;
while( ++idx < len ) cb.call(thisArg, this[idx], idx, this)
return this
- },
+ }
mapInPlace(cb, thisArg) {
return this.each((el, idx, list)=> this[idx] = cb(el, idx, list))
- },
+ }
map(cb, thisArg) {
var idx = -1, len = this.length, result = []
- while( ++idx < len ) result.push(cb.call(thisArg, this[idx], idx, this))
+ while (++idx < len) result.push(cb.call(thisArg, this[idx], idx, this))
return result
- },
+ }
+
+ _reduce(cb, initial){
+ return new ComponentCollection(
+ this._getInstances().reduce(cb, initial)
+ , this.context
+ , this._mountPount
+ , this.selector
+ )
+ }
+
+ reduce(cb, initial){
+ return new ComponentCollection(
+ [].reduce.call(this, cb, initial)
+ , this.context
+ , this._mountPount
+ , this.selector
+ )
+ }
_getInstances(){
- return this.map((component, idx) => {
+ return this.map((_, idx) => {
return this._privateInstances[idx]
})
- },
+ }
get(){
return unwrap(this.map(component => component))
- },
+ }
dom() {
return unwrap(this.map(rtq.dom))
- },
+ }
find(selector){
- let result = []
+ return this._reduce((result, instance) => {
+ return result.concat(match(selector, instance, false))
+ }, [])
+ }
- this.each((component, idx) => {
- component = component !== null
- ? this._privateInstances[idx] || component
- : component
+ filter(selector) {
+ if (!selector) return this
- result = result.concat(_find(component, selector))
- })
+ let matches = match(selector, this._root());
- return new ComponentCollection(result, this.context, selector)
- },
+ return this._reduce((result, el) => {
+ return matches.indexOf(el) !== -1 ? result.concat(el) : result
+ }, [])
+ }
only(){
if (this.length !== 1) throw Error('`' + this.selector +'` found: ' + this.length + ' not 1 ')
return this.first()
- },
+ }
single(selector) {
return selector
? this.find(selector).only()
: this.only()
- },
+ }
first(selector){
return selector
? this.find(selector).first()
- : new ComponentCollection(this[0], this.context, this.selector)
- },
+ : new ComponentCollection(this[0], this.context, this._mountPount, this.selector)
+ }
last(selector){
return selector
? this.find(selector).last()
- : new ComponentCollection(this[this.length - 1], this.context, this.selector)
- },
-
- is(selector){
- let instances = this._getInstances();
- let getPublicInst = inst => inst.getPublicInstance ? inst.getPublicInstance() : inst;
-
- if( typeof selector === 'function') {
- return instances.every(inst => {
- let publicInst = getPublicInst(inst);
- return findAll.isCompositeComponent(publicInst)
- && inst._currentElement.type === selector
- })
- }
+ : new ComponentCollection(this[this.length - 1], this.context, this._mountPount, this.selector)
+ }
- else if( selector === ':dom' )
- return instances.every(inst => {
- return utils.isDOMComponent(getPublicInst(inst))
- })
-
- else if( selector === ':composite' )
- return instances.every(inst => {
- return findAll.isCompositeComponent(getPublicInst(inst))
- })
- else if ( selector[0] === '.' )
- return instances.every(inst => {
- return hasClass(rtq.dom(getPublicInst(inst)), selector.substr(1))
- })
- else
- return instances.every(inst => {
- return rtq.dom(getPublicInst(inst)).tagName.toUpperCase() === selector.toUpperCase()
- })
- },
+ is(selector) {
+ return this.filter(selector).length === this.length
+ }
trigger(event, data){
data = data || {}
@@ -228,34 +232,6 @@ ComponentCollection.prototype = {
}
}
-function _find(context, selector){
- var components;
-
- if( typeof selector === 'function') {
- components = findAll.componentsByType(context, selector)
- selector = selector.name || '<>'
- }
- else if ( !selector )
- components = findAll.findAllInRenderedTree(context, function(){ return true })
-
- else if( selector === ':dom' )
- components = findAll.findAllInRenderedTree(context, function(item){
- return utils.isDOMComponent(item)
- })
-
- else if( selector === ':composite' )
- components = findAll.findAllInRenderedTree(context, function(item){
- return !utils.isDOMComponent(item)
- })
-
- else if ( selector[0] === '.' )
- components = findAll.componentsByClassName(context, selector.substr(1))
-
- else
- components = findAll.componentsByTagName(context, selector)
-
- return components || []
-}
function unwrap(arr){
return arr && arr.length === 1 ? arr[0] : arr
diff --git a/src/instance-selector.js b/src/instance-selector.js
new file mode 100644
index 0000000..9bf5ecd
--- /dev/null
+++ b/src/instance-selector.js
@@ -0,0 +1,85 @@
+var React = require('react');
+var ReactDOM = require('react-dom')
+var ReactInstanceMap = require('react/lib/ReactInstanceMap');
+var ReactTestUtils = require('react-addons-test-utils')
+
+import { create as createCompiler, parse } from 'bill/compiler';
+import { isCompositeComponent } from './utils';
+
+let compiler = createCompiler()
+
+compiler.registerPseudo('has', function(compiledSelector) {
+ return (root, inst) => {
+ let matches = findAll(inst, compiledSelector)
+ return !!matches.length
+ }
+})
+
+compiler.registerPseudo('dom', function() {
+ return (root, inst) => {
+ return typeof root.type === 'string' && root.type.toLowerCase() === root.type
+ }
+})
+
+compiler.registerPseudo('composite', function() {
+ return (root, inst) => {
+ return typeof root.type === 'function'
+ }
+})
+
+compiler.registerNesting('any', test => anyParent.bind(null, test))
+
+compiler.registerNesting('>', test => directParent.bind(null, test))
+
+
+function findAll(inst, test, getParent = ()=> ({ parent: null }), excludeSelf = true) {
+ let found = [];
+
+ if (!inst || !inst.getPublicInstance)
+ return found;
+
+ let publicInst = inst.getPublicInstance()
+ , element = inst._currentElement
+ , parent = ()=> ({ parent: element, getParent });
+
+ if (!excludeSelf && test(element, inst, getParent))
+ found = found.concat(inst)
+
+ if (ReactTestUtils.isDOMComponent(publicInst)) {
+ let renderedChildren = inst._renderedChildren || {};
+
+ Object.keys(renderedChildren).forEach(key => {
+ found = found.concat(
+ findAll(renderedChildren[key], test, parent, false)
+ );
+ })
+ }
+ else if (isCompositeComponent(publicInst)) {
+ found = found.concat(findAll(inst._renderedComponent, test, parent, false));
+ }
+
+ return found;
+}
+
+function anyParent(test, element, inst, parentNode){
+ do {
+ var { getParent, parent } = parentNode();
+ element = parent
+ parentNode = getParent
+ } while(element && !test(element, test, getParent))
+
+ return !!element
+}
+
+function directParent(test, element, inst, parentNode) {
+ element = parentNode().parent
+ return !!(element && test(element, parentNode().getParent))
+}
+
+export function match(selector, inst, includeSelf = true) {
+ let tree = inst.getPublicInstance ? inst : ReactInstanceMap.get(inst)
+
+ return findAll(tree, compiler.compile(selector), undefined, !includeSelf)
+}
+
+export let { compile, compileRule, selector } = compiler
diff --git a/src/shallow.js b/src/shallow.js
index 0888373..5823e00 100644
--- a/src/shallow.js
+++ b/src/shallow.js
@@ -43,7 +43,6 @@ function rtq(element) {
else if (isRtq(element)) {
context = element.root
element = element.get();
- //rerender = element._rerender
}
return new ShallowCollection(element, context, rerender)
@@ -110,9 +109,6 @@ class ShallowCollection {
if (!selector)
return this
- if (typeof selector === 'function')
- return new ShallowCollection([].filter.call(this, selector), this.root)
-
let matches = match(selector, this.root);
return new ShallowCollection([].filter.call(this, el => {
@@ -120,6 +116,18 @@ class ShallowCollection {
}), this.root)
}
+ first(selector){
+ return selector
+ ? this.find(selector).first()
+ : new ShallowCollection(this[0], this.root)
+ }
+
+ last(selector){
+ return selector
+ ? this.find(selector).last()
+ : new ComponentCollection(this[this.length - 1], this.root)
+ }
+
is(selector) {
return this.filter(selector).length === this.length
}
diff --git a/src/utils.js b/src/utils.js
index 594497f..a6a25da 100644
--- a/src/utils.js
+++ b/src/utils.js
@@ -1,35 +1,5 @@
-var React = require('react');
-var ReactDOM = require('react-dom')
-var ReactInstanceMap = require('react/lib/ReactInstanceMap');
var ReactTestUtils = require('react-addons-test-utils')
-export function _findAllInRenderedTree(inst, test) {
- if (!inst || !inst.getPublicInstance)
- return [];
-
- var publicInst = inst.getPublicInstance();
-
- var ret = [];
-
- if (test(publicInst, inst)){
- ret = ret.concat(inst)
- }
-
- if (ReactTestUtils.isDOMComponent(publicInst)) {
- var key, renderedChildren = inst._renderedChildren
-
- for (key in renderedChildren) {
- if (!renderedChildren.hasOwnProperty(key)) continue;
- ret = ret.concat(_findAllInRenderedTree(renderedChildren[key], test));
- }
- }
- else if (isCompositeComponent(publicInst)) {
- ret = ret.concat(_findAllInRenderedTree(inst._renderedComponent, test));
- }
-
- return ret;
-}
-
export function isCompositeComponent(inst) {
if (ReactTestUtils.isDOMComponent(inst)) {
// Accessing inst.setState warns; just return false as that'll be what
@@ -38,41 +8,3 @@ export function isCompositeComponent(inst) {
}
return inst === null || typeof inst.render === 'function' && typeof inst.setState === 'function';
}
-
-export function isCompositeComponentWithType(inst, type) {
- if (!isCompositeComponent(inst)) return false;
- var internalInstance = ReactInstanceMap.get(inst);
- var constructor = internalInstance._currentElement.type;
- return constructor === type;
-}
-
-export function findAllInRenderedTree(inst, test){
- if (!inst) return [];
- return _findAllInRenderedTree(
- inst.getPublicInstance ? inst : ReactInstanceMap.get(inst), test);
-}
-
-export function componentsByTagName(root, tagName) {
- return findAllInRenderedTree(root, (inst) => {
- return ReactTestUtils.isDOMComponent(inst)
- && inst.tagName.toUpperCase() === tagName.toUpperCase();
- });
-}
-
-export function componentsByClassName(root, className) {
- return findAllInRenderedTree(root, (inst) => {
- if (ReactTestUtils.isDOMComponent(inst)) {
- var instClassName = ReactDOM.findDOMNode(inst).className;
- return instClassName && ('' + instClassName).split(/\s+/).indexOf(className) !== -1;
- }
- })
-}
-
-export function componentsByType(root, componentType) {
- return findAllInRenderedTree(root, (inst, privateInst) => {
- if (!isCompositeComponent(inst)) return false;
-
- var constructor = privateInst._currentElement.type;
- return constructor === componentType;
- })
-}
diff --git a/test/dom.js b/test/dom.js
index 7e63779..c8dd125 100644
--- a/test/dom.js
+++ b/test/dom.js
@@ -1,6 +1,7 @@
import React from 'react';
import { unmountComponentAtNode, render } from 'react-dom';
import $ from '../src/index';
+import { match, selector as sel } from '../src/instance-selector';
chai.use(require('sinon-chai'))
@@ -37,6 +38,24 @@ describe('DOM rendering', ()=> {
}
}
+ describe('css selector parsing', ()=>{
+
+ it('should match nested', ()=>{
+ let inst = $().get();
+
+ match('.list-wrapper', inst).length.should.equal(1)
+
+ match(sel`div.list-wrapper > ${List}`, inst).length.should.equal(1)
+
+ match(sel`${Stateless}`, inst).length.should.equal(1)
+
+ match(sel`.list-wrapper:has(${List})`, inst).length.should.equal(1)
+
+ match(sel`span:has(${List})`, inst).length.should.equal(0)
+ })
+
+ })
+
it('should wrap existing mounted component', ()=> {
let instance = render(, document.createElement('div'))
@@ -59,7 +78,7 @@ describe('DOM rendering', ()=> {
let instance = $()
instance.context.tagName.should.equal('DIV')
- expect(instance.context.parentNode).to.not.exist
+ expect(instance._mountPoint.parentNode).to.not.exist
})
it('should render element at mountPoint', ()=> {
@@ -67,7 +86,7 @@ describe('DOM rendering', ()=> {
let instance = $(, mount)
mount.children[0].classList.contains('test').should.equal(true)
- instance.context.should.equal(mount)
+ instance._mountPoint.should.equal(mount)
})
it('should render into document', ()=> {
@@ -75,7 +94,7 @@ describe('DOM rendering', ()=> {
document.querySelectorAll('.test').length.should.equal(1)
- unmountComponentAtNode(instance.context)
+ unmountComponentAtNode(instance._mountPoint)
})
it('should render mount into document', ()=> {
@@ -83,9 +102,9 @@ describe('DOM rendering', ()=> {
let instance = $(, mount, true)
document.querySelectorAll('.test').length.should.equal(1)
- instance.context.should.equal(mount)
+ instance._mountPoint.should.equal(mount)
- unmountComponentAtNode(instance.context)
+ unmountComponentAtNode(instance._mountPoint)
})
it('should work with Stateless components as root', ()=>{
@@ -151,7 +170,7 @@ describe('DOM rendering', ()=> {
let instance = $()
let result = instance.find(':composite')
- result.length.should.equal(3);
+ result.length.should.equal(2);
})
it('should find by :dom', ()=>{
@@ -259,6 +278,21 @@ describe('DOM rendering', ()=> {
})
})
+ it('should: filter()', ()=>{
+ let items = $().find('li')
+
+ items.length.should.equal(3)
+
+ items.filter('.item').length.should.equal(1)
+
+ $().find('div > *').filter(List).length.should.equal(1)
+ })
+
+ it('an empty filter should be a noop', ()=>{
+ let instance = $()
+ instance.filter().should.equal(instance)
+ })
+
it('should find single', ()=> {
let instance = $()
diff --git a/test/shallow.js b/test/shallow.js
index 1752fb4..ef734bb 100644
--- a/test/shallow.js
+++ b/test/shallow.js
@@ -87,8 +87,6 @@ describe('Shallow rendering', ()=> {
items.length.should.equal(3)
items.filter('.foo').length.should.equal(2)
-
- items.filter((el, idx) => idx === 0).length.should.equal(1)
})
it('an empty filter should be a noop', ()=>{