account payments page and cypress tests
This commit is contained in:
parent
4dd95af2fa
commit
c2ffbff216
|
|
@ -0,0 +1,46 @@
|
|||
import makeFakeUser from '../../factories/user';
|
||||
|
||||
describe('Payments Page', () => {
|
||||
beforeEach(() => {
|
||||
// Place any setup code here, such as logging in or navigating to the payments page
|
||||
const currentUser = makeFakeUser();
|
||||
cy.stubAuthenticate({ ...currentUser });
|
||||
cy.intercept('GET', /\S+\/invoice_history\?limit=10&cursor=0/, { fixture: 'payments_page1' }).as('getPayments1');
|
||||
cy.intercept('GET', /\S+\/invoice_history\?limit=10&cursor=10/, { fixture: 'payments_page2' }).as('getPayments2');
|
||||
cy.intercept('GET', /\S+\/invoice_history\?limit=10&cursor=20/, { fixture: 'payments_page3' }).as('getPayments3');
|
||||
})
|
||||
|
||||
it('should list user\'s payments', () => {
|
||||
// Call the external API that fetches the payment records
|
||||
cy.visit('/account/payments')
|
||||
cy.wait('@getPayments1')
|
||||
cy.get('[data-testid="paymentsListTable"]').should('be.visible').find('tbody tr').first().within(() => {
|
||||
cy.contains('05/01/2022')
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
it.only('paginate through the payments', () => {
|
||||
// Call the external API that fetches the payment records
|
||||
cy.visit('/account/payments')
|
||||
cy.wait('@getPayments1')
|
||||
cy.get('[data-testid="paymentsListTable"]').should('be.visible').find('tbody tr').first().within(() => {
|
||||
cy.contains('12/01/2022')
|
||||
})
|
||||
|
||||
// Click the next page button
|
||||
cy.get('[data-testid="nextPageButton"]').click()
|
||||
cy.wait('@getPayments2')
|
||||
cy.get('[data-testid="paymentsListTable"]').should('be.visible').find('tbody tr').first().within(() => {
|
||||
cy.contains('02/01/2022')
|
||||
})
|
||||
|
||||
// Click the next page button
|
||||
cy.get('[data-testid="nextPageButton"]').click()
|
||||
cy.wait('@getPayments3')
|
||||
cy.get('[data-testid="paymentsListTable"]').should('be.visible').find('tbody tr').first().within(() => {
|
||||
cy.contains('03/01/2021')
|
||||
})
|
||||
});
|
||||
|
||||
})
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
{
|
||||
"entries": [
|
||||
{
|
||||
"id": "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6",
|
||||
"created_at": "2022-12-01T00:00:00Z",
|
||||
"total_in_cents": 999,
|
||||
"description": "JamKazam Gold Plan - Monthly",
|
||||
"status": "paid"
|
||||
},
|
||||
{
|
||||
"id": "q7r8s9t0-u1v2-w3x4-y5z6-a7b8c9d0e1f2",
|
||||
"created_at": "2022-11-01T00:00:00Z",
|
||||
"total_in_cents": 999,
|
||||
"description": "JamKazam Gold Plan - Monthly",
|
||||
"status": "paid"
|
||||
},
|
||||
{
|
||||
"id": "g3h4i5j6-k7l8-m9n0-o1p2-q3r4s5t6u7v8w9x0",
|
||||
"created_at": "2022-10-01T00:00:00Z",
|
||||
"total_in_cents": 999,
|
||||
"description": "JamKazam Gold Plan - Monthly",
|
||||
"status": "paid"
|
||||
},
|
||||
{
|
||||
"id": "y1z2a3b4-c5d6-e7f8-g9h0-i1j2k3l4m5n6o7",
|
||||
"created_at": "2022-09-01T00:00:00Z",
|
||||
"total_in_cents": 999,
|
||||
"description": "JamKazam Gold Plan - Monthly",
|
||||
"status": "paid"
|
||||
},
|
||||
{
|
||||
"id": "p8q9r0s1-t2u3-v4w5-x6y7-z8a9b0c1d2e3f4",
|
||||
"created_at": "2022-08-01T00:00:00Z",
|
||||
"total_in_cents": 999,
|
||||
"description": "JamKazam Gold Plan - Monthly",
|
||||
"status": "paid"
|
||||
},
|
||||
{
|
||||
"id": "g5h6i7j8-k9l0-m1n2-o3p4-q5r6s7t8u9v0w1x2",
|
||||
"created_at": "2022-07-01T00:00:00Z",
|
||||
"total_in_cents": 999,
|
||||
"description": "JamKazam Gold Plan - Monthly",
|
||||
"status": "paid"
|
||||
},
|
||||
{
|
||||
"id": "y3z4a5b6-c7d8-e9f0-g1h2-i3j4k5l6m7n8o9",
|
||||
"created_at": "2022-06-01T00:00:00Z",
|
||||
"total_in_cents": 999,
|
||||
"description": "JamKazam Gold Plan - Monthly",
|
||||
"status": "paid"
|
||||
},
|
||||
{
|
||||
"id": "p2q3r4s5-t6u7-v8w9-x0y1-z2a3b4c5d6e7f8",
|
||||
"created_at": "2022-05-01T00:00:00Z",
|
||||
"total_in_cents": 999,
|
||||
"description": "JamKazam Gold Plan - Monthly",
|
||||
"status": "paid"
|
||||
},
|
||||
{
|
||||
"id": "g9h0i1j2-k3l4-m5n6-o7p8-q9r0s1t2u3v4w5x6",
|
||||
"created_at": "2022-04-01T00:00:00Z",
|
||||
"total_in_cents": 999,
|
||||
"description": "JamKazam Gold Plan - Monthly",
|
||||
"status": "paid"
|
||||
},
|
||||
{
|
||||
"id": "y7z8a9b0-c1d2-e3f4-g5h6-i7j8k9l0m1n2o3p4",
|
||||
"created_at": "2022-03-01T00:00:00Z",
|
||||
"total_in_cents": 999,
|
||||
"description": "JamKazam Gold Plan - Monthly",
|
||||
"status": "paid"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
{
|
||||
"entries": [
|
||||
{
|
||||
"id": "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6",
|
||||
"created_at": "2022-02-01T00:00:00Z",
|
||||
"total_in_cents": 999,
|
||||
"description": "JamKazam Gold Plan - Monthly",
|
||||
"status": "paid"
|
||||
},
|
||||
{
|
||||
"id": "q7r8s9t0-u1v2-w3x4-y5z6-a7b8c9d0e1f2",
|
||||
"created_at": "2022-01-01T00:00:00Z",
|
||||
"total_in_cents": 999,
|
||||
"description": "JamKazam Gold Plan - Monthly",
|
||||
"status": "paid"
|
||||
},
|
||||
{
|
||||
"id": "g3h4i5j6-k7l8-m9n0-o1p2-q3r4s5t6u7v8w9x0",
|
||||
"created_at": "2021-12-01T00:00:00Z",
|
||||
"total_in_cents": 999,
|
||||
"description": "JamKazam Gold Plan - Monthly",
|
||||
"status": "paid"
|
||||
},
|
||||
{
|
||||
"id": "y1z2a3b4-c5d6-e7f8-g9h0-i1j2k3l4m5n6o7",
|
||||
"created_at": "2021-11-01T00:00:00Z",
|
||||
"total_in_cents": 999,
|
||||
"description": "JamKazam Gold Plan - Monthly",
|
||||
"status": "paid"
|
||||
},
|
||||
{
|
||||
"id": "p8q9r0s1-t2u3-v4w5-x6y7-z8a9b0c1d2e3f4",
|
||||
"created_at": "2021-10-01T00:00:00Z",
|
||||
"total_in_cents": 999,
|
||||
"description": "JamKazam Gold Plan - Monthly",
|
||||
"status": "paid"
|
||||
},
|
||||
{
|
||||
"id": "g5h6i7j8-k9l0-m1n2-o3p4-q5r6s7t8u9v0w1x2",
|
||||
"created_at": "2021-09-01T00:00:00Z",
|
||||
"total_in_cents": 999,
|
||||
"description": "JamKazam Gold Plan - Monthly",
|
||||
"status": "paid"
|
||||
},
|
||||
{
|
||||
"id": "y3z4a5b6-c7d8-e9f0-g1h2-i3j4k5l6m7n8o9",
|
||||
"created_at": "2021-08-01T00:00:00Z",
|
||||
"total_in_cents": 999,
|
||||
"description": "JamKazam Gold Plan - Monthly",
|
||||
"status": "paid"
|
||||
},
|
||||
{
|
||||
"id": "p2q3r4s5-t6u7-v8w9-x0y1-z2a3b4c5d6e7f8",
|
||||
"created_at": "2021-07-01T00:00:00Z",
|
||||
"total_in_cents": 999,
|
||||
"description": "JamKazam Gold Plan - Monthly",
|
||||
"status": "paid"
|
||||
},
|
||||
{
|
||||
"id": "g9h0i1j2-k3l4-m5n6-o7p8-q9r0s1t2u3v4w5x6",
|
||||
"created_at": "2021-06-01T00:00:00Z",
|
||||
"total_in_cents": 999,
|
||||
"description": "JamKazam Gold Plan - Monthly",
|
||||
"status": "paid"
|
||||
},
|
||||
{
|
||||
"id": "y7z8a9b0-c1d2-e3f4-g5h6-i7j8k9l0m1n2o3p4",
|
||||
"created_at": "2021-05-01T00:00:00Z",
|
||||
"total_in_cents": 999,
|
||||
"description": "JamKazam Gold Plan - Monthly",
|
||||
"status": "paid"
|
||||
},
|
||||
{
|
||||
"id": "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6",
|
||||
"created_at": "2021-04-01T00:00:00Z",
|
||||
"total_in_cents": 999,
|
||||
"description": "JamKazam Gold Plan - Monthly",
|
||||
"status": "paid"
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"entries": [
|
||||
{
|
||||
"id": "a1b2c3d4-e5f6-g7h8-i9j0-k1l2m3n4o5p6",
|
||||
"created_at": "2021-03-01T00:00:00Z",
|
||||
"total_in_cents": 999,
|
||||
"description": "JamKazam Gold Plan - Monthly",
|
||||
"status": "paid"
|
||||
},
|
||||
{
|
||||
"id": "q7r8s9t0-u1v2-w3x4-y5z6-a7b8c9d0e1f2",
|
||||
"created_at": "2021-02-01T00:00:00Z",
|
||||
"total_in_cents": 999,
|
||||
"description": "JamKazam Gold Plan - Monthly",
|
||||
"status": "paid"
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
|
|
@ -38,6 +38,7 @@ import JKMusicSessionsLobby from '../page/JKMusicSessionsLobby';
|
|||
import JKEditProfile from '../page/JKEditProfile';
|
||||
import JKEditAccount from '../page/JKEditAccount';
|
||||
import JKAccountSubscription from '../page/JKAccountSubscription';
|
||||
import JKPaymentHistory from '../page/JKPaymentHistory';
|
||||
|
||||
|
||||
//import loadable from '@loadable/component';
|
||||
|
|
@ -265,6 +266,7 @@ function JKDashboardMain() {
|
|||
<PrivateRoute path="/profile" component={JKEditProfile} />
|
||||
<PrivateRoute path="/account/identity" component={JKEditAccount} />
|
||||
<PrivateRoute path="/account/subscription" component={JKAccountSubscription} />
|
||||
<PrivateRoute path="/account/payments" component={JKPaymentHistory} />
|
||||
{/*Redirect*/}
|
||||
<Redirect to="/errors/404" />
|
||||
</Switch>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
import React, { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Card, CardBody, Row, Col, Table, Alert, Button } from 'reactstrap';
|
||||
import FalconCardHeader from '../common/FalconCardHeader';
|
||||
import { getInvoiceHistory } from '../../helpers/rest';
|
||||
import { isIterableArray } from '../../helpers/utils';
|
||||
|
||||
const JKPaymentHistory = () => {
|
||||
const { t } = useTranslation('account');
|
||||
const [payments, setPayments] = useState([]);
|
||||
const LIMIT = 10;
|
||||
const [offset, setOffset] = useState(0);
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const fetchPayments = async () => {
|
||||
const options = { limit: LIMIT, cursor: offset };
|
||||
try {
|
||||
setLoading(true);
|
||||
const response = await getInvoiceHistory(options);
|
||||
const data = await response.json();
|
||||
setPayments(data.entries);
|
||||
setOffset(prev => prev + LIMIT);
|
||||
}catch(error) {
|
||||
console.error(error);
|
||||
}finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(async () => {
|
||||
// fetch payments
|
||||
const options = { cursor: offset, limit: LIMIT };
|
||||
await fetchPayments(options);
|
||||
}, []);
|
||||
|
||||
const goToNextPage = async () => {
|
||||
const options = { cursor: offset, limit: LIMIT };
|
||||
await fetchPayments(options);
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<FalconCardHeader title={t('payments.page_title')} titleClass="font-weight-bold" />
|
||||
<CardBody className="pt-3" style={{ backgroundColor: '#edf2f9' }}>
|
||||
<Row>
|
||||
<Col className="mb-2 col-md-9 col-lg-8 m-auto">
|
||||
{isIterableArray(payments) && payments.length ? (
|
||||
<>
|
||||
<Table striped bordered className="fs--1" data-testid="paymentsListTable">
|
||||
<thead className="bg-200 text-900">
|
||||
<tr>
|
||||
<th scope="col">{t('payments.payment_attributes.date')}</th>
|
||||
<th scope="col" style={{ minWidth: 250 }}>
|
||||
{t('payments.payment_attributes.description')}
|
||||
</th>
|
||||
<th scope="col">{t('payments.payment_attributes.status')}</th>
|
||||
<th scope="col">{t('payments.payment_attributes.amount')}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody className="list">
|
||||
{payments.map(payment => (
|
||||
<tr key={payment.id}>
|
||||
<td>{new Date(payment.created_at).toLocaleDateString("en-US", {
|
||||
year: "numeric",
|
||||
month: "2-digit",
|
||||
day: "2-digit"}
|
||||
)}
|
||||
</td>
|
||||
<td>{payment.description}</td>
|
||||
<td>{payment.status}</td>
|
||||
<td>{`$${(payment.total_in_cents / 100).toFixed(2)}`}</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
</Table>
|
||||
<Button onClick={goToNextPage} data-testid="nextPageButton" disabled={loading}>
|
||||
{loading ? <span>{t('payments.loading')}</span> : <span>{t('payments.load_more')}</span> }
|
||||
</Button>
|
||||
</>
|
||||
) : (
|
||||
<Alert color="info" className="mb-0">
|
||||
{t('payments.no_payments')}
|
||||
</Alert>
|
||||
)}
|
||||
</Col>
|
||||
</Row>
|
||||
</CardBody>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default JKPaymentHistory;
|
||||
|
|
@ -311,4 +311,12 @@ export const changeSubscription = (plan_code) => {
|
|||
.then(response => resolve(response))
|
||||
.catch(error => reject(error));
|
||||
})
|
||||
}
|
||||
|
||||
export const getInvoiceHistory = (options = {}) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
apiFetch(`/recurly/invoice_history?${new URLSearchParams(options)}`)
|
||||
.then(response => resolve(response))
|
||||
.catch(error => reject(error))
|
||||
});
|
||||
}
|
||||
|
|
@ -84,5 +84,17 @@
|
|||
"failed_to_change_plan": "Failed to update subscription plan. Please try again later. Please contact support@jamkazam.com if you continue to have problems.",
|
||||
"changed_plan_successfully": "You have successfully updated your subscription plan."
|
||||
}
|
||||
},
|
||||
"payments": {
|
||||
"page_title": "Payment History",
|
||||
"payment_attributes": {
|
||||
"date": "Date",
|
||||
"description": "Description",
|
||||
"amount": "Amount",
|
||||
"status": "Status"
|
||||
},
|
||||
"no_payments": "No payments found.",
|
||||
"load_more": "Load More",
|
||||
"loading": "Loading..."
|
||||
}
|
||||
}
|
||||
|
|
@ -55,10 +55,11 @@ export const accountRoutes = {
|
|||
exact: true,
|
||||
icon: 'lock',
|
||||
children: [
|
||||
{ to: '/account/subscription', name: 'Subscription'},
|
||||
{ to: '/account/payments', name: 'Payments'},
|
||||
{ to: '/account/identity', name: 'Identity'},
|
||||
{ to: '/account/affiliate', name: 'Affiliate'}
|
||||
{ to: '/account/subscription', name: 'Subscription'},
|
||||
{ to: '/account/payments', name: 'Payment History'},
|
||||
{ to: '/account/payment-method', name: 'Payment Method'},
|
||||
{ to: '/account/affiliate', name: 'Affiliate Program'},
|
||||
]
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue