import { describe, expect, it } from 'vitest'; import { render, screen } from '@testing-library/react'; import React from 'react'; import { BudgetChip } from '../../src/components/WorkCard'; /** * 往返预算徽标。 * * 它是「这个任务还剩几个来回」的唯一视觉提示,两件事必须对: * - 显示的是**剩余**而不是已用(人做决定看的是「还能问几次」) * - 0 = 不限时**不显示**,而不是显示「0/0」 */ describe('BudgetChip 预算渲染', () => { it('显示剩余数而不是已用数', () => { render(React.createElement(BudgetChip, { max: 20, used: 3 })); // 20 个上限、用了 3 个 → 剩 17。显示 3/20 会让人以为快用完了 expect(screen.getByText('17/20')).toBeInTheDocument(); }); it('max 为 0(不限)时完全不渲染', () => { const { container } = render(React.createElement(BudgetChip, { max: 0, used: 0 })); // 「0/0」或「不限」对每张卡片都成立,等于纯噪声 expect(container.firstChild).toBeNull(); }); it('max 为负数时也不渲染(脏数据兜底)', () => { const { container } = render(React.createElement(BudgetChip, { max: -1, used: 0 })); expect(container.firstChild).toBeNull(); }); it('用超时剩余按 0 显示,不出现负数', () => { render(React.createElement(BudgetChip, { max: 5, used: 8 })); // 「-3/5」看起来像 bug,而实际情形(免配额转发不计数、人手动下调过上限)是合法的 expect(screen.getByText('0/5')).toBeInTheDocument(); }); it('剩余为 0 时转红并标注「已用尽」', () => { render(React.createElement(BudgetChip, { max: 5, used: 5 })); const chip = screen.getByText('0/5').closest('span')!; expect(chip.className).toContain('bg-red-100'); expect(chip.getAttribute('title')).toContain('已用尽'); }); it('剩余 1 个时转橙 —— 那是需要人介入的时刻', () => { render(React.createElement(BudgetChip, { max: 20, used: 19 })); const chip = screen.getByText('1/20').closest('span')!; // 要么加预算,要么让它收尾;这一步不提示的话下一封信就被挡住了 expect(chip.className).toContain('bg-orange-100'); }); it('余量充足时用中性灰,不抢注意力', () => { render(React.createElement(BudgetChip, { max: 20, used: 2 })); const chip = screen.getByText('18/20').closest('span')!; expect(chip.className).toContain('bg-gray-100'); expect(chip.className).not.toContain('red'); expect(chip.className).not.toContain('orange'); }); it('title 里带已用/上限,供悬停查看细节', () => { render(React.createElement(BudgetChip, { max: 20, used: 7 })); const chip = screen.getByText('13/20').closest('span')!; // 徽标上只有剩余,具体用了几个放在 title 里 —— 徽标要窄 expect(chip.getAttribute('title')).toContain('已用 7/20'); }); it('剩余 2 个时还不转橙(阈值是 <= 1)', () => { render(React.createElement(BudgetChip, { max: 10, used: 8 })); const chip = screen.getByText('2/10').closest('span')!; expect(chip.className).toContain('bg-gray-100'); }); });