Skip to content

Commit

Permalink
Merge pull request #87 from RevelioStartup/hotfix/payment-error
Browse files Browse the repository at this point in the history
[FIX] update payment error message display
  • Loading branch information
catherineeangel authored May 27, 2024
2 parents 8ee25e2 + 1c57497 commit a021328
Show file tree
Hide file tree
Showing 11 changed files with 115 additions and 24 deletions.
41 changes: 41 additions & 0 deletions __tests__/payment/payment-details-midtrans-error.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import '@testing-library/jest-dom'
import { render, waitFor } from '@testing-library/react'
import PaymentPage from '@/app/payment/page'

jest.mock('next/navigation', () => ({
useSearchParams: jest.fn(() => ({
get: jest.fn(() => 'test_order_id'),
})),
}))

jest.mock('@/redux/api/paymentApi', () => ({
useLazyGetTransactionQuery: jest.fn(() => [
jest.fn(),
{
data: null,
isLoading: false,
error: {
data: {
error:
'Midtrans API is returning API error. HTTP status code: `401`. API response: `{"status_code":"401","status_message":"Unknown Merchant server_key/id","id":"c8f11ee1-1ed5-4efe-bcfb-65a24876371e"}`',
},
},
},
]),
}))

describe('Payment Detail Page Returns Error', () => {
beforeAll(() => {
jest.spyOn(window, 'open').mockImplementation()
})

it('renders transaction detail with error message', async () => {
const { queryByTestId, getByText } = render(<PaymentPage />)
await waitFor(() => {
expect(queryByTestId('loader')).not.toBeInTheDocument()
})

expect(getByText('Oops... something went wrong')).toBeInTheDocument()
expect(getByText('Unknown Merchant server_key/id')).toBeInTheDocument()
})
})
1 change: 1 addition & 0 deletions __tests__/payment/payment-details-no-url.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ jest.mock('@/redux/api/paymentApi', () => ({
},
},
isLoading: false,
error: null,
},
]),
}))
Expand Down
3 changes: 2 additions & 1 deletion __tests__/payment/payment-details-with-url.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ jest.mock('@/redux/api/paymentApi', () => ({
transaction_detail: mockTransaction,
},
isLoading: false,
error: null,
},
]),
}))
Expand Down Expand Up @@ -51,6 +52,6 @@ describe('Payment Detail Page With Midtrans Url', () => {

fireEvent.click(getByText('Continue Transaction'))

expect(window.open).toHaveBeenCalledWith('https://example.com/midtrans')
expect(window.open).toHaveBeenCalledWith(mockTransaction.midtrans_url)
})
})
3 changes: 2 additions & 1 deletion __tests__/payment/payment-fail.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ describe('PaymentSuccess Component', () => {
},
},
isLoading: false,
error: null,
},
])

Expand All @@ -63,7 +64,7 @@ describe('PaymentSuccess Component', () => {
const button = getByRole('button', { name: 'See Transaction History' })
expect(button.closest('a')).toHaveAttribute(
'href',
'/profile?tab=history'
'/dashboard?tab=history'
)
})
})
Expand Down
3 changes: 2 additions & 1 deletion __tests__/payment/payment-success.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ describe('PaymentSuccess Component', () => {
},
},
isLoading: false,
error: null,
},
])

