Skip to content
This repository has been archived by the owner on Nov 4, 2024. It is now read-only.

Commit

Permalink
UI: Payment Page clean-up (#47)
Browse files Browse the repository at this point in the history
* fix: merge conflicts

* fix: saga tests to reflect complete basket state

* fix: delete comment

* test: update saga test with blank voucher
  • Loading branch information
julianajlk authored Jul 3, 2019
1 parent d8e0483 commit 9ed5373
Show file tree
Hide file tree
Showing 14 changed files with 121 additions and 50 deletions.
3 changes: 2 additions & 1 deletion src/payment/BasketSummary.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ function SummaryTable({ calculatedDiscount, totalExclDiscount }) {
</td>
</tr>

{calculatedDiscount !== undefined ? (
{calculatedDiscount !== undefined && calculatedDiscount !== null &&
calculatedDiscount > 0 ? (
<tr>
<th className="font-weight-normal" scope="row">
<FormattedMessage
Expand Down
1 change: 1 addition & 0 deletions src/payment/PaymentForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ export class PaymentFormComponent extends React.Component {
handleSubmit,
submitting,
} = this.props;

return (
<form onSubmit={handleSubmit(this.onSubmit)} noValidate>
<CardHolderInformation />
Expand Down
2 changes: 1 addition & 1 deletion src/payment/PaymentPage.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ describe('<PaymentPage />', () => {
});

const product = {
imageURL: 'https://prod-discovery.edx-cdn.org/media/course/image/21be6203-b140-422c-9233-a1dc278d7266-941abf27df4d.small.jpg',
imageUrl: 'https://prod-discovery.edx-cdn.org/media/course/image/21be6203-b140-422c-9233-a1dc278d7266-941abf27df4d.small.jpg',
title: 'Introduction to Happiness',
seatType: 'Verified',
};
Expand Down
6 changes: 3 additions & 3 deletions src/payment/ProductLineItem.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ class ProductLineItem extends React.PureComponent {

render() {
const {
imageURL,
imageUrl,
title,
seatType,
} = this.props;
return (
<div className="row align-items-center">
<div className="col-5">
<img className="img-thumbnail" src={imageURL} alt={title} />
<img className="img-thumbnail" src={imageUrl} alt={title} />
</div>
<div className="col-7">
<h6 className="m-0">{title}</h6>
Expand All @@ -47,7 +47,7 @@ class ProductLineItem extends React.PureComponent {
}

ProductLineItem.propTypes = {
imageURL: PropTypes.string.isRequired,
imageUrl: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
seatType: PropTypes.oneOf(['professional', 'no-id-professional', 'Verified', 'honor', 'audit']),
};
Expand Down
4 changes: 2 additions & 2 deletions src/payment/ProductLineItems.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function ProductLineItems({ products }) {
<h2 className="section-heading">
<FormattedMessage
id="payment.productlineitem.purchase.cart.heading"
defaultMessage="In your cart"
defaultMessage="In Your Cart"
description="Heading of the cart in product details section"
/>
</h2>
Expand All @@ -31,7 +31,7 @@ function ProductLineItems({ products }) {

ProductLineItems.propTypes = {
products: PropTypes.arrayOf(PropTypes.shape({
imageURL: PropTypes.string,
imageUrl: PropTypes.string,
title: PropTypes.string,
seatType: PropTypes.oneOf(['professional', 'no-id-professional', 'Verified', 'honor', 'audit']),
})),
Expand Down
2 changes: 1 addition & 1 deletion src/payment/__mocks__/loadedBasket.mockStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ module.exports = {
totalExclDiscount: 161,
products: [
{
imageURL:
imageUrl:
'https://prod-discovery.edx-cdn.org/media/course/image/21be6203-b140-422c-9233-a1dc278d7266-941abf27df4d.small.jpg',
title: 'Introduction to Happiness',
seatType: 'Verified',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ module.exports = {
sdnCheck: true,
products: [
{
imageURL:
imageUrl:
'https://prod-discovery.edx-cdn.org/media/course/image/21be6203-b140-422c-9233-a1dc278d7266-941abf27df4d.small.jpg',
title: 'Introduction to Happiness',
seatType: 'Verified',
Expand Down
4 changes: 2 additions & 2 deletions src/payment/__snapshots__/PaymentPage.test.jsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ exports[`<PaymentPage /> Renders correctly in various states should render the b
className="section-heading"
>
<span>
In your cart
In Your Cart
</span>
</h2>
<p>
Expand Down Expand Up @@ -2124,7 +2124,7 @@ exports[`<PaymentPage /> Renders correctly in various states should successfully
className="section-heading"
>
<span>
In your cart
In Your Cart
</span>
</h2>
<p>
Expand Down
4 changes: 2 additions & 2 deletions src/payment/_style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
@extend .mb-5;
}
.section-heading {
@extend .h6;
@extend .h5;
}
label {
font-weight: normal;
Expand All @@ -35,7 +35,7 @@
display: inline-block;
padding: map-get($spacers, 2);
margin-right: map-get($spacers, 2);
border: solid $border-width $border-color;
border: solid $border-width $border-color;
border-radius: $border-radius;
cursor: pointer;
display: inline-flex;
Expand Down
15 changes: 10 additions & 5 deletions src/payment/coupon/data/sagas.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
addCouponFailure,
removeCouponFailure,
} from './actions';
import { fetchBasketSuccess } from '../../data/actions';
import { deleteCoupon, postCoupon } from './service';

import {
Expand All @@ -21,11 +22,15 @@ export function* handleAddCoupon(action) {
yield put(addCouponBegin());
try {
const result = yield call(postCoupon, action.payload.code);
const { id: voucherId, code, benefit } = result.voucher;
yield put(addCouponSuccess(voucherId, code, benefit));
yield put(addMessage('payment.coupon.added', null, {
code,
}, INFO));
yield put(fetchBasketSuccess(result));
if (result.voucher === undefined) {
yield put(addCouponSuccess(null, null, null));
} else {
yield put(addCouponSuccess(result.voucher.id, result.voucher.code, result.voucher.benefit));
yield put(addMessage('payment.coupon.added', null, {
code: result.voucher.code,
}, INFO));
}
} catch (e) {
yield put(addCouponFailure());
yield call(handleErrors, e);
Expand Down
83 changes: 77 additions & 6 deletions src/payment/coupon/data/sagas.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
removeCoupon,
removeCouponFailure,
} from './actions';
import { fetchBasketSuccess } from '../../data/actions';
import { transformResults } from '../../data/service';
import { PERCENTAGE_BENEFIT } from './constants';
import { addMessage, INFO, DANGER } from '../../../feedback';

Expand All @@ -34,6 +36,7 @@ describe('saga tests', () => {
const responses = {
successResponse: {
data: {
show_voucher_form: true,
voucher: {
id: 12345,
code: 'DEMO25',
Expand All @@ -42,6 +45,31 @@ describe('saga tests', () => {
value: 25,
},
},
total_excl_discount: 161,
order_total: 149,
calculated_discount: 12,
products: [
{
image_url: 'https://prod-discovery.edx-cdn.org/media/course/image/21be6203-b140-422c-9233-a1dc278d7266-941abf27df4d.small.jpg',
title: 'Introduction to Happiness',
seat_type: 'Verified',
},
],
},
},
blankVoucherResponse: {
data: {
show_voucher_form: true,
total_excl_discount: 161,
order_total: 161,
calculated_discount: 0,
products: [
{
image_url: 'https://prod-discovery.edx-cdn.org/media/course/image/21be6203-b140-422c-9233-a1dc278d7266-941abf27df4d.small.jpg',
title: 'Introduction to Happiness',
seat_type: 'Verified',
},
],
},
},
errorResponse: {
Expand Down Expand Up @@ -75,6 +103,7 @@ describe('saga tests', () => {

expect(dispatched).toEqual([
addCouponBegin(),
fetchBasketSuccess(transformResults(responses.successResponse.data)),
addCouponSuccess(12345, 'DEMO25', {
type: PERCENTAGE_BENEFIT,
value: 25,
Expand All @@ -88,7 +117,37 @@ describe('saga tests', () => {
INFO,
),
]);
expect(apiClientPost).toHaveBeenCalledWith(
'http://localhost/bff/payment/v0/vouchers/',
{ code: 'DEMO25' },
{ headers: { 'Content-Type': 'application/json' } },
);
});

it('should handle an empty vouchers', async () => {
const apiClientPost = jest.fn(() =>
new Promise((resolve) => {
resolve(responses.blankVoucherResponse);
}));

configureApiService(configuration, {
post: apiClientPost,
});

const dispatched = [];
await runSaga(
{
dispatch: action => dispatched.push(action),
},
handleAddCoupon,
addCoupon('DEMO25'),
).toPromise();

expect(dispatched).toEqual([
addCouponBegin(),
fetchBasketSuccess(transformResults(responses.blankVoucherResponse.data)),
addCouponSuccess(null, null, null),
]);
expect(apiClientPost).toHaveBeenCalledWith(
'http://localhost/bff/payment/v0/vouchers/',
{ code: 'DEMO25' },
Expand Down Expand Up @@ -172,9 +231,25 @@ describe('saga tests', () => {
const responses = {
successResponse: {
data: {
show_voucher_form: true,
voucher: {
id: 12345,
code: 'DEMO25',
benefit: {
type: PERCENTAGE_BENEFIT,
value: 25,
},
},
total_excl_discount: 161,
order_total: 149,
calculated_discount: 12,
total_excl_discount: 161,
products: [
{
image_url: 'https://prod-discovery.edx-cdn.org/media/course/image/21be6203-b140-422c-9233-a1dc278d7266-941abf27df4d.small.jpg',
title: 'Introduction to Happiness',
seat_type: 'Verified',
},
],
},
},
errorResponse: {
Expand Down Expand Up @@ -211,11 +286,7 @@ describe('saga tests', () => {

expect(dispatched).toEqual([
removeCouponBegin(),
removeCouponSuccess({
order_total: 149,
calculated_discount: 12,
total_excl_discount: 161,
}),
removeCouponSuccess(transformResults(responses.successResponse.data)),
addMessage(
'payment.coupon.removed',
null,
Expand Down
11 changes: 5 additions & 6 deletions src/payment/coupon/data/service.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import pick from 'lodash.pick';

import { handleRequestError, applyConfiguration } from '../../../common/serviceUtils';
import { transformResults } from '../../data/service';

let config = {
ECOMMERCE_BASE_URL: null,
Expand All @@ -15,7 +16,7 @@ export function configureApiService(newConfig, newApiClient) {
}

export async function postCoupon(code) {
const response = await apiClient
const { data } = await apiClient
.post(
`${config.ECOMMERCE_BASE_URL}/bff/payment/v0/vouchers/`,
{ code },
Expand All @@ -24,14 +25,12 @@ export async function postCoupon(code) {
},
)
.catch(handleRequestError);

return response.data;
return transformResults(data);
}

export async function deleteCoupon(voucherId) {
const response = await apiClient
const { data } = await apiClient
.delete(`${config.ECOMMERCE_BASE_URL}/bff/payment/v0/vouchers/${voucherId}`)
.catch(handleRequestError);

return response.data;
return transformResults(data);
}
10 changes: 1 addition & 9 deletions src/payment/data/__mocks__/getBasket.json
Original file line number Diff line number Diff line change
@@ -1,21 +1,13 @@
{
"show_voucher_form": true,
"payment_providers": [
{
"type": "cybersource"
},
{
"type": "paypal"
}
],
"order_total": 149,
"calculated_discount": 12,
"total_excl_discount": 161,
"sdn_check": true,
"products": [
{
"image_url": "https://prod-discovery.edx-cdn.org/media/course/image/21be6203-b140-422c-9233-a1dc278d7266-941abf27df4d.small.jpg",
"name": "Introduction to Happiness",
"title": "Introduction to Happiness",
"seat_type": "Verified"
}
],
Expand Down
24 changes: 13 additions & 11 deletions src/payment/data/service.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import pick from 'lodash.pick';
import { configureApiService as configureCouponApiService } from '../coupon';
import { applyConfiguration, handleRequestError } from '../../common/serviceUtils';


let config = {
ACCOUNTS_API_BASE_URL: null,
ECOMMERCE_BASE_URL: null,
Expand All @@ -21,27 +22,28 @@ export function configureApiService(newConfig, newApiClient) {
configureCouponApiService(config, apiClient);
}

export async function getBasket() {
const { data } = await apiClient
.get(`${config.ECOMMERCE_BASE_URL}/bff/payment/v0/payment/`)
.catch(handleRequestError);

export function transformResults(data) {
const transformedResults = {
basketId: data.basket_id,
showVoucherForm: data.show_voucher_form,
paymentProviders: data.payment_providers,
orderTotal: Number.parseInt(data.order_total, 10),
calculatedDiscount: Number.parseInt(data.calculated_discount, 10),
calculatedDiscount: data.calculated_discount !== null ?
Number.parseInt(data.calculated_discount, 10) : null,
totalExclDiscount: Number.parseInt(data.total_excl_discount, 10),
products: data.products.map(({ image_url: imageURL, title, seat_type: seatType }) => ({
imageURL, title, seatType,
products: data.products.map(({ image_url: imageUrl, title, seat_type: seatType }) => ({
imageUrl, title, seatType,
})),
voucher: data.voucher,
};

return transformedResults;
}

export async function getBasket() {
const { data } = await apiClient
.get(`${config.ECOMMERCE_BASE_URL}/bff/payment/v0/payment/`)
.catch(handleRequestError);
return transformResults(data);
}

export async function sdnCheck(firstName, lastName, city, country) {
const { data } = await apiClient.post(
`${config.ECOMMERCE_BASE_URL}/api/v2/sdn/search/`,
Expand Down

0 comments on commit 9ed5373

Please sign in to comment.