diff options
| author | Wes Bos <wesbos@gmail.com> | 2018-03-14 21:00:08 -0400 |
|---|---|---|
| committer | Wes Bos <wesbos@gmail.com> | 2018-03-14 21:00:08 -0400 |
| commit | bd45d4c7aac6d1c6b054185058a96b2e01669828 (patch) | |
| tree | aeee19f26cc846496213822b6b28c9aa223bc6d1 | |
| parent | 7c760dd4d1e27180222d3d524949216e5b65194a (diff) | |
tests
| -rw-r--r-- | frontend/__tests__/AddToCart.test.js | 24 | ||||
| -rw-r--r-- | frontend/__tests__/Cart.test.js | 30 | ||||
| -rw-r--r-- | frontend/__tests__/TakeMyMoney.test.js | 55 | ||||
| -rw-r--r-- | frontend/__tests__/__snapshots__/AddToCart.test.js.snap | 9 | ||||
| -rw-r--r-- | frontend/__tests__/__snapshots__/TakeMyMoney.test.js.snap | 18 | ||||
| -rw-r--r-- | frontend/components/AddToCart.js | 9 | ||||
| -rw-r--r-- | frontend/components/Cart.js | 82 | ||||
| -rw-r--r-- | frontend/components/CartItem.js | 7 | ||||
| -rw-r--r-- | frontend/components/TakeMyMoney.js | 17 | ||||
| -rw-r--r-- | frontend/enhancers/enhancers.js | 4 | ||||
| -rw-r--r-- | frontend/lib/formatMoney.js | 2 |
11 files changed, 203 insertions, 54 deletions
diff --git a/frontend/__tests__/AddToCart.test.js b/frontend/__tests__/AddToCart.test.js new file mode 100644 index 0000000..2285b3b --- /dev/null +++ b/frontend/__tests__/AddToCart.test.js @@ -0,0 +1,24 @@ +import React from 'react'; +import { shallow, mount } from 'enzyme'; +import toJSON from 'enzyme-to-json'; +import { AddToCart } from '../components/AddToCart'; + +const currentUser = { + me: {}, + refetch() {}, +}; + +describe('<AddtoCart/>', () => { + it('renders and matches snapshot', () => { + const wrapper = shallow(<AddToCart id="abc123" addToCart={() => {}} currentUser={currentUser} />); + expect(toJSON(wrapper)).toMatchSnapshot(); + }); + + it('adds an item to the cart', () => { + const addToCart = jest.fn(() => Promise.resolve()); + const wrapper = shallow(<AddToCart id="abc123" addToCart={addToCart} currentUser={currentUser} />); + wrapper.simulate('click'); + expect(addToCart).toHaveBeenCalled(); + expect(addToCart).toHaveBeenCalledWith({ variables: { id: 'abc123' } }); + }); +}); diff --git a/frontend/__tests__/Cart.test.js b/frontend/__tests__/Cart.test.js new file mode 100644 index 0000000..0936e97 --- /dev/null +++ b/frontend/__tests__/Cart.test.js @@ -0,0 +1,30 @@ +import React from 'react'; +import { shallow, mount } from 'enzyme'; +import toJSON from 'enzyme-to-json'; +import { Cart } from '../components/Cart'; + +const cartItem = { + item: { price: 5000 }, + quantity: 10, +}; + +const currentUser = { + me: { + cart: [cartItem, cartItem, cartItem], + }, + refetch() {}, +}; + +describe('<Cart/>', () => { + it('renders', () => { + const wrapper = shallow(<Cart currentUser={currentUser} />); + }); + + xit('opens', () => { + const wrapper = shallow(<Cart currentUser={currentUser} />); + expect('wes').toEqual('figure out how to call test context'); + }); + // it('renders', () => { + // shallow(<Cart currentUser={currentUserLoggedOut} />); + // }); +}); diff --git a/frontend/__tests__/TakeMyMoney.test.js b/frontend/__tests__/TakeMyMoney.test.js new file mode 100644 index 0000000..2b33ca6 --- /dev/null +++ b/frontend/__tests__/TakeMyMoney.test.js @@ -0,0 +1,55 @@ +import React from 'react'; +import { shallow, mount } from 'enzyme'; +import toJSON from 'enzyme-to-json'; +import NProgress from 'nprogress'; +import { TakeMyMoney } from '../components/TakeMyMoney'; +import Router from 'next/router'; + +const wait = amount => new Promise(resolve => setTimeout(resolve, amount)); + +Router.router = { push() {} }; + +const cartItem = { + item: { price: 5000 }, + quantity: 10, +}; + +const currentUser = { + me: { + cart: [cartItem, cartItem, cartItem], + }, + refetch() {}, +}; + +describe('<TakeMyMoney />', () => { + it('renders', () => { + const wrapper = shallow(<TakeMyMoney createOrder={() => {}} currentUser={currentUser} />); + expect(toJSON(wrapper)).toMatchSnapshot(); + }); + + it('creates an order onToken', () => { + const createOrderSpy = jest.fn(() => Promise.resolve({ data: { createOrder: { id: 'xyz789' } } })); + const wrapper = shallow(<TakeMyMoney createOrder={createOrderSpy} currentUser={currentUser} />); + // manually run onToken + wrapper.instance().onToken({ id: 'abc123' }); + expect(createOrderSpy).toBeCalled(); + expect(createOrderSpy).toBeCalledWith({ variables: { token: 'abc123' } }); + }); + + it('turns the progress bar on', () => { + const createOrderSpy = jest.fn(() => Promise.resolve({ data: { createOrder: { id: 'xyz789' } } })); + NProgress.start = jest.fn(); + const wrapper = shallow(<TakeMyMoney createOrder={createOrderSpy} currentUser={currentUser} />); + wrapper.instance().onToken({ id: 'abc123' }); + expect(NProgress.start).toHaveBeenCalled(); + }); + + it('routes to the order page', async () => { + Router.router.push = jest.fn(); + const createOrderSpy = jest.fn(() => Promise.resolve({ data: { createOrder: { id: 'xyz789' } } })); + const wrapper = shallow(<TakeMyMoney createOrder={createOrderSpy} currentUser={currentUser} />); + wrapper.instance().onToken({ id: 'abc123' }); + await wait(0); + expect(Router.router.push).toHaveBeenCalledWith({ pathname: '/order/xyz789', query: { id: 'xyz789' } }); + }); +}); diff --git a/frontend/__tests__/__snapshots__/AddToCart.test.js.snap b/frontend/__tests__/__snapshots__/AddToCart.test.js.snap new file mode 100644 index 0000000..999161c --- /dev/null +++ b/frontend/__tests__/__snapshots__/AddToCart.test.js.snap @@ -0,0 +1,9 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`<AddtoCart/> renders and matches snapshot 1`] = ` +<button + onClick={[Function]} +> + 🛒 Add To Cart +</button> +`; diff --git a/frontend/__tests__/__snapshots__/TakeMyMoney.test.js.snap b/frontend/__tests__/__snapshots__/TakeMyMoney.test.js.snap new file mode 100644 index 0000000..8c77e01 --- /dev/null +++ b/frontend/__tests__/__snapshots__/TakeMyMoney.test.js.snap @@ -0,0 +1,18 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`<TakeMyMoney /> renders 1`] = ` +<ReactStripeCheckout + ComponentClass="span" + amount={150000} + className="StripeCheckout" + currency="USD" + description="Order of 30 Items From Sick Fits" + label="Pay With Card" + locale="auto" + name="Sick Fits Haul" + reconfigureOnUpdate={false} + stripeKey="pk_lclTtThFp8CnO3QtEZSd8HA9mFUps" + token={[Function]} + triggerEvent="onClick" +/> +`; diff --git a/frontend/components/AddToCart.js b/frontend/components/AddToCart.js index 9c52f83..22cfe02 100644 --- a/frontend/components/AddToCart.js +++ b/frontend/components/AddToCart.js @@ -14,13 +14,11 @@ class AddToCart extends Component { } handleAddToCart = async () => { - console.log(`Gonna add this item to the cart! ${this.props.id}`); const res = await this.props.addToCart({ variables: { id: this.props.id, }, }); - // this.props.currentUser.refetch(); }; render() { @@ -28,4 +26,11 @@ class AddToCart extends Component { } } +AddToCart.propTypes = { + currentUser: PropTypes.object.isRequired, + addToCart: PropTypes.func.isRequired, + id: PropTypes.string.isRequired, +}; + export default compose(userEnhancer, addToCartEnhancer)(AddToCart); +export { AddToCart }; diff --git a/frontend/components/Cart.js b/frontend/components/Cart.js index f270b80..8752c54 100644 --- a/frontend/components/Cart.js +++ b/frontend/components/Cart.js @@ -1,9 +1,8 @@ -import { Component } from 'react'; -import { graphql, compose } from 'react-apollo'; +import React from 'react'; +import { compose } from 'react-apollo'; import styled from 'styled-components'; -import Title from './styles/Title'; -import { updateUIEnhancer, userEnhancer, uiEnhancer } from '../enhancers/enhancers'; -import RemoveFromCart from './RemoveFromCart'; +import PropTypes from 'prop-types'; +import { userEnhancer } from '../enhancers/enhancers'; import TakeMyMoney from './TakeMyMoney'; import formatMoney from '../lib/formatMoney'; import { UIContext } from './UIContext'; @@ -74,48 +73,43 @@ const CloseButton = styled.button` right: 0; `; -class Cart extends Component { - componentDidMount() { - // TODO listen for escape - } +const Cart = props => { + const { me } = props.currentUser; + if (!me) return null; + const itemCount = me.cart.length; + const totalPrice = me.cart.reduce((tally, cartItem) => tally + cartItem.quantity * cartItem.item.price, 0); - componentWillUnmount() { - // TODO unlisten for escape - } - render() { - const { me } = this.props.currentUser; - if (!me) return null; - const itemCount = me.cart.length; - const quantityCount = me.cart.reduce((tally, cartItem) => tally + cartItem.quantity, 0); - const totalPrice = me.cart.reduce((tally, cartItem) => tally + cartItem.quantity * cartItem.item.price, 0); + return ( + <UIContext> + {context => ( + <CartStyles open={context.state.isCartOpen}> + <header> + <CloseButton title="close" onClick={context.toggle}> + × + </CloseButton> - return ( - <UIContext> - {context => ( - <CartStyles open={context.state.isCartOpen}> - <header> - <CloseButton title="close" onClick={context.toggle}> - × - </CloseButton> + <Supreme>{me.name}'s Cart.</Supreme> + <p> + You have {itemCount} item{itemCount === 1 ? '' : 's'} in your cart. + </p> + </header> - <Supreme>{me.name}'s Cart.</Supreme> - <p> - You have {itemCount} item{itemCount === 1 ? '' : 's'} in your cart. - </p> - </header> + <CartUl>{me.cart.map(cartItem => <CartItem key={cartItem.id} cartItem={cartItem} />)}</CartUl> + <footer> + <p>{formatMoney(totalPrice)}</p> + <TakeMyMoney> + <button>Checkout</button> + </TakeMyMoney> + </footer> + </CartStyles> + )} + </UIContext> + ); +}; - <CartUl>{me.cart.map(cartItem => <CartItem key={cartItem.id} cartItem={cartItem} />)}</CartUl> - <footer> - <p>{formatMoney(totalPrice)}</p> - <TakeMyMoney> - <button>Checkout</button> - </TakeMyMoney> - </footer> - </CartStyles> - )} - </UIContext> - ); - } -} +Cart.propTypes = { + currentUser: PropTypes.object.isRequired, +}; export default compose(userEnhancer)(Cart); +export { Cart }; diff --git a/frontend/components/CartItem.js b/frontend/components/CartItem.js index 83c948e..895b688 100644 --- a/frontend/components/CartItem.js +++ b/frontend/components/CartItem.js @@ -1,6 +1,7 @@ +import styled from 'styled-components'; +import PropTypes from 'prop-types'; import formatMoney from '../lib/formatMoney'; import RemoveFromCart from './RemoveFromCart'; -import styled from 'styled-components'; const CartItemStyles = styled.li` padding: 1rem 0; @@ -36,4 +37,8 @@ const CartItem = ({ cartItem }) => ( </CartItemStyles> ); +CartItem.propTypes = { + cartItem: PropTypes.object.isRequired, +}; + export default CartItem; diff --git a/frontend/components/TakeMyMoney.js b/frontend/components/TakeMyMoney.js index 333f31b..011451a 100644 --- a/frontend/components/TakeMyMoney.js +++ b/frontend/components/TakeMyMoney.js @@ -1,10 +1,11 @@ import { Component } from 'react'; import StripeCheckout from 'react-stripe-checkout'; -import { graphql, compose } from 'react-apollo'; -import { CREATE_ORDER_MUTATION, CURRENT_USER_QUERY } from '../queries'; -import formatMoney from '../lib/formatMoney'; +import { compose } from 'react-apollo'; import Router from 'next/router'; import NProgress from 'nprogress'; +import PropTypes from 'prop-types'; +// import { CREATE_ORDER_MUTATION, CURRENT_USER_QUERY } from '../queries'; +import { userEnhancer, createOrderEnhancer } from '../enhancers/enhancers'; class TakeMyMoney extends Component { onToken = async res => { @@ -23,7 +24,7 @@ class TakeMyMoney extends Component { }; render() { - const { me } = this.props.currentUserQuery; + const { me } = this.props.currentUser; if (!me || !me.cart.length) return null; const total = me.cart.reduce((tally, cartItem) => tally + cartItem.item.price * cartItem.quantity, 0); const totalItems = me.cart.reduce((tally, cartItem) => tally + cartItem.quantity, 0); @@ -44,6 +45,10 @@ class TakeMyMoney extends Component { } } -const userEnhancer = graphql(CURRENT_USER_QUERY, { name: 'currentUserQuery' }); -const createOrderEnhancer = graphql(CREATE_ORDER_MUTATION, { name: 'createOrder' }); +TakeMyMoney.propTypes = { + currentUser: PropTypes.object.isRequired, + createOrder: PropTypes.func.isRequired, +}; + export default compose(userEnhancer, createOrderEnhancer)(TakeMyMoney); +export { TakeMyMoney }; diff --git a/frontend/enhancers/enhancers.js b/frontend/enhancers/enhancers.js index 2651b6c..3a483e2 100644 --- a/frontend/enhancers/enhancers.js +++ b/frontend/enhancers/enhancers.js @@ -10,6 +10,7 @@ import { GET_UI_STATE, TOGGLE_CART, UPDATE_USER_MUTATION, + CREATE_ORDER_MUTATION, } from '../queries/index'; import { perPage } from '../config'; @@ -105,3 +106,6 @@ export const updateUIEnhancer = graphql(UPDATE_UI, { }), }), }); + +// export const const userEnhancer = graphql(CURRENT_USER_QUERY, { name: 'currentUser' }); +export const createOrderEnhancer = graphql(CREATE_ORDER_MUTATION, { name: 'createOrder' }); diff --git a/frontend/lib/formatMoney.js b/frontend/lib/formatMoney.js index 301f01f..c001aee 100644 --- a/frontend/lib/formatMoney.js +++ b/frontend/lib/formatMoney.js @@ -1,4 +1,4 @@ -export default function (amount) { +export default function(amount) { const options = { style: 'currency', currency: 'USD', |
