UNPKG

d2-ui

Version:
288 lines (241 loc) 7.9 kB
import React from 'react'; import sinon from 'sinon'; import { expect } from 'chai'; import { splitSelector, } from '../src/Utils'; import { hasClassName, nodeHasProperty, treeForEach, treeFilter, pathToNode, getTextFromNode, } from '../src/ShallowTraversal'; describe('ShallowTraversal', () => { describe('splitSelector', () => { const fn = splitSelector; it('splits multiple class names', () => { expect(fn('.foo.bar')).to.eql(['.foo', '.bar']); expect(fn('.foo.bar.baz')).to.eql(['.foo', '.bar', '.baz']); }); it('splits tag names and class names', () => { expect(fn('input.bar')).to.eql(['input', '.bar']); expect(fn('div.bar.baz')).to.eql(['div', '.bar', '.baz']); expect(fn('Foo.bar')).to.eql(['Foo', '.bar']); }); it('splits tag names and attributes', () => { expect(fn('input[type="text"]')).to.eql(['input', '[type="text"]']); expect( fn('div[title="title"][data-value="foo"]') ).to.eql(['div', '[title="title"]', '[data-value="foo"]']); }); }); describe('hasClassName', () => { it('should work for standalone classNames', () => { const node = (<div className="foo" />); expect(hasClassName(node, 'foo')).to.equal(true); expect(hasClassName(node, 'bar')).to.equal(false); }); it('should work for multiple classNames', () => { const node = (<div className="foo bar baz" />); expect(hasClassName(node, 'foo')).to.equal(true); expect(hasClassName(node, 'bar')).to.equal(true); expect(hasClassName(node, 'baz')).to.equal(true); expect(hasClassName(node, 'bax')).to.equal(false); }); it('should also allow hyphens', () => { const node = (<div className="foo-bar" />); expect(hasClassName(node, 'foo-bar')).to.equal(true); }); }); describe('nodeHasProperty', () => { it('should find properties', () => { function noop() {} const node = (<div onChange={noop} title="foo" />); expect(nodeHasProperty(node, 'onChange')).to.equal(true); expect(nodeHasProperty(node, 'title', '"foo"')).to.equal(true); }); it('should not match on html attributes', () => { const node = (<div htmlFor="foo" />); expect(nodeHasProperty(node, 'for', '"foo"')).to.equal(false); }); it('should not find undefined properties', () => { const node = (<div title={undefined} />); expect(nodeHasProperty(node, 'title')).to.equal(false); }); it('should parse false as a literal', () => { const node = (<div foo={false} />); expect(nodeHasProperty(node, 'foo', 'false')).to.equal(true); }); it('should parse false as a literal', () => { const node = (<div foo />); expect(nodeHasProperty(node, 'foo', 'true')).to.equal(true); }); it('should parse numbers as numeric literals', () => { expect(nodeHasProperty(<div foo={2.3} />, 'foo', '2.3')).to.equal(true); expect(nodeHasProperty(<div foo={2} />, 'foo', '2')).to.equal(true); expect(() => nodeHasProperty(<div foo={2} />, 'foo', '2abc')).to.throw(); expect(() => nodeHasProperty(<div foo={2} />, 'foo', 'abc2')).to.throw(); expect(nodeHasProperty(<div foo={-2} />, 'foo', '-2')).to.equal(true); expect(nodeHasProperty(<div foo={2e8} />, 'foo', '2e8')).to.equal(true); expect(nodeHasProperty(<div foo={Infinity} />, 'foo', 'Infinity')).to.equal(true); expect(nodeHasProperty(<div foo={-Infinity} />, 'foo', '-Infinity')).to.equal(true); }); it('should throw when un unquoted string is passed in', () => { const node = (<div title="foo" />); expect(() => nodeHasProperty(node, 'title', 'foo')).to.throw(); }); }); describe('treeForEach', () => { it('should be called once for a leaf node', () => { const spy = sinon.spy(); const node = (<div />); treeForEach(node, spy); expect(spy.calledOnce).to.equal(true); }); it('should handle a single child', () => { const spy = sinon.spy(); const node = ( <div> <div /> </div> ); treeForEach(node, spy); expect(spy.callCount).to.equal(2); }); it('should handle several children', () => { const spy = sinon.spy(); const node = ( <div> <div /> <div /> </div> ); treeForEach(node, spy); expect(spy.callCount).to.equal(3); }); it('should handle multiple hierarchies', () => { const spy = sinon.spy(); const node = ( <div> <div> <div /> <div /> </div> </div> ); treeForEach(node, spy); expect(spy.callCount).to.equal(4); }); it('should not get trapped from empty strings', () => { const spy = sinon.spy(); const node = ( <div> <p>{""}</p> </div> ); treeForEach(node, spy); expect(spy.callCount).to.equal(3); }); it('should pass in the node', () => { const spy = sinon.spy(); const node = ( <div> <button /> <nav> <input /> </nav> </div> ); treeForEach(node, spy); expect(spy.callCount).to.equal(4); expect(spy.args[0][0].type).to.equal('div'); expect(spy.args[1][0].type).to.equal('button'); expect(spy.args[2][0].type).to.equal('nav'); expect(spy.args[3][0].type).to.equal('input'); }); }); describe('treeFilter', () => { const tree = ( <div> <button /> <button /> <nav> <input /> </nav> </div> ); it('should return an empty array for falsey test', () => { expect(treeFilter(tree, () => false).length).to.equal(0); }); it('should return the full array for truthy test', () => { expect(treeFilter(tree, () => true).length).to.equal(5); }); it('should filter for truthiness', () => { expect(treeFilter(tree, node => node.type === 'nav').length).to.equal(1); expect(treeFilter(tree, node => node.type === 'button').length).to.equal(2); }); }); describe('pathToNode', () => { it('should return trees from the root node', () => { const node = <label />; const tree = ( <div> <button /> <nav> {node} <input /> </nav> </div> ); const result = pathToNode(node, tree); expect(result.length).to.equal(2); expect(result[0].type).to.equal('div'); expect(result[1].type).to.equal('nav'); }); it('should return trees from the root node except the sibling node', () => { const node = <label />; const tree = ( <div> <button /> <nav> {node} <div><input /></div> </nav> </div> ); const result = pathToNode(node, tree); expect(result.length).to.equal(2); expect(result[0].type).to.equal('div'); expect(result[1].type).to.equal('nav'); }); }); describe('getTextFromNode', () => { it('should return displayName for functions that provides one', () => { class Subject extends React.Component { render() { return ( <div /> ); } } Subject.displayName = 'CustomSubject'; const node = <Subject />; const result = getTextFromNode(node); expect(result).to.equal('<CustomSubject />'); }); it('should return function name if displayName is not provided', () => { class Subject extends React.Component { render() { return ( <div /> ); } } const node = <Subject />; const result = getTextFromNode(node); expect(result).to.equal('<Subject />'); }); }); });