forked from Creditra/Creditra-Frontend
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathAprBreakdown.test.tsx
More file actions
117 lines (96 loc) · 5.21 KB
/
Copy pathAprBreakdown.test.tsx
File metadata and controls
117 lines (96 loc) · 5.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import { fireEvent, render, screen } from '@testing-library/react';
import { describe, expect, it, vi } from 'vitest';
import { AprBreakdown } from './AprBreakdown';
vi.mock('../hooks/useBodyScrollLock', () => ({ useBodyScrollLock: vi.fn() }));
vi.mock('../hooks/useFocusTrap', () => ({
useFocusTrap: vi.fn(() => ({ current: null })),
}));
const renderBreakdown = (props?: Partial<React.ComponentProps<typeof AprBreakdown>>) =>
render(<AprBreakdown apr={8.5} {...props} />);
describe('AprBreakdown', () => {
// ── Trigger ───────────────────────────────────────────────────────────────
it('renders the APR on the trigger button', () => {
renderBreakdown({ apr: 8.5 });
expect(screen.getByRole('button', { name: /8\.50%/i })).toBeInTheDocument();
});
it('trigger has aria-expanded=false when closed', () => {
renderBreakdown();
expect(screen.getByRole('button', { name: /8\.50%/i })).toHaveAttribute('aria-expanded', 'false');
});
it('panel is not in the DOM when closed', () => {
renderBreakdown();
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
});
// ── Open / close ──────────────────────────────────────────────────────────
it('opens panel on trigger click', () => {
renderBreakdown();
fireEvent.click(screen.getByRole('button', { name: /8\.50%/i }));
expect(screen.getByRole('dialog')).toBeInTheDocument();
expect(screen.getByRole('button', { name: /8\.50%/i })).toHaveAttribute('aria-expanded', 'true');
});
it('closes panel when close button is clicked', () => {
renderBreakdown();
fireEvent.click(screen.getByRole('button', { name: /8\.50%/i }));
fireEvent.click(screen.getByRole('button', { name: /close apr breakdown/i }));
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
});
it('closes panel on Escape key', () => {
renderBreakdown();
fireEvent.click(screen.getByRole('button', { name: /8\.50%/i }));
fireEvent.keyDown(document, { key: 'Escape' });
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
});
it('toggles closed when trigger is clicked again', () => {
renderBreakdown();
const trigger = screen.getByRole('button', { name: /8\.50%/i });
fireEvent.click(trigger);
fireEvent.click(trigger);
expect(screen.queryByRole('dialog')).not.toBeInTheDocument();
});
// ── Itemized math ─────────────────────────────────────────────────────────
it('shows all breakdown rows when panel is open', () => {
renderBreakdown({ apr: 8.5, baseRate: 5, riskPremium: 3.5, originationFee: 0 });
fireEvent.click(screen.getByRole('button', { name: /8\.50%/i }));
expect(screen.getByText('Base interest rate')).toBeInTheDocument();
expect(screen.getByText('Risk premium')).toBeInTheDocument();
});
it('shows origination fee row when fee > 0', () => {
renderBreakdown({ apr: 9.5, baseRate: 5, riskPremium: 3.5, originationFee: 1 });
fireEvent.click(screen.getByRole('button', { name: /9\.50%/i }));
expect(screen.getByText('Origination fee (annual equiv.)')).toBeInTheDocument();
});
it('omits origination fee row when fee is 0', () => {
renderBreakdown({ apr: 8.5, baseRate: 5, riskPremium: 3.5, originationFee: 0 });
fireEvent.click(screen.getByRole('button', { name: /8\.50%/i }));
expect(screen.queryByText(/origination fee/i)).not.toBeInTheDocument();
});
it('total APR row shows the passed apr value', () => {
renderBreakdown({ apr: 12.75 });
fireEvent.click(screen.getByRole('button', { name: /12\.75%/i }));
// Total row shows "12.75%" in the value cell
const totalValue = document.querySelector('.apr-breakdown-total-value');
expect(totalValue?.textContent).toContain('12.75%');
});
it('derives risk premium from apr - baseRate when riskPremium is omitted', () => {
renderBreakdown({ apr: 8.5, baseRate: 5 });
fireEvent.click(screen.getByRole('button', { name: /8\.50%/i }));
// Risk premium = 8.5 - 5 = 3.5
expect(screen.getByText('Risk premium')).toBeInTheDocument();
});
// ── Accessibility ─────────────────────────────────────────────────────────
it('panel has role="dialog" with accessible label', () => {
renderBreakdown();
fireEvent.click(screen.getByRole('button', { name: /8\.50%/i }));
expect(screen.getByRole('dialog', { name: /apr breakdown/i })).toBeInTheDocument();
});
it('close button has an accessible label', () => {
renderBreakdown();
fireEvent.click(screen.getByRole('button', { name: /8\.50%/i }));
expect(screen.getByRole('button', { name: /close apr breakdown/i })).toBeInTheDocument();
});
it('footnote is present', () => {
renderBreakdown();
fireEvent.click(screen.getByRole('button', { name: /8\.50%/i }));
expect(screen.getByText(/monthly interest/i)).toBeInTheDocument();
});
});