summaryrefslogtreecommitdiffstats
path: root/frontend/__tests__
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/__tests__')
-rw-r--r--frontend/__tests__/CartCount.test.js21
-rw-r--r--frontend/__tests__/CreateItem.test.js85
-rw-r--r--frontend/__tests__/Item.test.js31
-rw-r--r--frontend/__tests__/Nav.test.js35
-rw-r--r--frontend/__tests__/Pagination.test.js46
-rw-r--r--frontend/__tests__/__snapshots__/CartCount.test.js.snap201
-rw-r--r--frontend/__tests__/__snapshots__/CreateItem.test.js.snap58
-rw-r--r--frontend/__tests__/__snapshots__/Item.test.js.snap60
-rw-r--r--frontend/__tests__/__snapshots__/Nav.test.js.snap69
-rw-r--r--frontend/__tests__/__snapshots__/Pagination.test.js.snap67
-rw-r--r--frontend/__tests__/formatMoney.test.js21
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');
+ });
+});