181 lines
4.8 KiB
TypeScript
181 lines
4.8 KiB
TypeScript
import { describe, it, expect, vi, beforeEach } from 'vitest'
|
|
import { render, screen, fireEvent } from '@testing-library/react'
|
|
import { ProgressTracker } from '../ProgressTracker'
|
|
|
|
describe('ProgressTracker', () => {
|
|
const mockOnShowTaskList = vi.fn()
|
|
|
|
beforeEach(() => {
|
|
vi.clearAllMocks()
|
|
})
|
|
|
|
describe('基礎渲染', () => {
|
|
it('應該正確顯示進度文字', () => {
|
|
render(
|
|
<ProgressTracker
|
|
completedTests={3}
|
|
totalTests={10}
|
|
onShowTaskList={mockOnShowTaskList}
|
|
/>
|
|
)
|
|
|
|
expect(screen.getByText('學習進度')).toBeInTheDocument()
|
|
expect(screen.getByText('測驗: 3/10')).toBeInTheDocument()
|
|
})
|
|
|
|
it('應該在沒有測驗時顯示 0/0', () => {
|
|
render(
|
|
<ProgressTracker
|
|
completedTests={0}
|
|
totalTests={0}
|
|
onShowTaskList={mockOnShowTaskList}
|
|
/>
|
|
)
|
|
|
|
expect(screen.getByText('測驗: 0/0')).toBeInTheDocument()
|
|
})
|
|
})
|
|
|
|
describe('進度百分比計算', () => {
|
|
it('應該正確計算進度百分比', () => {
|
|
render(
|
|
<ProgressTracker
|
|
completedTests={5}
|
|
totalTests={10}
|
|
onShowTaskList={mockOnShowTaskList}
|
|
/>
|
|
)
|
|
|
|
// 檢查進度條寬度 (50%) - 使用實際的 div 元素
|
|
const progressBar = document.querySelector('.bg-blue-500')
|
|
expect(progressBar).toHaveStyle({ width: '50%' })
|
|
})
|
|
|
|
it('應該處理 100% 完成的情況', () => {
|
|
render(
|
|
<ProgressTracker
|
|
completedTests={10}
|
|
totalTests={10}
|
|
onShowTaskList={mockOnShowTaskList}
|
|
/>
|
|
)
|
|
|
|
const progressBar = document.querySelector('.bg-blue-500')
|
|
expect(progressBar).toHaveStyle({ width: '100%' })
|
|
})
|
|
|
|
it('應該處理 0% 完成的情況', () => {
|
|
render(
|
|
<ProgressTracker
|
|
completedTests={0}
|
|
totalTests={5}
|
|
onShowTaskList={mockOnShowTaskList}
|
|
/>
|
|
)
|
|
|
|
const progressBar = document.querySelector('.bg-blue-500')
|
|
expect(progressBar).toHaveStyle({ width: '0%' })
|
|
})
|
|
|
|
it('應該處理除零情況 (totalTests = 0)', () => {
|
|
render(
|
|
<ProgressTracker
|
|
completedTests={0}
|
|
totalTests={0}
|
|
onShowTaskList={mockOnShowTaskList}
|
|
/>
|
|
)
|
|
|
|
const progressBar = document.querySelector('.bg-blue-500')
|
|
expect(progressBar).toHaveStyle({ width: '0%' })
|
|
})
|
|
})
|
|
|
|
describe('交互功能', () => {
|
|
it('應該在點擊按鈕時調用 onShowTaskList', () => {
|
|
render(
|
|
<ProgressTracker
|
|
completedTests={3}
|
|
totalTests={10}
|
|
onShowTaskList={mockOnShowTaskList}
|
|
/>
|
|
)
|
|
|
|
const button = screen.getByText('測驗: 3/10')
|
|
fireEvent.click(button)
|
|
|
|
expect(mockOnShowTaskList).toHaveBeenCalledTimes(1)
|
|
})
|
|
|
|
it('應該在點擊進度條時也調用 onShowTaskList', () => {
|
|
render(
|
|
<ProgressTracker
|
|
completedTests={5}
|
|
totalTests={10}
|
|
onShowTaskList={mockOnShowTaskList}
|
|
/>
|
|
)
|
|
|
|
const progressBarContainer = document.querySelector('.cursor-pointer.hover\\:bg-gray-300')
|
|
fireEvent.click(progressBarContainer!)
|
|
|
|
expect(mockOnShowTaskList).toHaveBeenCalledTimes(1)
|
|
})
|
|
})
|
|
|
|
describe('邊界值測試', () => {
|
|
it('應該處理負數輸入', () => {
|
|
render(
|
|
<ProgressTracker
|
|
completedTests={-1}
|
|
totalTests={5}
|
|
onShowTaskList={mockOnShowTaskList}
|
|
/>
|
|
)
|
|
|
|
expect(screen.getByText('測驗: -1/5')).toBeInTheDocument()
|
|
})
|
|
|
|
it('應該處理 completedTests > totalTests 的情況', () => {
|
|
render(
|
|
<ProgressTracker
|
|
completedTests={15}
|
|
totalTests={10}
|
|
onShowTaskList={mockOnShowTaskList}
|
|
/>
|
|
)
|
|
|
|
expect(screen.getByText('測驗: 15/10')).toBeInTheDocument()
|
|
const progressBar = document.querySelector('.bg-blue-500')
|
|
expect(progressBar).toHaveStyle({ width: '150%' })
|
|
})
|
|
})
|
|
|
|
describe('可訪問性', () => {
|
|
it('應該有正確的 aria 屬性', () => {
|
|
render(
|
|
<ProgressTracker
|
|
completedTests={3}
|
|
totalTests={10}
|
|
onShowTaskList={mockOnShowTaskList}
|
|
/>
|
|
)
|
|
|
|
const button = screen.getByRole('button')
|
|
expect(button).toHaveAttribute('title', '點擊查看詳細進度')
|
|
})
|
|
|
|
it('應該有正確的進度條元素', () => {
|
|
render(
|
|
<ProgressTracker
|
|
completedTests={5}
|
|
totalTests={10}
|
|
onShowTaskList={mockOnShowTaskList}
|
|
/>
|
|
)
|
|
|
|
const progressBar = document.querySelector('.bg-blue-500')
|
|
expect(progressBar).toBeInTheDocument()
|
|
})
|
|
})
|
|
}) |