Skip to content

Commit

Permalink
Refactor react plugin (#11)
Browse files Browse the repository at this point in the history
* Refactor react plugin and tests

* Add docs for react plugin
  • Loading branch information
jamiebuilds authored Jun 15, 2016
1 parent 9254efe commit 561a3c9
Show file tree
Hide file tree
Showing 6 changed files with 152 additions and 157 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,22 @@ prettyFormat(obj, {
// "bar": Object {}
// }
```

#### ReactTestComponent plugin

```js
var prettyFormat = require('pretty-format');
var reactPlugin = require('pretty-format/plugins/ReactTestComponent');

var React = require('react');
var renderer = require('react/lib/ReactTestRenderer');

var jsx = React.createElement('h1', null, 'Hello World');

prettyFormat(renderer.create(jsx).toJSON(), {
plugins: [reactPlugin]
});
// <h1>
// Hello World
// </h1>
```
5 changes: 2 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,8 @@ function printWithPlugin(plugin, val, refs, opts, state) {
return print(val, refs, opts, state);
}

function boundIndent(val, options) {
options = options || opts;
return indent(val, options);
function boundIndent(val) {
return indent(val, opts);
}

return plugin.print(val, boundPrint, boundIndent);
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"bugs": "https://github.com/thejameskyle/pretty-format/issues",
"homepage": "https://github.com/thejameskle/pretty-format",
"scripts": {
"test": "mocha test.js test-plugins-ReactTestComponent.js"
"test": "mocha test.js"
},
"devDependencies": {
"mocha": "^2.1.0",
Expand Down
80 changes: 33 additions & 47 deletions plugins/ReactTestComponent.js
Original file line number Diff line number Diff line change
@@ -1,64 +1,50 @@
var reactTestInstance = Symbol.for('react.test.json');

function handleChildren(children, indentation, print, indent) {
var result = '';
if (children) {
children.forEach(function(child) {
result += '\n' + objectToJSX(child, indentation, print, indent);
});
result += '\n';
}
return result;
function printChildren(children, print, indent) {
return children.map(function(child) {
return printElement(child, print, indent);
}).join('\n');
}

function handleProps(node, indentation, print, indent) {
var props = node.props;
var result = '';
if (props) {
var indentOpts = {
indent: 2 * (indentation + 1)
};
Object.keys(props).forEach(function(prop) {
result += '\n' + indent(prop, indentOpts) + '=';
var value = props[prop];
if (typeof value === 'string') {
result += '"' + value + '"';
} else {
var formatted = indent(print(value), {indent: 2 * (indentation + 2)});
result += '{\n' + formatted + '\n' + indent('}', indentOpts);
}
});
}
return result;
function printProps(props, print, indent) {
return Object.keys(props).map(function(name) {
var prop = props[name];
var printed = print(prop);

if (typeof prop !== 'string') {
printed = '{\n' + indent(indent(printed) + '\n}');
}

return '\n' + indent(name + '=') + printed;
}).join('');
}

function objectToJSX(root, indentation, print, indent) {
indentation = indentation || 0;
var indentationOpts = {indent: indentation * 2};
var type = root.type;
if (!type && typeof root === 'string'){
return indent(root, indentationOpts);
function printElement(element, print, indent) {
if (typeof element === 'string') {
return element;
}
var result = '';
if (!root.children) {
result += indent('<', indentationOpts) + type;
result += handleProps(root, indentation, print, indent);
result += ' />';

var result = '<' + element.type;

if (element.props) {
result += printProps(element.props, print, indent);
}

if (element.children) {
var children = printChildren(element.children, print, indent);
result += '>\n' + indent(children) + '\n</' + element.type + '>';
} else {
result += indent('<', indentationOpts) + type;
result += handleProps(root, indentation, print, indent);
result += '>';
result += handleChildren(root.children, indentation + 1, print, indent);
result += indent('</', indentationOpts) + type + '>';
result += ' />';
}

return result;
}

module.exports = {
test: function(object){
test: function(object) {
return object && object.$$typeof === reactTestInstance;
},
print: function(val, print, indent){
return objectToJSX(val, 0, print, indent);
print: function(val, print, indent) {
return printElement(val, print, indent);
}
};
105 changes: 0 additions & 105 deletions test-plugins-ReactTestComponent.js

This file was deleted.

98 changes: 97 additions & 1 deletion test.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
var assert = require('assert');
var prettyFormat = require('./');

var React = require('react');
var ReactTestComponent = require('./plugins/ReactTestComponent');
var renderer = require('react/lib/ReactTestRenderer');

function returnArguments() {
return arguments;
}

function assertPrintedJSX(actual, expected) {
assert.equal(
prettyFormat(renderer.create(actual).toJSON(), {
plugins: [ReactTestComponent]
}),
expected
);
}

describe('prettyFormat()', function() {
it('should print empty arguments', function() {
var val = returnArguments();
Expand Down Expand Up @@ -239,5 +252,88 @@ describe('prettyFormat()', function() {
}
}]
}), 'class Foo');
})
});

describe('ReactTestComponent plugin', function() {
var Mouse = React.createClass({
getInitialState: function() {
return { mouse: 'mouse' };
},
handleMoose: function() {
this.setState({ mouse: 'moose' });
},
render: function() {
return React.createElement('div', null, this.state.mouse);
}
});

it('should support a single element with no props or children', function() {
assertPrintedJSX(
React.createElement('Mouse'),
'<Mouse />'
);
});

it('should support a single element with no props or children', function() {
assertPrintedJSX(
React.createElement('Mouse', null, 'Hello World'),
'<Mouse>\n Hello World\n</Mouse>'
);
});

it('should support props with strings', function() {
assertPrintedJSX(
React.createElement('Mouse', { style: 'color:red' }),
'<Mouse\n style="color:red" />'
);
});

it('should support a single element with a function prop', function() {
assertPrintedJSX(
React.createElement('Mouse', { onclick: function onclick(){} }),
'<Mouse\n onclick={\n function onclick(){}\n } />'
);
});

it('should support a single element with a object prop', function() {
assertPrintedJSX(
React.createElement('Mouse', { customProp: { one: '1', two: 2 } }),
'<Mouse\n customProp={\n Object {\n "one": "1",\n "two": 2\n }\n } />'
);
});

it('should support an element with and object prop and children', function() {
assertPrintedJSX(
React.createElement('Mouse', { customProp: { one: '1', two: 2 } },
React.createElement('Mouse')
),
'<Mouse\n customProp={\n Object {\n "one": "1",\n "two": 2\n }\n }>\n <Mouse />\n</Mouse>'
);
});

it('should support an element with complex props and mixed children', function() {
assertPrintedJSX(
React.createElement('Mouse', { customProp: { one: '1', two: 2 }, onclick: function(){} },
'HELLO',
React.createElement('Mouse'), 'CIAO'
),
'<Mouse\n customProp={\n Object {\n "one": "1",\n "two": 2\n }\n }\n onclick={\n function (){}\n }>\n HELLO\n <Mouse />\n CIAO\n</Mouse>'
);
});

it('should support everything all together', function() {
assertPrintedJSX(
React.createElement('Mouse', { customProp: { one: '1', two: 2 }, onclick: function(){} },
'HELLO',
React.createElement('Mouse', { customProp: { one: '1', two: 2 }, onclick: function(){} },
'HELLO',
React.createElement('Mouse'),
'CIAO'
),
'CIAO'
),
'<Mouse\n customProp={\n Object {\n "one": "1",\n "two": 2\n }\n }\n onclick={\n function (){}\n }>\n HELLO\n <Mouse\n customProp={\n Object {\n "one": "1",\n "two": 2\n }\n }\n onclick={\n function (){}\n }>\n HELLO\n <Mouse />\n CIAO\n </Mouse>\n CIAO\n</Mouse>'
);
});
});
});

0 comments on commit 561a3c9

Please sign in to comment.