Expand All @@ -64,7 +65,7 @@ describe('PaymentSuccess Component', () => {
const button = getByRole('button', { name: 'See Transaction History' })
expect(button.closest('a')).toHaveAttribute(
'href',
'/profile?tab=history'
'/dashboard?tab=history'
)
})
})
Expand Down
2 changes: 1 addition & 1 deletion src/app/dashboard/TransactionHistory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ export const TransactionHistory = ({ status }: TransactionHistoryI) => {
'hover:underline hover:underline-offset-1'
)}
>
<p>{status.toUpperCase()}</p>
<p>{(status ?? '').toUpperCase()}</p>
{!!midtrans_url && (
<i className="i-ph-arrow-square-up-right-light size-5" />
)}
Expand Down
71 changes: 54 additions & 17 deletions src/app/payment/PaymentDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
'use client'
import { Button } from '@/components/elements/Button'
import { useLazyGetTransactionQuery } from '@/redux/api/paymentApi'
import { transactionErrorStatuses } from '@/types/payment'
import {
MidtransErrorResponse,
transactionErrorStatuses,
} from '@/types/payment'
import { useSearchParams } from 'next/navigation'
import React, { useEffect } from 'react'
import React, { useEffect, useState } from 'react'
import { PaymentSuccess } from './PaymentSuccess'
import { PaymentError } from './PaymentError'
import Link from 'next/link'
Expand All @@ -12,32 +15,60 @@ export const PaymentDetail = () => {
const searchParams = useSearchParams()
const orderId = searchParams.get('order_id')
const status = searchParams.get('transaction_status')
const [errorMessage, setErrorMessage] = useState<string>('')

const [getTransaction, { data, isLoading }] = useLazyGetTransactionQuery()
const [getTransaction, { data, isLoading, error }] =
useLazyGetTransactionQuery()
useEffect(() => {
if (orderId) {
getTransaction({ order_id: orderId })
}
}, [orderId])
const test_stat = null

if (status == 'settlement' || status == 'capture')
useEffect(() => {
if (!!error && 'data' in error) {
// Adjusted regex to correctly extract JSON surrounded by backticks
const regex = /API response: `({.*})`/
const match = (error.data as MidtransErrorResponse).error.match(regex)
if (match && match[1]) {
const jsonPart = match[1]
try {
const apiResponse = JSON.parse(jsonPart)
const statusMessage = apiResponse.status_message
setErrorMessage(statusMessage)
} catch (parseError) {
console.error('Error parsing JSON from error message:', parseError)
}
} else {
console.log('No match found or JSON part missing in the error message.')
}
}
}, [error])

if ((Boolean(data) && status == 'settlement') || status == 'capture')
return (
<PaymentSuccess
status={status ?? ''}
packageName={data?.transaction_detail.package.name ?? ''}
/>
)
if (transactionErrorStatuses.includes(status ?? ''))
if (Boolean(data) && transactionErrorStatuses.includes(status ?? ''))
return <PaymentError status={status} />
return (
<div>
<div className="flex flex-col items-center justify-center gap-3 h-[90vh]">
{isLoading ? (
<div className="flex flex-col justify-center items-center min-h-[90vh]">
<div data-testid="loader" className="loader" />
</div>
<div data-testid="loader" className="loader" />
) : Boolean(error) ? (
<>
<p className="text-3xl lg:text-5xl font-bold text-rose-600">
Oops... something went wrong
</p>
<p className="">{errorMessage}</p>
</>
) : (
data && (
<div className="flex flex-col items-center justify-center gap-3 h-[90vh]">
<>
<p className="text-3xl lg:text-5xl font-bold text-gray-600">
Transaction in Progress
</p>
Expand All @@ -46,11 +77,17 @@ export const PaymentDetail = () => {
<p className="font-bold">Package Name</p>
<p>{data?.transaction_detail.package.name}</p>
<p className="font-bold">Payment Type</p>
<p>{data?.transaction_detail.payment_type?.toUpperCase()}</p>
<p>
{(data?.transaction_detail.payment_type ?? '').toUpperCase()}
</p>
<p className="font-bold">Merchant</p>
<p>{data?.transaction_detail.payment_merchant?.toUpperCase()}</p>
<p>
{(
data?.transaction_detail.payment_merchant ?? ''
).toUpperCase()}
</p>
<p className="font-bold">Status</p>
<p>{data?.transaction_detail.status?.toUpperCase()}</p>
<p>{(data?.transaction_detail.status ?? '')?.toUpperCase()}</p>
</div>
<Button
onClick={() => {
Expand All @@ -61,12 +98,12 @@ export const PaymentDetail = () => {
>
Continue Transaction
</Button>
<Link href={'/payment?tab=history'}>
<Button>See Transaction History</Button>
</Link>
</div>
</>
)
)}
<Link href={'/dashboard?tab=history'}>
<Button>See Transaction History</Button>
</Link>
</div>
)
}
4 changes: 2 additions & 2 deletions src/app/payment/PaymentError.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ export const PaymentError = ({ status }: PaymentDetailI) => {
<p>
Transaction status:{' '}
<span className="font-bold text-rose-700">
{status.toUpperCase()}
{(status ?? '').toUpperCase()}
</span>
</p>
)}
<i className="i-ph-x-circle-duotone size-20 text-rose-400 aspect-square" />
<Link href={'/profile?tab=history'}>
<Link href={'/dashboard?tab=history'}>
<Button variant={'ghost'}>See Transaction History</Button>
</Link>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/app/payment/PaymentSuccess.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const PaymentSuccess = ({ packageName }: PaymentSuccessI) => {
Enjoy the <span className="font-bold">{packageName}</span> Package
</p>
<i className="i-ph-check-circle-duotone size-20 text-emerald-400 aspect-square" />
<Link href={'/profile?tab=history'}>
<Link href={'/dashboard?tab=history'}>
<Button>See Transaction History</Button>
</Link>
</div>
Expand Down
5 changes: 5 additions & 0 deletions src/redux/middleware/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const LOGGER_ENDPOINTS_WHITELIST = [
'createTimeline',
'createTimeline',
'askSuggestion',
]
4 changes: 4 additions & 0 deletions src/types/payment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,7 @@ export const transactionErrorStatuses = [
export type TransactionStatus = TransactionSuccess &
TransactionPending &
TransactionError

export type MidtransErrorResponse = {
error: string
}

0 comments on commit a021328

Please sign in to comment.