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

Feat: implement payment #75

Merged
merged 6 commits into from
May 12, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
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
67 changes: 52 additions & 15 deletions __tests__/package/package-list-free.test.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,51 @@
import React from 'react'
import { render } from '@testing-library/react'
import { render, fireEvent } from '@testing-library/react'
import '@testing-library/jest-dom'
import PackageList from '@/app/package/page'
import { useCreateTransactionMutation } from '@/redux/api/paymentApi'

const premium_package = {
name: 'Premium Package',
price: 5000,
event_planner: true,
event_tracker: true,
event_timeline: true,
event_rundown: true,
ai_assistant: true,
}
jest.mock('@/redux/api/packageApi', () => ({
useGetPackageDetailQuery: jest.fn((id) => ({
data: {
name: 'Default Package',
price: 5000,
event_planner: true,
event_tracker: true,
event_timeline: true,
event_rundown: true,
ai_assistant: false,
},
})),
useGetPackageDetailQuery: jest.fn((id) => {
if (id === 1) {
return {
data: {
name: 'Free Package',
price: 0,
event_planner: true,
event_tracker: false,
event_timeline: false,
event_rundown: false,
ai_assistant: false,
},
}
} else if (id === 2) {
return {
data: premium_package,
}
}

return { data: null }
}),
}))

jest.mock('@/redux/api/paymentApi', () => ({
useCreateTransactionMutation: jest.fn(),
}))

jest.mock('@/redux/api/subscriptionApi', () => ({
useGetLatestSubscriptionQuery: jest.fn((id) => ({
data: {
id: 1,
plan: 'PREMIUM',
plan: { id: 1, name: 'FREE' },
start_date: '2024-05-05T13:30:00.000Z',
end_date: '2025-05-05T13:30:00.000Z',
user: 1,
Expand All @@ -31,9 +55,22 @@ jest.mock('@/redux/api/subscriptionApi', () => ({
}))

describe('PackageList component', () => {
it('renders correctly', () => {
const { getByTestId } = render(<PackageList />)
it('renders correctly for free user', () => {
const createTransactionMock = jest.fn()
;(useCreateTransactionMutation as jest.Mock).mockReturnValue([
createTransactionMock,
{
data: { token: 'token', redirect_url: 'https://example.midtrans.com' },
isLoading: false,
},
])
const { getByTestId, queryByTestId } = render(<PackageList />)
const packageDetail = getByTestId('package-detail')
expect(packageDetail).toBeInTheDocument()
const subscribeButton = getByTestId('choose-plan-button')
expect(subscribeButton).toBeInTheDocument()
expect(queryByTestId('subscribed-plan')).not.toBeInTheDocument()
fireEvent.click(subscribeButton)
expect(createTransactionMock).toHaveBeenCalled()
})
})
40 changes: 31 additions & 9 deletions __tests__/package/package-list-premium.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import React from 'react'
import { render } from '@testing-library/react'
import '@testing-library/jest-dom'
import PackageList from '@/app/package/page'
import { formatDate } from '@/utils/formatDate'
import { useCreateTransactionMutation } from '@/redux/api/paymentApi'

jest.mock('@/redux/api/packageApi', () => ({
useGetPackageDetailQuery: jest.fn((id) => ({
Expand All @@ -17,23 +19,43 @@ jest.mock('@/redux/api/packageApi', () => ({
})),
}))

jest.mock('@/redux/api/paymentApi', () => ({
useCreateTransactionMutation: jest.fn(),
}))

const latestSubs = {
id: 1,
plan: 'PREMIUM',
start_date: '2024-05-05T13:30:00.000Z',
end_date: '2025-05-05T13:30:00.000Z',
user: 1,
is_active: true,
}

jest.mock('@/redux/api/subscriptionApi', () => ({
useGetLatestSubscriptionQuery: jest.fn((id) => ({
data: {
id: 1,
plan: 'PREMIUM',
start_date: '2024-05-05T13:30:00.000Z',
end_date: '2025-05-05T13:30:00.000Z',
user: 1,
is_active: true,
},
data: latestSubs,
})),
}))

describe('PackageList component', () => {
beforeAll(() => {
jest.spyOn(window, 'open').mockImplementation()
})

it('renders correctly', () => {
const { getByTestId } = render(<PackageList />)
;(useCreateTransactionMutation as jest.Mock).mockReturnValue([
jest.fn(),
{
data: { token: 'string', redirect_url: 'https://example.com/midtrans' },
isLoading: false,
},
])
const { getByTestId, queryByTestId } = render(<PackageList />)
const packageDetail = getByTestId('package-detail')
expect(packageDetail).toBeInTheDocument()
expect(queryByTestId('choose-plan-button')).not.toBeInTheDocument()
expect(getByTestId('subscribed-plan')).toBeInTheDocument()
expect(window.open).toHaveBeenCalledWith('https://example.com/midtrans')
})
})
55 changes: 55 additions & 0 deletions __tests__/payment/payment-details-no-url.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import '@testing-library/jest-dom'
import { render, waitFor } from '@testing-library/react'
import PaymentPage from '@/app/payment/page'
import { useLazyGetTransactionQuery } from '@/redux/api/paymentApi'

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

jest.mock('@/redux/api/paymentApi', () => ({
useLazyGetTransactionQuery: jest.fn(() => [
jest.fn(),
{
data: {
transaction_detail: {
package: { name: 'Test Package' },
payment_type: 'Test Payment Type',
payment_merchant: 'Test Payment Merchant',
midtrans_url: null,
},
},
isLoading: false,
},
]),
}))

describe('Payment Detail Page No Midtrans Url', () => {
beforeAll(() => {
jest.spyOn(window, 'open').mockImplementation()
})

it('disables button when midtrans_url is not available', async () => {
const { queryByTestId, getByRole } = render(<PaymentPage />)

await waitFor(() => expect(queryByTestId('loader')).not.toBeInTheDocument())
const continueButton = getByRole('button', {
name: 'Continue Transaction',
})
expect(continueButton).toBeDisabled()
})
it('shows loading state when query is still loading', async () => {
;(useLazyGetTransactionQuery as jest.Mock).mockReturnValue([
jest.fn(),
{
data: null,
isLoading: true,
},
])
const { queryByTestId } = render(<PaymentPage />)

await waitFor(() => expect(queryByTestId('loader')).toBeInTheDocument())
})
})
48 changes: 48 additions & 0 deletions __tests__/payment/payment-details-with-url.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import '@testing-library/jest-dom'
import { render, fireEvent, 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: {
transaction_detail: {
package: { name: 'Test Package' },
payment_type: 'Test Payment Type',
payment_merchant: 'Test Payment Merchant',
midtrans_url: 'https://example.com/midtrans',
},
},
isLoading: false,
},
]),
}))

describe('Payment Detail Page With Midtrans Url', () => {
beforeAll(() => {
jest.spyOn(window, 'open').mockImplementation()
})

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

expect(getByText('Transaction Detail')).toBeInTheDocument()
expect(getByText('Test Package')).toBeInTheDocument()
expect(getByText('Test Payment Type')).toBeInTheDocument()
expect(getByText('Test Payment Merchant')).toBeInTheDocument()

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

expect(window.open).toHaveBeenCalledWith('https://example.com/midtrans')
})
})
76 changes: 76 additions & 0 deletions __tests__/payment/payment-success.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { render, waitFor } from '@testing-library/react'
import '@testing-library/jest-dom'
import PaymentSuccessPage from '@/app/payment/success/page'
import { useLazyGetTransactionQuery } from '@/redux/api/paymentApi'

jest.mock('next/link', () => {
const MockedLink = ({ children, href }: any) => <a href={href}>{children}</a>

MockedLink.displayName = 'MockedNextLink'

return MockedLink
})

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

jest.mock('@/redux/api/paymentApi', () => ({
useLazyGetTransactionQuery: jest.fn(),
}))
describe('PaymentSuccess Component', () => {
it('renders the success message when data is loaded', async () => {
;(useLazyGetTransactionQuery as jest.Mock).mockReturnValue([
jest.fn(),
{
data: {
transaction_detail: {
id: 'transaction_id',
package: {
id: 2,
name: 'Premium',
},
midtrans_url: null,
midtrans_transaction_id: 'midtrans_id',
order_id: 'order_id',
price: 10000,
checkout_time: '2024-05-06T14:49:19Z',
expiry_time: '2024-05-06T15:04:19Z',
payment_type: 'qris',
payment_merchant: 'gopay',
status: 'settlement',
},
},
isLoading: false,
},
])

const { getByText, getByRole } = render(<PaymentSuccessPage />)

await waitFor(() => {
expect(getByText('Payment Success')).toBeInTheDocument()
expect(getByText('Premium')).toBeInTheDocument()
const button = getByRole('button', { name: 'Go to transactions' })
expect(button.closest('a')).toHaveAttribute(
'href',
'/payment/transactions/'
)
})
})

it('shows loader when data is still loading', () => {
;(useLazyGetTransactionQuery as jest.Mock).mockReturnValue([
jest.fn(),
{
data: null,
isLoading: true,
},
])

const { getByTestId } = render(<PaymentSuccessPage />)

expect(getByTestId('loader')).toBeInTheDocument()
})
})
29 changes: 24 additions & 5 deletions __tests__/profile/profile.test.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import '@testing-library/jest-dom'
import React from 'react'
import { render, screen, fireEvent } from '@testing-library/react'
import '@testing-library/jest-dom'
import { Provider } from 'react-redux'
import { store } from '@/redux/store' // Update the import path according to your file structure
import { store } from '@/redux/store'
import { useGetProfileQuery, useGetEventsQuery } from '@/redux/api/profileApi'
import Profile from '@/app/profile/page'
import { useGetSubscriptionsQuery } from '@/redux/api/subscriptionApi'

// Mock data based on the IEvent type
const mockEventsData = [
{
id: '1',
Expand All @@ -19,16 +18,36 @@ const mockEventsData = [
theme: 'Summer Vibes',
services: 'Live Music, Food Stalls, Security',
},
// ... add more mock events as needed
]

jest.mock('@/redux/api/subscriptionApi', () => ({
useGetSubscriptionsQuery: jest.fn().mockReturnValue({
data: [],
}),
useGetLatestSubscriptionQuery: jest.fn().mockReturnValue({
data: {
id: '63be0832-ece7-4e98-8f4f-65e1143c0d48',
package: {
id: 2,
name: 'Premium Package',
duration: 30,
event_planner: true,
event_tracker: true,
event_timeline: true,
event_rundown: true,
ai_assistant: true,
},
midtrans_url: null,
midtrans_transaction_id: 'midtrans_id',
order_id: 'order_id',
price: 10000,
checkout_time: '2024-05-06T14:49:19Z',
expiry_time: '2024-05-06T15:04:19Z',
status: 'settlement',
},
}),
}))

// Mocking the RTK Query hook used in the component
jest.mock('@/redux/api/profileApi', () => ({
useGetProfileQuery: jest.fn(),
useGetEventsQuery: jest.fn(),
Expand Down
Loading
Loading