- Add frontend unit tests with Vitest for components, hooks, pages, and utilities - Add backend tests for webhooks, notifications, middleware, and edge cases - Add ForgotPassword, NotFound, and ResetPassword pages - Add migration for orphaned staff resources conversion - Add coverage directory to gitignore (generated reports) - Various bug fixes and improvements from previous work 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
682 lines
21 KiB
TypeScript
682 lines
21 KiB
TypeScript
/**
|
|
* Unit tests for QuotaWarningBanner component
|
|
*
|
|
* Tests cover:
|
|
* - Rendering based on quota overage state
|
|
* - Critical, urgent, and warning severity levels
|
|
* - Display of correct percentage and usage information
|
|
* - Multiple overages display
|
|
* - Manage Quota button/link functionality
|
|
* - Dismiss button functionality
|
|
* - Date formatting
|
|
* - Internationalization (i18n)
|
|
* - Accessibility attributes
|
|
*/
|
|
|
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
import { render, screen } from '@testing-library/react';
|
|
import userEvent from '@testing-library/user-event';
|
|
import { BrowserRouter } from 'react-router-dom';
|
|
import React from 'react';
|
|
import QuotaWarningBanner from '../QuotaWarningBanner';
|
|
import { QuotaOverage } from '../../api/auth';
|
|
|
|
// Mock react-i18next
|
|
vi.mock('react-i18next', () => ({
|
|
useTranslation: () => ({
|
|
t: (key: string, fallback: string, options?: Record<string, unknown>) => {
|
|
// Handle interpolation for dynamic values
|
|
if (options) {
|
|
let result = fallback;
|
|
Object.entries(options).forEach(([key, value]) => {
|
|
result = result.replace(`{{${key}}}`, String(value));
|
|
});
|
|
return result;
|
|
}
|
|
return fallback;
|
|
},
|
|
}),
|
|
}));
|
|
|
|
// Test wrapper with Router
|
|
const createWrapper = () => {
|
|
return ({ children }: { children: React.ReactNode }) => (
|
|
<BrowserRouter>{children}</BrowserRouter>
|
|
);
|
|
};
|
|
|
|
// Test data factories
|
|
const createMockOverage = (overrides?: Partial<QuotaOverage>): QuotaOverage => ({
|
|
id: 1,
|
|
quota_type: 'resources',
|
|
display_name: 'Resources',
|
|
current_usage: 15,
|
|
allowed_limit: 10,
|
|
overage_amount: 5,
|
|
days_remaining: 14,
|
|
grace_period_ends_at: '2025-12-21T00:00:00Z',
|
|
...overrides,
|
|
});
|
|
|
|
describe('QuotaWarningBanner', () => {
|
|
beforeEach(() => {
|
|
vi.clearAllMocks();
|
|
});
|
|
|
|
describe('Rendering Conditions', () => {
|
|
it('should not render when overages array is empty', () => {
|
|
const { container } = render(
|
|
<QuotaWarningBanner overages={[]} />,
|
|
{ wrapper: createWrapper() }
|
|
);
|
|
|
|
expect(container).toBeEmptyDOMElement();
|
|
});
|
|
|
|
it('should not render when overages is null', () => {
|
|
const { container } = render(
|
|
<QuotaWarningBanner overages={null as any} />,
|
|
{ wrapper: createWrapper() }
|
|
);
|
|
|
|
expect(container).toBeEmptyDOMElement();
|
|
});
|
|
|
|
it('should not render when overages is undefined', () => {
|
|
const { container } = render(
|
|
<QuotaWarningBanner overages={undefined as any} />,
|
|
{ wrapper: createWrapper() }
|
|
);
|
|
|
|
expect(container).toBeEmptyDOMElement();
|
|
});
|
|
|
|
it('should render when quota is near limit (warning state)', () => {
|
|
const overages = [createMockOverage({ days_remaining: 14 })];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
expect(screen.getByText(/quota exceeded/i)).toBeInTheDocument();
|
|
});
|
|
|
|
it('should render when quota is critical (1 day remaining)', () => {
|
|
const overages = [createMockOverage({ days_remaining: 1 })];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
expect(screen.getByText(/urgent.*automatic archiving tomorrow/i)).toBeInTheDocument();
|
|
});
|
|
|
|
it('should render when quota is urgent (7 days remaining)', () => {
|
|
const overages = [createMockOverage({ days_remaining: 7 })];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
expect(screen.getByText(/action required.*7 days left/i)).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
describe('Severity Levels and Styling', () => {
|
|
it('should apply warning styles for normal overages (>7 days)', () => {
|
|
const overages = [createMockOverage({ days_remaining: 14 })];
|
|
|
|
const { container } = render(
|
|
<QuotaWarningBanner overages={overages} />,
|
|
{ wrapper: createWrapper() }
|
|
);
|
|
|
|
const banner = container.querySelector('div[class*="bg-amber-100"]');
|
|
expect(banner).toBeInTheDocument();
|
|
});
|
|
|
|
it('should apply urgent styles for 7 days or less', () => {
|
|
const overages = [createMockOverage({ days_remaining: 7 })];
|
|
|
|
const { container } = render(
|
|
<QuotaWarningBanner overages={overages} />,
|
|
{ wrapper: createWrapper() }
|
|
);
|
|
|
|
const banner = container.querySelector('div[class*="bg-amber-500"]');
|
|
expect(banner).toBeInTheDocument();
|
|
});
|
|
|
|
it('should apply critical styles for 1 day or less', () => {
|
|
const overages = [createMockOverage({ days_remaining: 1 })];
|
|
|
|
const { container } = render(
|
|
<QuotaWarningBanner overages={overages} />,
|
|
{ wrapper: createWrapper() }
|
|
);
|
|
|
|
const banner = container.querySelector('div[class*="bg-red-600"]');
|
|
expect(banner).toBeInTheDocument();
|
|
});
|
|
|
|
it('should apply critical styles for 0 days remaining', () => {
|
|
const overages = [createMockOverage({ days_remaining: 0 })];
|
|
|
|
const { container } = render(
|
|
<QuotaWarningBanner overages={overages} />,
|
|
{ wrapper: createWrapper() }
|
|
);
|
|
|
|
const banner = container.querySelector('div[class*="bg-red-600"]');
|
|
expect(banner).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
describe('Usage and Percentage Display', () => {
|
|
it('should display correct overage amount', () => {
|
|
const overages = [
|
|
createMockOverage({
|
|
overage_amount: 5,
|
|
display_name: 'Resources',
|
|
}),
|
|
];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
expect(screen.getByText(/you have 5 Resources over your plan limit/i)).toBeInTheDocument();
|
|
});
|
|
|
|
it('should display current usage and limit in multi-overage list', () => {
|
|
const overages = [
|
|
createMockOverage({
|
|
id: 1,
|
|
current_usage: 15,
|
|
allowed_limit: 10,
|
|
display_name: 'Staff Members',
|
|
}),
|
|
createMockOverage({
|
|
id: 2,
|
|
current_usage: 20,
|
|
allowed_limit: 15,
|
|
display_name: 'Resources',
|
|
}),
|
|
];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
// Usage/limit is shown in the "All overages" list when there are multiple
|
|
expect(screen.getByText(/Staff Members: 15\/10/)).toBeInTheDocument();
|
|
expect(screen.getByText(/Resources: 20\/15/)).toBeInTheDocument();
|
|
});
|
|
|
|
it('should display quota type name', () => {
|
|
const overages = [
|
|
createMockOverage({
|
|
display_name: 'Calendar Events',
|
|
overage_amount: 100,
|
|
}),
|
|
];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
expect(screen.getByText(/you have 100 Calendar Events over your plan limit/i)).toBeInTheDocument();
|
|
});
|
|
|
|
it('should format and display grace period end date', () => {
|
|
const overages = [
|
|
createMockOverage({
|
|
grace_period_ends_at: '2025-12-25T00:00:00Z',
|
|
}),
|
|
];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
// Date formatting will depend on locale, but should contain the date components
|
|
const detailsText = screen.getByText(/grace period ends/i);
|
|
expect(detailsText).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
describe('Multiple Overages', () => {
|
|
it('should display most urgent overage in main message', () => {
|
|
const overages = [
|
|
createMockOverage({ id: 1, days_remaining: 14, display_name: 'Resources' }),
|
|
createMockOverage({ id: 2, days_remaining: 3, display_name: 'Staff Members' }),
|
|
createMockOverage({ id: 3, days_remaining: 7, display_name: 'Events' }),
|
|
];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
// Should show the most urgent (3 days)
|
|
expect(screen.getByText(/action required.*3 days left/i)).toBeInTheDocument();
|
|
});
|
|
|
|
it('should show additional overages section when multiple overages exist', () => {
|
|
const overages = [
|
|
createMockOverage({ id: 1, days_remaining: 14, display_name: 'Resources', current_usage: 15, allowed_limit: 10, overage_amount: 5 }),
|
|
createMockOverage({ id: 2, days_remaining: 7, display_name: 'Staff', current_usage: 8, allowed_limit: 5, overage_amount: 3 }),
|
|
];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
expect(screen.getByText(/all overages:/i)).toBeInTheDocument();
|
|
});
|
|
|
|
it('should list all overages with details in the additional section', () => {
|
|
const overages = [
|
|
createMockOverage({
|
|
id: 1,
|
|
display_name: 'Resources',
|
|
current_usage: 15,
|
|
allowed_limit: 10,
|
|
overage_amount: 5,
|
|
days_remaining: 14,
|
|
}),
|
|
createMockOverage({
|
|
id: 2,
|
|
display_name: 'Staff',
|
|
current_usage: 8,
|
|
allowed_limit: 5,
|
|
overage_amount: 3,
|
|
days_remaining: 7,
|
|
}),
|
|
];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
expect(screen.getByText(/Resources: 15\/10/)).toBeInTheDocument();
|
|
expect(screen.getByText(/over by 5/)).toBeInTheDocument();
|
|
expect(screen.getByText(/Staff: 8\/5/)).toBeInTheDocument();
|
|
expect(screen.getByText(/over by 3/)).toBeInTheDocument();
|
|
});
|
|
|
|
it('should not show additional overages section for single overage', () => {
|
|
const overages = [createMockOverage()];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
expect(screen.queryByText(/all overages:/i)).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('should display "expires today" for 0 days remaining in overage list', () => {
|
|
const overages = [
|
|
createMockOverage({ id: 1, days_remaining: 14 }),
|
|
createMockOverage({ id: 2, days_remaining: 0, display_name: 'Critical Item' }),
|
|
];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
expect(screen.getByText(/expires today!/i)).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
describe('Manage Quota Button', () => {
|
|
it('should render Manage Quota link', () => {
|
|
const overages = [createMockOverage()];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
const link = screen.getByRole('link', { name: /manage quota/i });
|
|
expect(link).toBeInTheDocument();
|
|
});
|
|
|
|
it('should link to settings/quota page', () => {
|
|
const overages = [createMockOverage()];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
const link = screen.getByRole('link', { name: /manage quota/i });
|
|
expect(link).toHaveAttribute('href', '/settings/quota');
|
|
});
|
|
|
|
it('should display external link icon', () => {
|
|
const overages = [createMockOverage()];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
const link = screen.getByRole('link', { name: /manage quota/i });
|
|
const icon = link.querySelector('svg');
|
|
expect(icon).toBeInTheDocument();
|
|
});
|
|
|
|
it('should apply warning button styles for normal overages', () => {
|
|
const overages = [createMockOverage({ days_remaining: 14 })];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
const link = screen.getByRole('link', { name: /manage quota/i });
|
|
expect(link).toHaveClass('bg-amber-600');
|
|
});
|
|
|
|
it('should apply urgent button styles for urgent/critical overages', () => {
|
|
const overages = [createMockOverage({ days_remaining: 7 })];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
const link = screen.getByRole('link', { name: /manage quota/i });
|
|
expect(link).toHaveClass('bg-white/20');
|
|
});
|
|
});
|
|
|
|
describe('Dismiss Button', () => {
|
|
it('should render dismiss button when onDismiss prop is provided', () => {
|
|
const overages = [createMockOverage()];
|
|
const onDismiss = vi.fn();
|
|
|
|
render(<QuotaWarningBanner overages={overages} onDismiss={onDismiss} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
const dismissButton = screen.getByRole('button', { name: /dismiss/i });
|
|
expect(dismissButton).toBeInTheDocument();
|
|
});
|
|
|
|
it('should not render dismiss button when onDismiss prop is not provided', () => {
|
|
const overages = [createMockOverage()];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
const dismissButton = screen.queryByRole('button', { name: /dismiss/i });
|
|
expect(dismissButton).not.toBeInTheDocument();
|
|
});
|
|
|
|
it('should call onDismiss when dismiss button is clicked', async () => {
|
|
const user = userEvent.setup();
|
|
const overages = [createMockOverage()];
|
|
const onDismiss = vi.fn();
|
|
|
|
render(<QuotaWarningBanner overages={overages} onDismiss={onDismiss} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
const dismissButton = screen.getByRole('button', { name: /dismiss/i });
|
|
await user.click(dismissButton);
|
|
|
|
expect(onDismiss).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('should display X icon in dismiss button', () => {
|
|
const overages = [createMockOverage()];
|
|
const onDismiss = vi.fn();
|
|
|
|
render(<QuotaWarningBanner overages={overages} onDismiss={onDismiss} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
const dismissButton = screen.getByRole('button', { name: /dismiss/i });
|
|
const icon = dismissButton.querySelector('svg');
|
|
expect(icon).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
describe('Accessibility', () => {
|
|
it('should have alert icon with appropriate styling', () => {
|
|
const overages = [createMockOverage()];
|
|
|
|
const { container } = render(
|
|
<QuotaWarningBanner overages={overages} />,
|
|
{ wrapper: createWrapper() }
|
|
);
|
|
|
|
// AlertTriangle icon should be present
|
|
const icon = container.querySelector('svg');
|
|
expect(icon).toBeInTheDocument();
|
|
});
|
|
|
|
it('should have accessible label for dismiss button', () => {
|
|
const overages = [createMockOverage()];
|
|
const onDismiss = vi.fn();
|
|
|
|
render(<QuotaWarningBanner overages={overages} onDismiss={onDismiss} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
const dismissButton = screen.getByRole('button', { name: /dismiss/i });
|
|
expect(dismissButton).toHaveAttribute('aria-label', 'Dismiss');
|
|
});
|
|
|
|
it('should use semantic HTML structure', () => {
|
|
const overages = [createMockOverage({ days_remaining: 14 })];
|
|
|
|
const { container } = render(
|
|
<QuotaWarningBanner overages={overages} />,
|
|
{ wrapper: createWrapper() }
|
|
);
|
|
|
|
// Should have proper div structure
|
|
expect(container.querySelector('div')).toBeInTheDocument();
|
|
});
|
|
|
|
it('should have accessible link for Manage Quota', () => {
|
|
const overages = [createMockOverage()];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
const link = screen.getByRole('link', { name: /manage quota/i });
|
|
expect(link).toBeInTheDocument();
|
|
expect(link.tagName).toBe('A');
|
|
});
|
|
});
|
|
|
|
describe('Message Priority', () => {
|
|
it('should show critical message for 1 day remaining', () => {
|
|
const overages = [createMockOverage({ days_remaining: 1 })];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
expect(screen.getByText(/urgent.*automatic archiving tomorrow/i)).toBeInTheDocument();
|
|
});
|
|
|
|
it('should show urgent message for 2-7 days remaining', () => {
|
|
const overages = [createMockOverage({ days_remaining: 5 })];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
expect(screen.getByText(/action required.*5 days left/i)).toBeInTheDocument();
|
|
});
|
|
|
|
it('should show warning message for more than 7 days remaining', () => {
|
|
const overages = [createMockOverage({ days_remaining: 10 })];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
expect(screen.getByText(/quota exceeded for 1 item/i)).toBeInTheDocument();
|
|
});
|
|
|
|
it('should show count of overages in warning message', () => {
|
|
const overages = [
|
|
createMockOverage({ id: 1, days_remaining: 14 }),
|
|
createMockOverage({ id: 2, days_remaining: 10 }),
|
|
createMockOverage({ id: 3, days_remaining: 12 }),
|
|
];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
expect(screen.getByText(/quota exceeded for 3 item/i)).toBeInTheDocument();
|
|
});
|
|
});
|
|
|
|
describe('Integration', () => {
|
|
it('should render complete banner with all elements', () => {
|
|
const overages = [
|
|
createMockOverage({
|
|
id: 1,
|
|
quota_type: 'resources',
|
|
display_name: 'Resources',
|
|
current_usage: 15,
|
|
allowed_limit: 10,
|
|
overage_amount: 5,
|
|
days_remaining: 7,
|
|
grace_period_ends_at: '2025-12-21T00:00:00Z',
|
|
}),
|
|
];
|
|
const onDismiss = vi.fn();
|
|
|
|
render(<QuotaWarningBanner overages={overages} onDismiss={onDismiss} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
// Check main message
|
|
expect(screen.getByText(/action required.*7 days left/i)).toBeInTheDocument();
|
|
|
|
// Check details
|
|
expect(screen.getByText(/you have 5 Resources over your plan limit/i)).toBeInTheDocument();
|
|
|
|
// Check Manage Quota link
|
|
const link = screen.getByRole('link', { name: /manage quota/i });
|
|
expect(link).toBeInTheDocument();
|
|
expect(link).toHaveAttribute('href', '/settings/quota');
|
|
|
|
// Check dismiss button
|
|
const dismissButton = screen.getByRole('button', { name: /dismiss/i });
|
|
expect(dismissButton).toBeInTheDocument();
|
|
|
|
// Check icons are present (via SVG elements)
|
|
const { container } = render(<QuotaWarningBanner overages={overages} onDismiss={onDismiss} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
const icons = container.querySelectorAll('svg');
|
|
expect(icons.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
it('should handle complex multi-overage scenario', async () => {
|
|
const user = userEvent.setup();
|
|
const overages = [
|
|
createMockOverage({
|
|
id: 1,
|
|
display_name: 'Resources',
|
|
current_usage: 15,
|
|
allowed_limit: 10,
|
|
overage_amount: 5,
|
|
days_remaining: 14,
|
|
}),
|
|
createMockOverage({
|
|
id: 2,
|
|
display_name: 'Staff Members',
|
|
current_usage: 12,
|
|
allowed_limit: 8,
|
|
overage_amount: 4,
|
|
days_remaining: 2,
|
|
}),
|
|
createMockOverage({
|
|
id: 3,
|
|
display_name: 'Calendar Events',
|
|
current_usage: 500,
|
|
allowed_limit: 400,
|
|
overage_amount: 100,
|
|
days_remaining: 7,
|
|
}),
|
|
];
|
|
const onDismiss = vi.fn();
|
|
|
|
render(<QuotaWarningBanner overages={overages} onDismiss={onDismiss} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
// Should show most urgent (2 days)
|
|
expect(screen.getByText(/action required.*2 days left/i)).toBeInTheDocument();
|
|
|
|
// Should show all overages section
|
|
expect(screen.getByText(/all overages:/i)).toBeInTheDocument();
|
|
expect(screen.getByText(/Resources: 15\/10/)).toBeInTheDocument();
|
|
expect(screen.getByText(/Staff Members: 12\/8/)).toBeInTheDocument();
|
|
expect(screen.getByText(/Calendar Events: 500\/400/)).toBeInTheDocument();
|
|
|
|
// Should be able to dismiss
|
|
const dismissButton = screen.getByRole('button', { name: /dismiss/i });
|
|
await user.click(dismissButton);
|
|
expect(onDismiss).toHaveBeenCalledTimes(1);
|
|
});
|
|
});
|
|
|
|
describe('Edge Cases', () => {
|
|
it('should handle negative days remaining', () => {
|
|
const overages = [createMockOverage({ days_remaining: -1 })];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
// Should treat as critical (0 or less)
|
|
const { container } = render(
|
|
<QuotaWarningBanner overages={overages} />,
|
|
{ wrapper: createWrapper() }
|
|
);
|
|
|
|
const banner = container.querySelector('div[class*="bg-red-600"]');
|
|
expect(banner).toBeInTheDocument();
|
|
});
|
|
|
|
it('should handle very large overage amounts', () => {
|
|
const overages = [
|
|
createMockOverage({
|
|
overage_amount: 999999,
|
|
display_name: 'Events',
|
|
}),
|
|
];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
expect(screen.getByText(/you have 999999 Events over your plan limit/i)).toBeInTheDocument();
|
|
});
|
|
|
|
it('should handle zero overage amount', () => {
|
|
const overages = [
|
|
createMockOverage({
|
|
overage_amount: 0,
|
|
current_usage: 10,
|
|
allowed_limit: 10,
|
|
}),
|
|
];
|
|
|
|
render(<QuotaWarningBanner overages={overages} />, {
|
|
wrapper: createWrapper(),
|
|
});
|
|
|
|
expect(screen.getByText(/you have 0 Resources over your plan limit/i)).toBeInTheDocument();
|
|
});
|
|
});
|
|
});
|