Skip to content

Commit

Permalink
Add support for new types to debug()
Browse files Browse the repository at this point in the history
  • Loading branch information
jquense committed Apr 4, 2018
1 parent 5d037c2 commit 704a600
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 4 deletions.
32 changes: 31 additions & 1 deletion packages/enzyme-test-suite/test/ShallowWrapper-spec.jsx
Expand Up @@ -6,7 +6,7 @@ import { shallow, render, ShallowWrapper, mount } from 'enzyme';
import { ITERATOR_SYMBOL, withSetStateAllowed, sym } from 'enzyme/build/Utils';

import './_helpers/setupAdapters';
import { createClass, createContext, forwardRef } from './_helpers/react-compat';
import { createClass, createContext, forwardRef, createPortal } from './_helpers/react-compat';
import { describeIf, itIf, itWithData, generateEmptyRenderData } from './_helpers';
import { REACT013, REACT014, REACT15, REACT150_4, REACT16, REACT163, is } from './_helpers/version';

Expand Down Expand Up @@ -2957,6 +2957,36 @@ describe('shallow', () => {
it('should pass through to the debugNodes function', () => {
expect(shallow(<div />).debug()).to.equal('<div />');
});

itIf(REACT163, 'should handle internal types gracefully', () => {
const { Provider, Consumer } = createContext(null);
// eslint-disable-next-line prefer-arrow-callback
const Forwarded = forwardRef(function MyComponent(props) {
return (
<Provider value={5}>
<Forwarded />
<div {...props}>
<React.Fragment>
<Consumer>{() => <div />}</Consumer>
{createPortal(<span />, { nodeType: 1 })}
</React.Fragment>
</div>
</Provider>
);
});

expect(shallow(<Forwarded />).debug()).to.equal(`<ContextProvider value={5}>
<ForwardRef(MyComponent) />
<div>
<Fragment>
<ContextConsumer>
[function child]
</ContextConsumer>
<Portal />
</Fragment>
</div>
</ContextProvider>`);
});
});

describe('.html()', () => {
Expand Down
35 changes: 32 additions & 3 deletions packages/enzyme/src/Debug.js
Expand Up @@ -12,13 +12,41 @@ import {
propsOfNode,
childrenOfNode,
} from './RSTTraversal';
import {
typeOf,
AsyncMode,
ContextProvider,
ContextConsumer,
Element,
ForwardRef,
Fragment,
Portal,
StrictMode,
} from './Utils';

const booleanValue = Function.bind.call(Function.call, Boolean.prototype.valueOf);


export function typeName(node) {
return typeof node.type === 'function'
? (node.type.displayName || functionName(node.type) || 'Component')
: node.type;
const { type } = node;
switch (typeOf(node)) {
case AsyncMode: return 'AsyncMode';
case ContextProvider: return 'ContextProvider';
case ContextConsumer: return 'ContextConsumer';
case Portal: return 'Portal';
case StrictMode: return 'StrictMode';
case ForwardRef: {
const name = type.render.displayName || functionName(type.render);
return name ? `ForwardRef(${name})` : 'ForwardRef';
}
case Fragment:
return 'Fragment';
case Element:
default:
return typeof node.type === 'function'
? (type.displayName || functionName(type) || 'Component')
: type || 'unknown';
}
}

export function spaces(n) {
Expand Down Expand Up @@ -66,6 +94,7 @@ function indentChildren(childrenStrs, indentLength) {

export function debugNode(node, indentLength = 2, options = {}) {
if (typeof node === 'string' || typeof node === 'number') return escape(node);
if (typeof node === 'function') return '[function child]';
if (!node) return '';

const childrenStrs = compact(childrenOfNode(node).map(n => debugNode(n, indentLength, options)));
Expand Down
39 changes: 39 additions & 0 deletions packages/enzyme/src/Utils.js
Expand Up @@ -7,8 +7,47 @@ import configuration from './configuration';
import validateAdapter from './validateAdapter';
import { childrenOfNode } from './RSTTraversal';

const hasSymbol = typeof Symbol === 'function' && Symbol.for;

export const ITERATOR_SYMBOL = typeof Symbol === 'function' && Symbol.iterator;

// TODO use react-is when a version is released with no peer dependency on React
export const AsyncMode = hasSymbol ? Symbol.for('react.async_mode') : 0xeacf;
export const ContextProvider = hasSymbol ? Symbol.for('react.provider') : 0xeacd;
export const ContextConsumer = hasSymbol ? Symbol.for('react.context') : 0xeace;
export const Element = hasSymbol ? Symbol.for('react.element') : 0xeac7;
export const ForwardRef = hasSymbol ? Symbol.for('react.forward_ref') : 0xead0;
export const Fragment = hasSymbol ? Symbol.for('react.fragment') : 0xeacb;
export const Portal = hasSymbol ? Symbol.for('react.portal') : 0xeaca;
export const StrictMode = hasSymbol ? Symbol.for('react.strict_mode') : 0xeacc;

export function typeOf(node) {
if (node !== null) {
const { type, $$typeof } = node;

switch (type || $$typeof) {
case AsyncMode:
case Fragment:
case StrictMode:
return type;
default: {
const $$typeofType = type && type.$$typeof;

switch ($$typeofType) {
case ContextConsumer:
case ForwardRef:
case Portal:
case ContextProvider:
return $$typeofType;
default:
return type || $$typeof;
}
}
}
}
return undefined;
}

export function getAdapter(options = {}) {
if (options.adapter) {
validateAdapter(options.adapter);
Expand Down

0 comments on commit 704a600

Please sign in to comment.