Skip to content

Instantly share code, notes, and snippets.

@vjwilson
Last active September 20, 2017 00:19
Show Gist options
  • Save vjwilson/bf976b4d49dd1db9d287b1e1bc007360 to your computer and use it in GitHub Desktop.
Save vjwilson/bf976b4d49dd1db9d287b1e1bc007360 to your computer and use it in GitHub Desktop.
# edit App component tests
touch src/components/App/App.test.js
# edit App component
touch src/components/App/App.js
# edit LinkItem component tests
touch src/components/LinkItem/LinkItem.test.js
# edit LinkItem component
touch src/components/LinkItem/LinkItem.js
# edit LinkList component tests
touch src/components/LinkList/LinkList.test.js
# edit LinkItem component
touch src/components/LinkList/LinkList.js
# edit App.js to include a LinkList
@@ -9,21 +9,30 @@ class App extends Component {
constructor(props) {
super(props);
- const links = [
- {
- linkUrl: 'http://www.csszengarden.com',
- favorites: 10
- },
- {
- linkUrl: 'http://www.daringfireball.com',
- favorites: 15
- }
- ];
-
this.state = {
- links: links
+ links: props.links
};
+
+ this.incrementLinkCount = this.incrementLinkCount.bind(this);
+ }
+
+ incrementLinkCount(linkUrl) {
+ const updatedLinkList = this.state.links.map((link) => {
+ if (link.linkUrl === linkUrl) {
+ return {
+ linkUrl: link.linkUrl,
+ favorites: link.favorites + 1
+ };
+ } else {
+ return link;
+ }
+ });
+
+ this.setState({
+ links: updatedLinkList
+ });
}
+
render() {
return (
<div className="app">
@@ -32,7 +41,7 @@ class App extends Component {
<h1>Welcome to Linkshare</h1>
</header>
<main className="app-intro">
- <LinkList links={this.state.links} />
+ <LinkList links={this.state.links} increment={this.incrementLinkCount} />
</main>
<footer className="app-footer">
<span className="attribution">
@@ -1,33 +1,62 @@
import React from 'react';
-import { shallow } from 'enzyme';
+import { shallow, mount } from 'enzyme';
import App from './App';
-
-it('renders without crashing', () => {
- const wrapper = shallow(<App />);
- expect(wrapper).toBeTruthy();
-});
-
-it('renders a header with the appropriate class', () => {
- const wrapper = shallow(<App />);
-
- const header = wrapper.find('header');
-
- expect(header).toHaveClassName('app-header');
-});
-
-it('renders a main element', () => {
- const wrapper = shallow(<App />);
-
- const header = wrapper.find('main');
-
- expect(header).toHaveClassName('app-intro');
-});
-
-it('renders a footer', () => {
- const wrapper = shallow(<App />);
-
- const header = wrapper.find('footer');
-
- expect(header).toHaveClassName('app-footer');
+import LinkItem from '../LinkItem/LinkItem';
+
+describe('App component', () => {
+ it('renders without crashing', () => {
+ const wrapper = shallow(<App />);
+ expect(wrapper).toBeTruthy();
+ });
+
+ it('renders a header with the appropriate class', () => {
+ const wrapper = shallow(<App />);
+
+ const header = wrapper.find('header');
+
+ expect(header).toHaveClassName('app-header');
+ });
+
+ it('renders a main element', () => {
+ const wrapper = shallow(<App />);
+
+ const header = wrapper.find('main');
+
+ expect(header).toHaveClassName('app-intro');
+ });
+
+ it('renders a footer', () => {
+ const wrapper = shallow(<App />);
+
+ const header = wrapper.find('footer');
+
+ expect(header).toHaveClassName('app-footer');
+ });
+
+ it('should increment the specified favorite count', () => {
+ const links = [
+ {
+ linkUrl: 'http://www.csszengarden.com',
+ favorites: 10
+ },
+ {
+ linkUrl: 'https://daringfireball.net',
+ favorites: 15
+ }
+ ];
+ const linkToTest = 1;
+ const secondLinkCount = links[linkToTest].favorites;
+ const props = {
+ links: links
+ };
+ const wrapper = mount(<App {...props} />);
+
+ const secondAddButton = wrapper.find(LinkItem).at(linkToTest);
+ secondAddButton.find('.add-fave').simulate('click');
+
+ const updatedLinks = wrapper.state('links');
+ const secondLinkInState = updatedLinks[linkToTest];
+ expect(secondLinkInState.favorites).toEqual(secondLinkCount + 1);
+ });
});
@@ -2,12 +2,18 @@ import React from 'react';
import './LinkItem.css';
-const LinkItem = ({ favoriteCount, linkUrl }) => {
+const LinkItem = ({ favoriteCount, linkUrl, action }) => {
const faves = favoriteCount || 0;
+ const onClick = ((e) => {
+ action(linkUrl);
+ });
return (
<div className="link-item">
- <div className="link-item-faves">{faves}</div>
+ <div className="link-item-faves">
+ <span className="fave-count">{faves}</span>
+ <button onClick={onClick} className="add-fave">+</button>
+ </div>
<div className="link-item-info">
<a className="link-item-link" href={linkUrl}>{linkUrl}</a>
</div>
@@ -7,7 +7,7 @@ import LinkItem from './LinkItem';
describe('LinkItem component', () => {
it('renders without crashing', () => {
const wrapper = shallow(<LinkItem />);
- expect(wrapper).toBeTruthy();
+ expect(wrapper).toHaveLength(1);
});
it('should have the appropriate class', () => {
@@ -35,15 +35,15 @@ describe('LinkItem component', () => {
it('should render its favorites prop', () => {
const wrapper = shallow(<LinkItem favoriteCount="12" />);
- const favorites = wrapper.find('.link-item-faves');
+ const favorites = wrapper.find('.fave-count');
expect(favorites.text()).toEqual('12');
});
it('should render 0 for favorites if no prop is given', () => {
const wrapper = shallow(<LinkItem />);
- const favorites = wrapper.find('.link-item-faves');
+ const favorites = wrapper.find('.fave-count');
expect(favorites.text()).toEqual('0');
});
@@ -63,4 +63,29 @@ describe('LinkItem component', () => {
expect(linkAnchor.prop('href')).toEqual('http://www.daringfireball.com');
});
+
+ it('should have an Add button in its favorites child', () => {
+ const wrapper = shallow(<LinkItem />);
+
+ const favoritesChild = wrapper.find('.link-item-faves');
+ const addFaveButton = favoritesChild.find('button');
+
+ expect(addFaveButton).toHaveLength(1);
+ expect(addFaveButton).toHaveClassName('add-fave');
+ });
+
+ it('should call the action prop when the Add button is clicked', () => {
+ const mock = jest.fn();
+ const props = {
+ favoriteCount: 11,
+ linkUrl: 'https://alistapart.com',
+ action: mock
+ }
+ const wrapper = shallow(<LinkItem {...props} />);
+
+ const addFaveButton = wrapper.find('.add-fave');
+ addFaveButton.simulate('click');
+
+ expect(mock).toHaveBeenCalled();
+ });
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment