account payments page and cypress tests

This commit is contained in:
Nuwan 2024-04-24 08:28:02 +05:30
parent 4dd95af2fa
commit c2ffbff216
10 changed files with 339 additions and 3 deletions

View File

@ -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')
})
});
})

View File

@ -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"
}
]
}

View File

@ -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"
}
]
}

View File

@ -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"
}
]
}

View File

@ -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>

View File

@ -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;

View File

@ -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))
});
}

View File

@ -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..."
}
}

View File

@ -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'},
]
}