Skip to content

Instantly share code, notes, and snippets.

@busypeoples
Last active May 12, 2016 21:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save busypeoples/03219349cf662492b536a3383e426ea3 to your computer and use it in GitHub Desktop.
Save busypeoples/03219349cf662492b536a3383e426ea3 to your computer and use it in GitHub Desktop.
Devcards for React - initial ideas
import React from 'react';
import { render } from 'react-dom';
const DevCards = require('./DevCardsIndex').DevCards;
import foobar from './SomeComponent';
import StateBar from './SomeStatefulComponent';
const dc = DevCards();
dc.test('do something', foobar, { name: 'foo', model: 1 }, 'Testdrive. Stateless Yes.foo1');
dc.card(StateBar, { left: 20 }, 'test .stateful component!');
dc.card(foobar, { name: 'foobar', model: 1 }, 'some state...');
dc.card(foobar, { name: 'foobar', model: 2 }, 'some state...');
dc.mount(window.app);
import React, { PropTypes, Component } from 'react';
import { createStore, combineReducers } from 'redux';
import { render } from 'react-dom';
let devCardTest = require('./DevCardsTest.js').default;
const devCardStyle = {
background: '#eee',
padding: '20px',
marginBottom: '10px'
};
class DevCardApp extends Component {
render() {
const { cards } = this.props;
return (
<div>
{cards.map((c, index) => {
const { Component, props, headline } = c;
return (
<div key={`component-${index}`} >
<h5>Dev Card {headline? headline : null}</h5>
<div style={devCardStyle}>
<Component key={`components-${index}`} {...props} />
</div>
</div>
)
})}
</div>
);
}
}
const TestResult = ({ results }) => {
const hasError = results.filter((r) => {
return!( typeof r.ok === 'undefined' || r.ok);
});
const style = hasError.length > 0? {color: 'red'} : {color: 'green'};
return <div style={style}>
{ results.map((r,i) => {
return <div key={`component-test-${i}`}>{ r.name }</div>
})}
</div>
};
export function DevCards() {
const cards = [];
const card = (Component, props, headline) => {
cards.push({Component, props, headline})
};
const devTest = devCardTest(function(results) {
card(TestResult, { results: results }, 'Testing Component');
mount(window.app);
});
const mount = (mountNode) => {
return render(<DevCardApp cards={cards}/>, mountNode);
}
return {
card: card,
test(headline, Component, props, expected) {
devTest(headline, Component, props, expected);
},
mount: mount,
}
}
import test from 'tape';
import React from 'react';
import { shallow } from 'enzyme';
function devCardTest(cb) {
return function(title, Component, props, expected) {
let results = [];
const tapeStream = test.createStream({objectMode: true})
const tapeStream1 = test.createStream({objectMode: true})
function callback() {
cb(results);
results = [];
test.getHarness()._results.removeAllListeners()
}
function addRow(row) {
results.push(row);
}
tapeStream.on('data', addRow);
tapeStream1.on('end', callback);
test(title, (assert) => {
const wrapper = shallow(<Component {...props}/>);
assert.equal(wrapper.text(), expected);
});
}
}
export default devCardTest;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Example</title>
<style>
.inactive {
text-decoration: line-through;
}
</style>
</head>
<body>
<div id="app"></div>
</body>
</html>
let dev = require('./devcards.js');
module.hot.accept('./devcards.js', function() {
dev = require('./devcards.js');
});
{
"name": "dev-cards-example",
"main": "index.js",
"scripts": {
"start": "webpack-dev-server --hot",
"build": "webpack --config webpack.config.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"react": "^0.14.8",
"react-dom": "^0.14.8",
"redux": "^3.5.2"
},
"devDependencies": {
"babel-core": "^6.7.4",
"babel-loader": "^6.2.4",
"babel-preset-es2015": "^6.6.0",
"babel-preset-react": "^6.5.0",
"babel-preset-react-hmre": "^1.1.1",
"enzyme": "^2.2.0",
"html-webpack-plugin": "^2.16.1",
"react-addons-test-utils": "^0.14",
"react-hot-loader": "^1.3.0",
"tape": "^4.5.1",
"webpack": "^1.12",
"webpack-dev-server": "^1.14"
},
"babel": {
"presets": [
"es2015",
"react"
]
}
}
import React, { PropTypes } from 'react';
const foobar = (props) => (
<div>
<h3>Testdrive. Stateless Yes.</h3>
<div>{props.name}</div>
<div>{props.model}</div>
</div>
);
foobar.propTypes = {
name: PropTypes.string.isRequired,
model: PropTypes.number.isRequired,
};
export default foobar;
import React, { Component } from 'react';
export default class SomeStatefulComponent extends Component {
constructor(props) {
super(props);
this.state = {ticked: 0, left: 0};
this.tick = null;
}
componentDidMount() {
this.transition(this.props);
}
componentWillReceiveProps(nextProps) {
//this.transition(nextProps);
}
transition(nextProps) {
// some random and quick transition example...
this.tick = setInterval(function() {
let ticked = this.state.ticked + 1;
let left = this.state.left;
if (left < nextProps.left) {
left += 1;
} else if (nextProps.left < left) {
left -= 1;
} else {
clearInterval(this.tick);
}
this.setState({ticked: ticked, left: left });
}.bind(this), Math.abs(nextProps.left - this.state.left)/1000);
}
componentWillUnmount() {
clearInterval(this.tick);
}
render() {
const left = this.state.left;
return <div>
<div style={{ paddingLeft: `${left}px` }}>Some Other Box
..</div>
</div>
}
}
'use strict';
const path = require('path');
const Webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const PORT = 8080;
const ASSETS_PATH = path.resolve(__dirname, 'build');
const NAME = 'index.js';
const SERVER_URL = 'http://localhost:' + PORT;
module.exports = {
debug: true,
devtool: 'eval-source-map',
entry: [
'./' + NAME
],
output: {
path: ASSETS_PATH,
filename: NAME,
publicPath: SERVER_URL + '/',
},
module: {
loaders: [
{ test: /\.js$/, loaders: ['react-hot', 'babel'], exclude: /node_modules/ },
],
},
plugins: [
new Webpack.NoErrorsPlugin(),
new HtmlWebpackPlugin({ template: './index.html', inject: 'body' }),
],
devServer: {
port: PORT,
contentBase: ASSETS_PATH,
hot: true,
quiet: false,
noInfo: false,
inline: true,
colors: true,
historyApiFallback: true
},
node: {
fs: "empty"
},
externals: {
"cheerio": "window",
"react/addons": true,
"react/lib/ExecutionEnvironment": true,
"react/lib/ReactContext": true
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment