Files
ftdl/app/download/__tests__/ApkList.test.tsx
tech d1ad58b504 refactor: simplify apk filename parsing logic
- Simplify parseApkFilename to use version delimiter split
- Update tests to match new data structure with rawEnvironment
- Remove unnecessary test cases and assertions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 20:27:54 +08:00

125 lines
3.5 KiB
TypeScript

import React from 'react';
import { render, screen, fireEvent, waitFor, act } from '@testing-library/react';
import ApkList from '../ApkList';
import useSWR from 'swr';
jest.mock('swr');
// Mock fetch for config API
const mockFetch = jest.fn();
global.fetch = mockFetch;
describe('ApkList', () => {
const mockApks = [
{
name: 'ft_dev_0_42_57ef3a60d.apk',
environment: 'dev',
rawEnvironment: 'dev',
commit: '57ef3a60d',
size: 15728640,
modifiedAt: '2026-03-04T14:30:00.000Z',
downloadUrl: '/api/download?project=FT&version=0_42&filename=ft_dev_0_42_57ef3a60d.apk',
},
{
name: 'ft_0_42_ff9ff3441.apk',
environment: 'product',
rawEnvironment: 'product',
commit: 'ff9ff3441',
size: 15728640,
modifiedAt: '2026-03-04T14:30:00.000Z',
downloadUrl: '/api/download?project=FT&version=0_42&filename=ft_0_42_ff9ff3441.apk',
},
{
name: 'ft_sandbox_0_42_abc123456.apk',
environment: 'sandbox',
rawEnvironment: 'sandbox',
commit: 'abc123456',
size: 15728640,
modifiedAt: '2026-03-04T14:30:00.000Z',
downloadUrl: '/api/download?project=FT&version=0_42&filename=ft_sandbox_0_42_abc123456.apk',
},
{
name: 'ft_timeshift_0_42_xyz987654.apk',
environment: 'other',
rawEnvironment: 'timeshift',
commit: 'xyz987654',
size: 15728640,
modifiedAt: '2026-03-04T14:30:00.000Z',
downloadUrl: '/api/download?project=FT&version=0_42&filename=ft_timeshift_0_42_xyz987654.apk',
},
];
beforeEach(() => {
(useSWR as jest.Mock).mockReturnValue({
data: mockApks,
isLoading: false,
error: null,
});
// Mock config API response
mockFetch.mockResolvedValue({
json: () => Promise.resolve({ tabs: ['dev', 'sandbox'] }),
});
});
afterEach(() => {
mockFetch.mockClear();
});
it('should render all 4 tabs', async () => {
await act(async () => {
render(<ApkList project="FT" version="0_42" commitId="" />);
});
await waitFor(() => {
// Use getAllByText since text appears in both tab and badge
expect(screen.getAllByText(/dev/).length).toBeGreaterThan(0);
expect(screen.getAllByText(/product/).length).toBeGreaterThan(0);
expect(screen.getAllByText(/sandbox/).length).toBeGreaterThan(0);
expect(screen.getAllByText(/other/).length).toBeGreaterThan(0);
});
});
it('should switch tabs correctly', async () => {
await act(async () => {
render(<ApkList project="FT" version="0_42" commitId="" />);
});
await waitFor(() => {
expect(screen.getByText(/dev/)).toBeInTheDocument();
});
const devTab = screen.getByText(/dev/);
fireEvent.click(devTab);
expect(screen.getByText('57ef3a60d')).toBeInTheDocument();
});
it('should show loading state', async () => {
(useSWR as jest.Mock).mockReturnValue({
data: null,
isLoading: true,
error: null,
});
await act(async () => {
render(<ApkList project="FT" version="0_42" commitId="" />);
});
expect(screen.getByText('加载中...')).toBeInTheDocument();
});
it('should show error state', async () => {
(useSWR as jest.Mock).mockReturnValue({
data: null,
isLoading: false,
error: new Error('API error'),
});
await act(async () => {
render(<ApkList project="FT" version="0_42" commitId="" />);
});
expect(screen.getByText('加载失败,请重试')).toBeInTheDocument();
});
});