diff options
| author | Wes Bos <wesbos@gmail.com> | 2018-03-14 12:19:54 -0400 |
|---|---|---|
| committer | Wes Bos <wesbos@gmail.com> | 2018-03-14 12:19:54 -0400 |
| commit | 331da87bd53bc1fb79063d142764c75df9f32170 (patch) | |
| tree | d80aac98154a811fdf57b10e90ac0350fe14568e /frontend/__tests__ | |
| parent | 46a0ba30ef54a7e36206481a4f5b2bf1f9702fca (diff) | |
tests
Diffstat (limited to 'frontend/__tests__')
| -rw-r--r-- | frontend/__tests__/CartCount.test.js | 21 | ||||
| -rw-r--r-- | frontend/__tests__/CreateItem.test.js | 85 | ||||
| -rw-r--r-- | frontend/__tests__/Item.test.js | 31 | ||||
| -rw-r--r-- | frontend/__tests__/Nav.test.js | 35 | ||||
| -rw-r--r-- | frontend/__tests__/Pagination.test.js | 46 | ||||
| -rw-r--r-- | frontend/__tests__/__snapshots__/CartCount.test.js.snap | 201 | ||||
| -rw-r--r-- | frontend/__tests__/__snapshots__/CreateItem.test.js.snap | 58 | ||||
| -rw-r--r-- | frontend/__tests__/__snapshots__/Item.test.js.snap | 60 | ||||
| -rw-r--r-- | frontend/__tests__/__snapshots__/Nav.test.js.snap | 69 | ||||
| -rw-r--r-- | frontend/__tests__/__snapshots__/Pagination.test.js.snap | 67 | ||||
| -rw-r--r-- | frontend/__tests__/formatMoney.test.js | 21 |
11 files changed, 694 insertions, 0 deletions
diff --git a/frontend/__tests__/CartCount.test.js b/frontend/__tests__/CartCount.test.js new file mode 100644 index 0000000..f3c4978 --- /dev/null +++ b/frontend/__tests__/CartCount.test.js @@ -0,0 +1,21 @@ +import React from 'react'; +import { shallow, mount } from 'enzyme'; +import toJSON from 'enzyme-to-json'; +import { CartCount } from '../components/CartCount'; + +describe('<CartCount></CartCount>', () => { + it('renders okay', () => { + shallow(<CartCount count="10" />); + }); + + it('matches snapshot', () => { + const wrapper = shallow(<CartCount count="10" />); + expect(toJSON(wrapper)).toMatchSnapshot(); + }); + it('updates via props', () => { + const wrapper = mount(<CartCount count="50" />); + expect(toJSON(wrapper)).toMatchSnapshot(); + wrapper.setProps({ count: 10 }); + expect(toJSON(wrapper)).toMatchSnapshot(); + }); +}); diff --git a/frontend/__tests__/CreateItem.test.js b/frontend/__tests__/CreateItem.test.js new file mode 100644 index 0000000..0994d9c --- /dev/null +++ b/frontend/__tests__/CreateItem.test.js @@ -0,0 +1,85 @@ +import React from 'react'; +import { shallow, mount } from 'enzyme'; +import toJSON from 'enzyme-to-json'; +import { CreateItem } from '../components/CreateItem'; + +// Wait func +const wait = amount => new Promise(resolve => setTimeout(resolve, amount)); + +const dogImage = 'https://dog.com/dog.jpg'; + +// Mock fetch to resolve data +global.fetch = jest.fn().mockResolvedValue({ + json: () => ({ + secure_url: dogImage, + eager: [{ secure_url: dogImage }], + }), +}); + +const fakeItem = { + title: 'Testing', + description: 'This is a really nice item', + image: dogImage, + largeImage: dogImage, + price: 50000, +}; + +describe('<Createitem/>', () => { + it('renders the form out', () => { + const createItemMutation = jest.fn(); + const wrapper = shallow(<CreateItem createItemMutation={createItemMutation} />); + expect(toJSON(wrapper)).toMatchSnapshot(); + }); + + it('uploads a file when changed', async () => { + const createItemMutation = jest.fn(); + const wrapper = shallow(<CreateItem createItemMutation={createItemMutation} />); + + const input = wrapper.find('input[type="file"]'); + // internally this does some setState() calls + input.simulate('change', { currentTarget: { files: ['fakedog.jpg'] } }); + await wait(0); + expect(wrapper.state('image')).toEqual(dogImage); + expect(wrapper.state('largeImage')).toEqual(dogImage); + }); + + it('handles state updating', async () => { + const createItemMutation = jest.fn(); + const wrapper = shallow(<CreateItem createItemMutation={createItemMutation} />); + + wrapper.find('#title').simulate('change', { target: { value: 'Testing', name: 'title' } }); + wrapper.find('#price').simulate('change', { + target: { + value: 50000, + name: 'price', + type: 'number', + }, + }); + wrapper.find('#description').simulate('change', { + target: { + value: 'This is a really nice item', + name: 'description', + }, + }); + expect(wrapper.state().item).toMatchObject({ + title: 'Testing', + description: 'This is a really nice item', + image: '', + largeImage: '', + price: 50000, + }); + }); + + it('creates an item with all the inputs', () => { + const createItemMutation = jest.fn(() => Promise.resolve({})); + const wrapper = shallow(<CreateItem createItemMutation={createItemMutation} />); + wrapper.setState({ item: fakeItem }); + const form = wrapper.find('Form'); + // console.log(form.debug()); + form.simulate('submit', { + preventDefault() {}, + }); + expect(createItemMutation).toHaveBeenCalled(); + expect(createItemMutation).toHaveBeenCalledWith({ variables: fakeItem }); + }); +}); diff --git a/frontend/__tests__/Item.test.js b/frontend/__tests__/Item.test.js new file mode 100644 index 0000000..2990b1f --- /dev/null +++ b/frontend/__tests__/Item.test.js @@ -0,0 +1,31 @@ +/* eslint-env jest */ + +import React from 'react'; +import Enzyme, { shallow, mount } from 'enzyme'; +import toJSON from 'enzyme-to-json'; +import { ItemComponent } from '../components/Item'; + +const fakeItem = { + id: 'ABC123', + title: 'A Cool Item', + price: 5000, + description: 'This item is really cool!', + image: 'dog.jpg', + largeImage: 'largedog.jpg', +}; + +describe('<Item/>', () => { + it('Renders an item', () => { + const removeItem = jest.fn(); + const wrapper = shallow(<ItemComponent item={fakeItem} removeItem={removeItem} />); + expect(toJSON(wrapper)).toMatchSnapshot(); + }); + it('handles button clicks', async () => { + const removeItem = jest.fn(); + global.confirm = jest.fn().mockReturnValue(true); + const wrapper = shallow(<ItemComponent item={fakeItem} removeItem={removeItem} />); + wrapper.find('button').simulate('click'); + expect(removeItem).toHaveBeenCalled(); + expect(global.confirm).toHaveBeenCalled(); + }); +}); diff --git a/frontend/__tests__/Nav.test.js b/frontend/__tests__/Nav.test.js new file mode 100644 index 0000000..49d16d6 --- /dev/null +++ b/frontend/__tests__/Nav.test.js @@ -0,0 +1,35 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import toJSON from 'enzyme-to-json'; +import { Nav } from '../components/Nav'; + +const currentUserLoggedOut = { + refetch() {}, +}; + +const currentUser = { + me: {}, + refetch() {}, +}; + +describe('<Nav></Nav>', () => { + it('renders', () => { + shallow(<Nav currentUser={currentUserLoggedOut} />); + }); + + it('Renders minimal nav when logged out', () => { + const wrapper = shallow(<Nav currentUser={currentUserLoggedOut} />); + expect(toJSON(wrapper)).toMatchSnapshot(); + }); + + it('renders full nav when logged in', () => { + const wrapper = shallow(<Nav currentUser={currentUser} />); + expect(toJSON(wrapper)).toMatchSnapshot(); + }); + + it('tries to refetch the current user when it mounts', () => { + const refetch = jest.fn(); + shallow(<Nav currentUser={{ ...currentUser, refetch }} />); + expect(refetch).toHaveBeenCalled(); + }); +}); diff --git a/frontend/__tests__/Pagination.test.js b/frontend/__tests__/Pagination.test.js new file mode 100644 index 0000000..e2ef7af --- /dev/null +++ b/frontend/__tests__/Pagination.test.js @@ -0,0 +1,46 @@ +import React from 'react'; +import { shallow, mount } from 'enzyme'; +import toJSON from 'enzyme-to-json'; +import { Pagination } from '../components/Pagination'; + +const fakeQuery = { + itemsConnection: { aggregate: { count: 18 } }, +}; + +describe('<Pagination/>', () => { + it('displays loading message', () => { + const wrapper = shallow(<Pagination loading page={1} itemsQuery={fakeQuery} />); + expect(toJSON(wrapper)).toMatchSnapshot(); + }); + + it('renders pagination for 18 items', () => { + const wrapper = shallow(<Pagination loading={false} page={1} itemsQuery={fakeQuery} />); + expect(toJSON(wrapper)).toMatchSnapshot(); + expect(wrapper.find('.totalPages').text()).toEqual('2'); + }); + + it('renders pagination for 28 items', () => { + const fakeQuery2 = { + itemsConnection: { aggregate: { count: 28 } }, + }; + const wrapper = shallow(<Pagination loading={false} page={1} itemsQuery={fakeQuery2} />); + expect(wrapper.find('.totalPages').text()).toEqual('4'); + }); + + it('disables and enables next/prev buttons', () => { + const fakeQuery3 = { + itemsConnection: { aggregate: { count: 100 } }, + }; + const wrapper = shallow(<Pagination loading={false} page={1} itemsQuery={fakeQuery} />); + + expect(wrapper.find('a.prev').props()['aria-disabled']).toEqual(true); + expect(wrapper.find('a.next').props()['aria-disabled']).toEqual(false); + wrapper.setProps({ page: 2 }); + expect(wrapper.find('a.prev').props()['aria-disabled']).toEqual(false); + expect(wrapper.find('a.next').props()['aria-disabled']).toEqual(true); + // when in the middle, both should work + wrapper.setProps({ itemsQuery: fakeQuery3, page: 3 }); + expect(wrapper.find('a.prev').props()['aria-disabled']).toEqual(false); + expect(wrapper.find('a.next').props()['aria-disabled']).toEqual(false); + }); +}); diff --git a/frontend/__tests__/__snapshots__/CartCount.test.js.snap b/frontend/__tests__/__snapshots__/CartCount.test.js.snap new file mode 100644 index 0000000..ddb6710 --- /dev/null +++ b/frontend/__tests__/__snapshots__/CartCount.test.js.snap @@ -0,0 +1,201 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`<CartCount></CartCount> matches snapshot 1`] = ` +<styled.span> + <TransitionGroup + childFactory={[Function]} + component="div" + > + <CSSTransition + className="count" + classNames="count" + key="10" + timeout={ + Object { + "enter": 2000, + "exit": 2000, + } + } + > + <styled.div> + 10 + </styled.div> + </CSSTransition> + </TransitionGroup> +</styled.span> +`; + +exports[`<CartCount></CartCount> updates via props 1`] = ` +<CartCount + count="50" +> + <styled.span> + <span + className="sc-bwzfXH fWZfOZ" + > + <TransitionGroup + childFactory={[Function]} + component="div" + > + <div> + <CSSTransition + className="count" + classNames="count" + in={true} + key=".$50" + onExited={[Function]} + timeout={ + Object { + "enter": 2000, + "exit": 2000, + } + } + > + <Transition + appear={false} + className="count" + enter={true} + exit={true} + in={true} + mountOnEnter={false} + onEnter={[Function]} + onEntered={[Function]} + onEntering={[Function]} + onExit={[Function]} + onExited={[Function]} + onExiting={[Function]} + timeout={ + Object { + "enter": 2000, + "exit": 2000, + } + } + unmountOnExit={false} + > + <styled.div + className="count" + > + <div + className="count sc-bdVaJa cYFOmX" + > + 50 + </div> + </styled.div> + </Transition> + </CSSTransition> + </div> + </TransitionGroup> + </span> + </styled.span> +</CartCount> +`; + +exports[`<CartCount></CartCount> updates via props 2`] = ` +<CartCount + count={10} +> + <styled.span> + <span + className="sc-bwzfXH fWZfOZ" + > + <TransitionGroup + childFactory={[Function]} + component="div" + > + <div> + <CSSTransition + className="count" + classNames="count" + in={true} + key=".$10" + onExited={[Function]} + timeout={ + Object { + "enter": 2000, + "exit": 2000, + } + } + > + <Transition + appear={false} + className="count" + enter={true} + exit={true} + in={true} + mountOnEnter={false} + onEnter={[Function]} + onEntered={[Function]} + onEntering={[Function]} + onExit={[Function]} + onExited={[Function]} + onExiting={[Function]} + timeout={ + Object { + "enter": 2000, + "exit": 2000, + } + } + unmountOnExit={false} + > + <styled.div + className="count" + > + <div + className="count sc-bdVaJa cYFOmX" + > + 10 + </div> + </styled.div> + </Transition> + </CSSTransition> + <CSSTransition + className="count" + classNames="count" + in={false} + key=".$50" + onExited={[Function]} + timeout={ + Object { + "enter": 2000, + "exit": 2000, + } + } + > + <Transition + appear={false} + className="count" + enter={true} + exit={true} + in={false} + mountOnEnter={false} + onEnter={[Function]} + onEntered={[Function]} + onEntering={[Function]} + onExit={[Function]} + onExited={[Function]} + onExiting={[Function]} + timeout={ + Object { + "enter": 2000, + "exit": 2000, + } + } + unmountOnExit={false} + > + <styled.div + className="count" + > + <div + className="count sc-bdVaJa cYFOmX" + > + 50 + </div> + </styled.div> + </Transition> + </CSSTransition> + </div> + </TransitionGroup> + </span> + </styled.span> +</CartCount> +`; diff --git a/frontend/__tests__/__snapshots__/CreateItem.test.js.snap b/frontend/__tests__/__snapshots__/CreateItem.test.js.snap new file mode 100644 index 0000000..66b7965 --- /dev/null +++ b/frontend/__tests__/__snapshots__/CreateItem.test.js.snap @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`<Createitem/> renders the form out 1`] = ` +<div> + <Form + onSubmit={[Function]} + > + <DisplayError + error={ + Object { + "message": null, + } + } + onButtonClick={[Function]} + /> + <p> + Image + <input + accept=".png, .jpg, .jpeg" + onChange={[Function]} + type="file" + /> + </p> + <p> + Title + <input + id="title" + name="title" + onChange={[Function]} + placeholder="Title" + type="text" + /> + </p> + <label> + Price + <input + id="price" + min="0" + name="price" + onChange={[Function]} + type="number" + /> + </label> + <textarea + id="description" + name="description" + onChange={[Function]} + placeholder="The desc for this item" + /> + <button + disabled={false} + type="submit" + > + Submit + </button> + </Form> +</div> +`; diff --git a/frontend/__tests__/__snapshots__/Item.test.js.snap b/frontend/__tests__/__snapshots__/Item.test.js.snap new file mode 100644 index 0000000..f088121 --- /dev/null +++ b/frontend/__tests__/__snapshots__/Item.test.js.snap @@ -0,0 +1,60 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`<Item/> Renders an item 1`] = ` +<styled.div + key="ABC123" +> + <img + alt="A Cool Item" + src="dog.jpg" + /> + <styled.h3> + <Link + href={ + Object { + "pathname": "/item", + "query": Object { + "id": "ABC123", + }, + } + } + > + <a> + A Cool Item + </a> + </Link> + </styled.h3> + <styled.span> + $50 + </styled.span> + <p> + This item is really cool! + </p> + <div + className="buttonList" + > + <Link + href={ + Object { + "pathname": "/admin/update", + "query": Object { + "id": "ABC123", + }, + } + } + > + <a> + Edit ✏️ + </a> + </Link> + <Apollo(Apollo(AddToCart)) + id="ABC123" + /> + <button + onClick={[Function]} + > + × Delete item + </button> + </div> +</styled.div> +`; diff --git a/frontend/__tests__/__snapshots__/Nav.test.js.snap b/frontend/__tests__/__snapshots__/Nav.test.js.snap new file mode 100644 index 0000000..d8520ac --- /dev/null +++ b/frontend/__tests__/__snapshots__/Nav.test.js.snap @@ -0,0 +1,69 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`<Nav></Nav> Renders minimal nav when logged out 1`] = ` +<styled.ul> + <Link + href="/items" + prefetch={true} + > + <a> + Shop + </a> + </Link> + <Link + href="/add" + prefetch={true} + > + <a> + Sell + </a> + </Link> + <Link + href="/signup" + prefetch={true} + > + <a> + Sign In + </a> + </Link> +</styled.ul> +`; + +exports[`<Nav></Nav> renders full nav when logged in 1`] = ` +<styled.ul> + <Link + href="/items" + prefetch={true} + > + <a> + Shop + </a> + </Link> + <Link + href="/add" + prefetch={true} + > + <a> + Sell + </a> + </Link> + <React.Fragment> + <Link + href="/orders" + > + <a> + Orders + </a> + </Link> + <Link + href="/me" + > + <a> + My Account + </a> + </Link> + <Apollo(Signout) /> + <[object Object] /> + </React.Fragment> +</styled.ul> +`; diff --git a/frontend/__tests__/__snapshots__/Pagination.test.js.snap b/frontend/__tests__/__snapshots__/Pagination.test.js.snap new file mode 100644 index 0000000..f2abcdf --- /dev/null +++ b/frontend/__tests__/__snapshots__/Pagination.test.js.snap @@ -0,0 +1,67 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`<Pagination/> displays loading message 1`] = ` +<p> + Loading... +</p> +`; + +exports[`<Pagination/> renders pagination for 18 items 1`] = ` +<styled.div> + <Link + href={ + Object { + "pathname": "items", + "query": Object { + "page": 0, + }, + } + } + prefetch={true} + > + <a + aria-disabled={true} + className="prev" + > + ←Prev + </a> + </Link> + <p> + Page + <strong> + 1 + + </strong> + of + <strong + className="totalPages" + > + 2 + </strong> + </p> + <p> + <strong> + 18 + </strong> + Items Total + </p> + <Link + href={ + Object { + "pathname": "items", + "query": Object { + "page": 2, + }, + } + } + prefetch={true} + > + <a + aria-disabled={false} + className="next" + > + Next → + </a> + </Link> +</styled.div> +`; diff --git a/frontend/__tests__/formatMoney.test.js b/frontend/__tests__/formatMoney.test.js new file mode 100644 index 0000000..c5c79b6 --- /dev/null +++ b/frontend/__tests__/formatMoney.test.js @@ -0,0 +1,21 @@ +import formatMoney from '../lib/formatMoney'; + +describe('formatMoney', () => { + it('works with fractional dollars', () => { + expect(formatMoney(1)).toEqual('$0.01'); + expect(formatMoney(10)).toEqual('$0.10'); + }); + + it('leaves cents off for whole dollars', () => { + expect(formatMoney(5000)).toEqual('$50'); + expect(formatMoney(100)).toEqual('$1'); + expect(formatMoney(50000000)).toEqual('$500,000'); + }); + + it('works with whole and fractional dollars', () => { + expect(formatMoney(5012)).toEqual('$50.12'); + expect(formatMoney(101)).toEqual('$1.01'); + expect(formatMoney(110)).toEqual('$1.10'); + expect(formatMoney(54345345)).toEqual('$543,453.45'); + }); +}); |
