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

[PWA-240] [feature]: Cart Price Summary #2092

Merged
merged 21 commits into from
Jan 15, 2020
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { useCallback, useEffect } from 'react';
import { useQuery } from '@apollo/react-hooks';
import { useCartContext } from '@magento/peregrine/lib/context/cart';

/**
* Flattens query data into a simple object. We create this here rather than
* having each line summary line component destructure its own data because
* only the parent "price summary" component knows the data structure.
*
* @param {Object} data query data
*/
const flattenData = data => {
if (!data) return {};
return {
subtotal: data.cart.prices.subtotal_excluding_tax,
total: data.cart.prices.grand_total,
discounts: data.cart.prices.discounts,
giftCards: data.cart.applied_gift_cards,
taxes: data.cart.prices.applied_taxes,
shipping: data.cart.shipping_addresses
};
};

export const usePriceSummary = props => {
const [{ cartId }] = useCartContext();
const { error, loading, data } = useQuery(props.query, {
variables: {
cartId
},
fetchPolicy: 'no-cache'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should verify that actions that modify the price summary values such as shipping method or adding a shipping address elsewhere also update the price summary even if no-cache is used here.

});

const handleProceedToCheckout = useCallback(() => {
// TODO: Navigate to checkout view
}, []);

useEffect(() => {
if (error) {
console.error('GraphQL Error:', error);
}
}, [error]);

return {
handleProceedToCheckout,
hasError: !!error,
hasItems: data && !!data.cart.items.length,
isLoading: !!loading,
flatData: flattenData(data)
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders accumulated discount value 1`] = `
Array [
<span
className="lineItemLabel"
>
Discounts applied
</span>,
<span
className="price"
>
(-
<span>
$2
</span>
)
</span>,
]
`;

exports[`renders discount summary line item correctly 1`] = `
Array [
<span
className="lineItemLabel"
>
Discounts applied
</span>,
<span
className="price"
>
(-
<span>
$10
</span>
)
</span>,
]
`;

exports[`renders nothing if discount data is empty 1`] = `null`;

exports[`renders nothing if discount value is "0" 1`] = `null`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders accumulated gift card value 1`] = `null`;

exports[`renders gift card summary line item correctly 1`] = `null`;

exports[`renders nothing if gift card data is empty 1`] = `null`;

exports[`renders nothing if gift card value is "0" 1`] = `null`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders PriceSummary correctly 1`] = `
<div
className="root"
>
<div
className="lineItems"
>
<span>
Subtotal
</span>
<span
className="price"
>
<span>
$11
</span>
</span>
<span>
Discounts applied
</span>
<span
className="price"
>
(-
<span>
$1
</span>
)
</span>
<span>
Estimated Tax
</span>
<span
className="price"
>
<span>
$0
</span>
</span>
<span>
Estimated Shipping
</span>
<span
className="price"
>
<span>
FREE
</span>
</span>
<span
className="totalLabel"
>
Estimated Total
</span>
<span
className="totalPrice"
>
<span>
$10
</span>
</span>
</div>
<div
className="checkoutButton_container"
>
<button
onClick={[Function]}
type="button"
>
<span>
PROCEED TO CHECKOUT
</span>
</button>
</div>
</div>
`;

exports[`renders an error state if query fails 1`] = `
<div
className="root"
>
An error occurred. Please refresh the page.
</div>
`;

exports[`renders nothing if query is loading 1`] = `null`;

exports[`renders nothing if query returns no items 1`] = `null`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders "FREE"" if shipping value is "0" 1`] = `
Array [
<span
className="lineItemLabel"
>
Estimated Shipping
</span>,
<span
className="price"
>
<span>
FREE
</span>
</span>,
]
`;

exports[`renders nothing if shipping data is empty 1`] = `null`;

exports[`renders nothing if there is no selected shipping method 1`] = `null`;

exports[`renders shipping summary line item correctly 1`] = `
Array [
<span
className="lineItemLabel"
>
Estimated Shipping
</span>,
<span
className="price"
>
<span>
$10
</span>
</span>,
]
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`renders accumulated tax value 1`] = `
Array [
<span
className="lineItemLabel"
>
Estimated Tax
</span>,
<span
className="price"
>
<span>
$2
</span>
</span>,
]
`;

exports[`renders nothing if tax data is empty 1`] = `null`;

exports[`renders tax summary line item correctly 1`] = `
Array [
<span
className="lineItemLabel"
>
Estimated Tax
</span>,
<span
className="price"
>
<span>
$10
</span>
</span>,
]
`;

exports[`renders tax summary line item correctly if tax value is "0" 1`] = `
Array [
<span
className="lineItemLabel"
>
Estimated Tax
</span>,
<span
className="price"
>
<span>
$0
</span>
</span>,
]
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import React from 'react';
import { createTestInstance } from '@magento/peregrine';

import DiscountSummary from '../discountSummary';

jest.mock('../../../../classify');

jest.mock('@magento/peregrine', () => {
const Price = props => <span>{`$${props.value}`}</span>;

return {
...jest.requireActual('@magento/peregrine'),
Price
};
});

const defaultProps = {
classes: {
lineItemLabel: 'lineItemLabel',
price: 'price'
},
data: [
{
amount: {
value: 10,
currency: 'USD'
}
}
]
};

test('renders discount summary line item correctly', () => {
const tree = createTestInstance(<DiscountSummary {...defaultProps} />);

expect(tree.toJSON()).toMatchSnapshot();
});

test('renders accumulated discount value', () => {
const props = {
...defaultProps,
data: [
{
amount: {
value: 0,
currency: 'USD'
}
},
{
amount: {
value: 1,
currency: 'USD'
}
},
{
amount: {
value: 1,
currency: 'USD'
}
}
]
};

const tree = createTestInstance(<DiscountSummary {...props} />);

expect(tree.toJSON()).toMatchSnapshot();
});

test('renders nothing if discount data is empty', () => {
const props = {
...defaultProps,
data: []
};
const tree = createTestInstance(<DiscountSummary {...props} />);

expect(tree.toJSON()).toMatchSnapshot();
});

test('renders nothing if discount value is "0"', () => {
const props = {
...defaultProps,
data: [
{
amount: {
value: 0,
currency: 'USD'
}
}
]
};
const tree = createTestInstance(<DiscountSummary {...props} />);

expect(tree.toJSON()).toMatchSnapshot();
});
Loading