Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create component for Recipe card, Add storybook support #41

Merged
merged 11 commits into from
Jul 10, 2018
7 changes: 7 additions & 0 deletions .storybook/config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { configure } from '@storybook/react';

function loadStories() {
require('../src/storybook');
}

configure(loadStories, module);
19 changes: 19 additions & 0 deletions .storybook/webpack.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// you can use this file to add your custom webpack plugins, loaders and anything you like.
// This is just the basic way to add additional webpack configurations.
// For more information refer the docs: https://storybook.js.org/configurations/custom-webpack-config

// IMPORTANT
// When you add this file, we won't add the default configurations which is similar
// to "React Create App". This only has babel loader to load JavaScript.
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const config = require('../webpack.config');

module.exports = {
resolve: config.resolve,
module: {
rules: config.module.rules,
},
plugins: [
new ExtractTextPlugin('styles.css')
],
}
13 changes: 13 additions & 0 deletions __tests__/ReactElementType.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const ReactElementType = {
div: 'div',
span: 'span',
};

describe('ReactElementType', () => {
it('map contains all test types', () => {
expect(ReactElementType.div).toBe('div');
expect(ReactElementType.span).toBe('span');
});
});

export default ReactElementType;
121 changes: 121 additions & 0 deletions __tests__/components/RecipeCard.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
import React from 'react';
import renderer from 'react-test-renderer';
import { shallow } from 'enzyme';

import RecipeCard from 'components/RecipeCard/RecipeCard';
import ReactElementType from '../ReactElementType.test';

describe('RecipeCard', () => {
const title = 'Spicy Hotdogs';
const image = 'https://cdn.cnn.com/cnnnext/dam/assets/171027052520-processed-foods-exlarge-tease.jpg';
const cookTime = 20;
const description = 'Pork and beef are the traditional meats used in hot dogs. Less expensive hot dogs are often made from chicken or turkey, using low-cost mechanically separated poultry. Hot dogs often have high sodium, fat and nitrite content, ingredients linked to health problems.';
const authorName = 'Rebecca Jones';
const authorImage = 'http://www.attractivepartners.co.uk/wp-content/uploads/2017/06/profile.jpg';

it('should render without throwing an error', () => {
expect(shallow(<RecipeCard
title={title}
image={image}
cooktime={cookTime}
description={description}
authorName={authorName}
authorImage={authorImage}
/>).find('div.recipe-card').exists()).toBe(true);
});

it('should set the props correctly', () => {
const wrapper = shallow(<RecipeCard
title={title}
image={image}
cooktime={cookTime}
description={description}
authorName={authorName}
authorImage={authorImage}
/>);
const { className, children } = wrapper.props();
const classNameToElement = {};

expect(className).toBe('recipe-card');

children.forEach((child) => {
classNameToElement[child.props.className] = child;
});

// Test for recipe card main image
expect(classNameToElement['recipe-card-image'].props.alt).toBe(title);
expect(classNameToElement['recipe-card-image'].type).toBe(ReactElementType.div);
expect(typeof classNameToElement['recipe-card-image'].props.children).toBe('object');
expect(classNameToElement['recipe-card-image']
.props
.children
.props
.name).toBe(authorName);
expect(classNameToElement['recipe-card-image']
.props
.children
.props
.image).toBe(authorImage);

// Test for recipe card title
expect(classNameToElement['recipe-card-title'].props.children).toBe(title);
expect(classNameToElement['recipe-card-title'].type).toBe(ReactElementType.div);
expect(typeof classNameToElement['recipe-card-title'].props.children).toBe('string');

// Test for recipe card description
expect(classNameToElement['recipe-card-body'].props.children).toBe(description);
expect(classNameToElement['recipe-card-body'].type).toBe(ReactElementType.div);
expect(typeof classNameToElement['recipe-card-body'].props.children).toBe('string');

// Test for recipe card footer
expect(classNameToElement['recipe-card-footer'].type).toBe(ReactElementType.div);
expect(typeof classNameToElement['recipe-card-footer'].props.children).toBe('object');
expect(classNameToElement['recipe-card-footer']
.props
.children[0]
.type).toBe(ReactElementType.div);

// Test for recipe card footer cooktime
expect(classNameToElement['recipe-card-footer']
.props
.children[0]
.props
.className).toBe('recipe-card-cooktime');
expect(typeof classNameToElement['recipe-card-footer']
.props
.children[0]
.props
.children).toBe('object');
expect(classNameToElement['recipe-card-footer']
.props
.children[0].props.children[0].type.displayName).toBe('FontAwesomeIcon');
expect(classNameToElement['recipe-card-footer']
.props
.children[0].props.children[1].type).toBe(ReactElementType.span);
expect(classNameToElement['recipe-card-footer']
.props
.children[0]
.props
.children[1]
.props
.children[0]).toBe(cookTime);

// Test for recipe card like
expect(typeof classNameToElement['recipe-card-footer']
.props
.children[1]
.type).toBe('function');
});

it('should render deep correctly', () => {
const tree = renderer.create(<RecipeCard
title={title}
image={image}
cooktime={cookTime}
description={description}
authorName={authorName}
authorImage={authorImage}
/>);
expect(tree).toMatchSnapshot();
});
});
81 changes: 81 additions & 0 deletions __tests__/components/__snapshots__/RecipeCard.test.jsx.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`RecipeCard should render deep correctly 1`] = `
<div
className="recipe-card"
>
<div
alt="Spicy Hotdogs"
className="recipe-card-image"
style={
Object {
"backgroundImage": "linear-gradient(to bottom, rgba(255,255,255,0) 20%, rgba(245, 242, 242, 1)), url(https://cdn.cnn.com/cnnnext/dam/assets/171027052520-processed-foods-exlarge-tease.jpg)",
}
}
>
<div
className="user-chip"
>
<img
alt="Rebecca Jones"
src="http://www.attractivepartners.co.uk/wp-content/uploads/2017/06/profile.jpg"
/>
Rebecca Jones
</div>
</div>
<div
className="recipe-card-title"
>
Spicy Hotdogs
</div>
<div
className="recipe-card-body"
>
Pork and beef are the traditional meats used in hot dogs. Less expensive hot dogs are often made from chicken or turkey, using low-cost mechanically separated poultry. Hot dogs often have high sodium, fat and nitrite content, ingredients linked to health problems.
</div>
<div
className="recipe-card-footer"
>
<div
className="recipe-card-cooktime"
>
<svg
aria-hidden="true"
className="svg-inline--fa fa-clock fa-w-16 "
data-icon="clock"
data-prefix="far"
role="img"
style={Object {}}
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8zm0 448c-110.5 0-200-89.5-200-200S145.5 56 256 56s200 89.5 200 200-89.5 200-200 200zm61.8-104.4l-84.9-61.7c-3.1-2.3-4.9-5.9-4.9-9.7V116c0-6.6 5.4-12 12-12h32c6.6 0 12 5.4 12 12v141.7l66.8 48.6c5.4 3.9 6.5 11.4 2.6 16.8L334.6 349c-3.9 5.3-11.4 6.5-16.8 2.6z"
fill="currentColor"
style={Object {}}
/>
</svg>
<span>
20
minutes
</span>
</div>
<button
className="like-container"
>
<button
className="like-area"
onClick={[Function]}
/>
<div
className="like-heart"
/>
<span
className="like-count"
>

</span>
</button>
</div>
</div>
`;
Loading