Initialized .NET Core 2.1 App with SPA front end in React, Emotion, Storybook, Jest
{ | |
"presets": ["babel-preset-env", "babel-preset-react"], | |
"env": { | |
"production": { | |
"plugins": [ | |
["emotion", { | |
"hoist": true | |
}] | |
] | |
}, | |
"development": { | |
"plugins": [ | |
["emotion", { | |
"sourceMap": true, | |
"autoLabel": true, | |
"labelFormat": "⚡[local]" | |
}] | |
] | |
}, | |
"test": { | |
"plugins": [ | |
["emotion", { | |
"sourceMap": true, | |
"autoLabel": true, | |
"labelFormat": "⚡[local]" | |
}] | |
] | |
} | |
} | |
} |
import React, { | |
Component | |
} from 'react'; | |
import PropTypes from 'prop-types'; | |
import logo from '../assets/images/logo.svg'; | |
import {Container, Header, Image, H1, Text} from './themes/DefaultTheme'; | |
class App extends Component { | |
render() { | |
return ( | |
<Container center> | |
<Header> | |
<Image src={logo} alt="logo" /> | |
<H1>{this.props.welcomeMessage}</H1> | |
</Header> | |
<Text> | |
To get started, edit | |
<code> | |
{this.props.fileLocation} | |
</code> and save to reload. | |
</Text> | |
</Container> | |
); | |
} | |
} | |
App.propTypes = { | |
fileLocation: PropTypes.string.isRequired, | |
welcomeMessage: PropTypes.string | |
} | |
App.defaultProps = { | |
fileLocation: 'src/components/App.js', | |
welcomeMessage: "Welcome to React!" | |
} | |
export default App; |
import React from 'react'; | |
import { storiesOf } from '@storybook/react'; | |
import { action } from '@storybook/addon-actions'; | |
import { linkTo } from '@storybook/addon-links'; | |
import App from '../components/App'; | |
storiesOf('App', module) | |
.add('default', () => <App />) | |
.add('with different welcome message', () => <App welcomeMessage="Welcome with a different welcome message" />); |
import React from 'react'; | |
import ReactDOM from 'react-dom'; | |
import renderer from 'react-test-renderer'; | |
import { mount } from 'enzyme'; | |
import App from '../components/App'; | |
it('renders without crashing', () => { | |
const div = document.createElement('div'); | |
ReactDOM.render(<App />, div); | |
ReactDOM.unmountComponentAtNode(div); | |
}); | |
it ('matches snapshot', () => { | |
const component = renderer.create(<App />); | |
let tree = component.toJSON(); | |
expect(tree).toMatchSnapshot(); | |
}); | |
it("should render the welcome message", () => { | |
const welcomeMessage = "Welcome to React!"; | |
//'shallow' will not full-render 'react-emotion' components, so use 'mount' to test | |
const wrapper = mount(<App welcomeMessage={welcomeMessage} />); | |
const text = wrapper.find("h1").text(); | |
expect(text).toEqual(welcomeMessage); | |
}); |
// config-overrides.js | |
const {injectBabelPlugin} = require('react-app-rewired'); | |
module.exports = function override(config, env) { | |
//do stuff with the webpack config... | |
config = injectBabelPlugin('babel-plugin-emotion',config) | |
return config; | |
} |
import React from 'react'; | |
import PropTypes from 'prop-types'; | |
import styled from 'react-emotion'; | |
export const Container = styled.div(props =>({ | |
'text-align': props.center && 'center', | |
'@keyframes App-logo-spin': { | |
'from': { | |
'transform': 'rotate(0deg)', | |
}, | |
'to': { | |
'transform': 'rotate(360deg)', | |
}, | |
}, | |
})); | |
Container.propTypes={ | |
center: PropTypes.bool.isRequired, | |
} | |
Container.defaultProps={ | |
center: false, | |
} | |
export const Image = styled.img({ | |
'animation': 'App-logo-spin infinite 20s linear', | |
height: '80px', | |
}); | |
export const Header = styled.header({ | |
'background-color': '#222', | |
'height': '150px', | |
'padding': '20px', | |
'color': 'white', | |
}); | |
export const H1 = styled.h1({ | |
'font-size': '1.5em', | |
}); | |
export const Text = styled.p({ | |
'font-size': 'large', | |
}); |
yarn global add create-react-app | |
yarn global add @storybook/cli | |
mkdir sampleApp | |
cd sampleApp | |
dotnet new react | |
dot dev-certs https --trust | |
rm -rf ClientApp | |
create-react-app sampleApp | |
mv sampleApp ClientApp | |
cd ClientApp | |
yarn add react-router-dom prop-types emotion react-emotion | |
yarn add -D react-app-rewired babel-plugin-emotion react-test-renderer enzyme enzyme-adapter-react-16 @storybook/addon-storyshots | |
getstorybook |
{ | |
"name": "clientapp", | |
"version": "0.1.0", | |
"private": true, | |
"dependencies": { | |
"babel-plugin-emotion": "^9.1.2", | |
"emotion": "^9.1.3", | |
"prop-types": "^15.6.1", | |
"react": "^16.4.0", | |
"react-dom": "^16.4.0", | |
"react-emotion": "^9.1.3", | |
"react-router-dom": "^4.2.2", | |
"react-scripts": "1.1.4" | |
}, | |
"scripts": { | |
"start": "react-app-rewired start", | |
"build": "react-app-rewired build", | |
"test": "set NODE_ENV=test && react-app-rewired test --env=jsdom", | |
"eject": "react--app-rewired eject", | |
"storybook": "set NODE_ENV=test && start-storybook -p 9009 -s public", | |
"build-storybook": "build-storybook -s public" | |
}, | |
"devDependencies": { | |
"@storybook/addon-actions": "^3.4.6", | |
"@storybook/addon-links": "^3.4.6", | |
"@storybook/addons": "^3.4.6", | |
"@storybook/react": "^3.4.6", | |
"babel-core": "^6.26.3", | |
"babel-runtime": "^6.26.0", | |
"enzyme": "^3.3.0", | |
"enzyme-adapter-react-16": "^1.1.1", | |
"react-app-rewired": "^1.5.2", | |
"react-test-renderer": "^16.4.0" | |
}, | |
"jest": { | |
"setupTestFrameworkScriptFile": "./src/setupTests.js" | |
} | |
} |
import Enzyme from "enzyme"; | |
import Adapter from "enzyme-adapter-react-16"; | |
Enzyme.configure({ adapter: new Adapter() }); |
import initStoryshots from '@storybook/addon-storyshots'; | |
initStoryshots(); |
const path = require("path"); | |
const { | |
injectBabelPlugin | |
} = require('react-app-rewired'); | |
module.exports = (baseConfig, env, defaultConfig) => { | |
// Extend defaultConfig as you need. | |
// For example, add typescript loader: | |
// defaultConfig.module.rules.push({ | |
// test: /\.(ts|tsx)$/, | |
// include: path.resolve(__dirname, "../src"), | |
// loader: require.resolve("ts-loader") | |
// }); | |
// defaultConfig.resolve.extensions.push(".ts", ".tsx"); | |
defaultConfig = injectBabelPlugin('babel-plugin-emotion', defaultConfig) | |
return defaultConfig; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment