#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 任務管理 API 測試 Author: PANJIT IT Team Created: 2024-01-28 Modified: 2024-01-28 """ import pytest from app.models.job import TranslationJob class TestJobsAPI: """任務管理 API 測試類別""" def test_get_user_jobs_success(self, authenticated_client, sample_job): """測試取得使用者任務列表""" response = authenticated_client.get('/api/v1/jobs') assert response.status_code == 200 data = response.get_json() assert data['success'] is True assert 'jobs' in data['data'] assert 'pagination' in data['data'] assert len(data['data']['jobs']) > 0 def test_get_user_jobs_with_status_filter(self, authenticated_client, sample_job): """測試按狀態篩選任務""" response = authenticated_client.get('/api/v1/jobs?status=PENDING') assert response.status_code == 200 data = response.get_json() assert data['success'] is True # 所有返回的任務都應該是 PENDING 狀態 for job in data['data']['jobs']: assert job['status'] == 'PENDING' def test_get_user_jobs_with_pagination(self, authenticated_client, sample_job): """測試分頁""" response = authenticated_client.get('/api/v1/jobs?page=1&per_page=5') assert response.status_code == 200 data = response.get_json() assert data['success'] is True assert data['data']['pagination']['page'] == 1 assert data['data']['pagination']['per_page'] == 5 def test_get_user_jobs_without_auth(self, client): """測試未認證取得任務列表""" response = client.get('/api/v1/jobs') assert response.status_code == 401 data = response.get_json() assert data['success'] is False assert data['error'] == 'AUTHENTICATION_REQUIRED' def test_get_job_detail_success(self, authenticated_client, sample_job): """測試取得任務詳細資訊""" response = authenticated_client.get(f'/api/v1/jobs/{sample_job.job_uuid}') assert response.status_code == 200 data = response.get_json() assert data['success'] is True assert 'job' in data['data'] assert data['data']['job']['job_uuid'] == sample_job.job_uuid def test_get_job_detail_not_found(self, authenticated_client): """測試取得不存在的任務""" fake_uuid = '00000000-0000-0000-0000-000000000000' response = authenticated_client.get(f'/api/v1/jobs/{fake_uuid}') assert response.status_code == 404 data = response.get_json() assert data['success'] is False assert data['error'] == 'JOB_NOT_FOUND' def test_get_job_detail_invalid_uuid(self, authenticated_client): """測試無效的UUID格式""" invalid_uuid = 'invalid-uuid' response = authenticated_client.get(f'/api/v1/jobs/{invalid_uuid}') assert response.status_code == 400 data = response.get_json() assert data['success'] is False assert data['error'] == 'INVALID_UUID' def test_get_job_detail_permission_denied(self, authenticated_client, app): """測試存取他人任務""" from app.models.user import User from app import db with app.app_context(): # 建立另一個使用者和任務 other_user = User( username='otheruser', display_name='Other User', email='other@panjit.com.tw', department='IT', is_admin=False ) db.session.add(other_user) db.session.commit() other_job = TranslationJob( user_id=other_user.id, original_filename='other.docx', file_extension='.docx', file_size=1024, file_path='/tmp/other.docx', source_language='auto', target_languages=['en'], status='PENDING' ) db.session.add(other_job) db.session.commit() response = authenticated_client.get(f'/api/v1/jobs/{other_job.job_uuid}') assert response.status_code == 403 data = response.get_json() assert data['success'] is False assert data['error'] == 'PERMISSION_DENIED' def test_retry_job_success(self, authenticated_client, sample_job): """測試重試失敗任務""" # 設定任務為失敗狀態 sample_job.update_status('FAILED', error_message='Test error') response = authenticated_client.post(f'/api/v1/jobs/{sample_job.job_uuid}/retry') assert response.status_code == 200 data = response.get_json() assert data['success'] is True assert data['data']['status'] == 'PENDING' assert data['data']['retry_count'] == 1 def test_retry_job_cannot_retry(self, authenticated_client, sample_job): """測試無法重試的任務""" # 設定任務為完成狀態 sample_job.update_status('COMPLETED') response = authenticated_client.post(f'/api/v1/jobs/{sample_job.job_uuid}/retry') assert response.status_code == 400 data = response.get_json() assert data['success'] is False assert data['error'] == 'CANNOT_RETRY' def test_retry_job_max_retries(self, authenticated_client, sample_job): """測試達到最大重試次數""" # 設定任務為失敗且重試次數已達上限 sample_job.update_status('FAILED', error_message='Test error') sample_job.retry_count = 3 from app import db db.session.commit() response = authenticated_client.post(f'/api/v1/jobs/{sample_job.job_uuid}/retry') assert response.status_code == 400 data = response.get_json() assert data['success'] is False assert data['error'] == 'CANNOT_RETRY' def test_get_user_statistics(self, authenticated_client, sample_job): """測試取得使用者統計資料""" response = authenticated_client.get('/api/v1/jobs/statistics') assert response.status_code == 200 data = response.get_json() assert data['success'] is True assert 'job_statistics' in data['data'] assert 'api_statistics' in data['data'] def test_get_user_statistics_with_date_range(self, authenticated_client): """測試指定日期範圍的統計""" response = authenticated_client.get('/api/v1/jobs/statistics?start_date=2024-01-01T00:00:00Z&end_date=2024-12-31T23:59:59Z') assert response.status_code == 200 data = response.get_json() assert data['success'] is True def test_get_user_statistics_invalid_date(self, authenticated_client): """測試無效的日期格式""" response = authenticated_client.get('/api/v1/jobs/statistics?start_date=invalid-date') assert response.status_code == 400 data = response.get_json() assert data['success'] is False assert data['error'] == 'INVALID_START_DATE' def test_get_queue_status(self, client, sample_job): """測試取得佇列狀態(不需認證)""" response = client.get('/api/v1/jobs/queue/status') assert response.status_code == 200 data = response.get_json() assert data['success'] is True assert 'queue_status' in data['data'] assert 'processing_jobs' in data['data'] def test_cancel_job_success(self, authenticated_client, sample_job): """測試取消等待中的任務""" # 確保任務是 PENDING 狀態 assert sample_job.status == 'PENDING' response = authenticated_client.post(f'/api/v1/jobs/{sample_job.job_uuid}/cancel') assert response.status_code == 200 data = response.get_json() assert data['success'] is True assert data['data']['status'] == 'FAILED' def test_cancel_job_cannot_cancel(self, authenticated_client, sample_job): """測試取消非等待狀態的任務""" # 設定任務為處理中 sample_job.update_status('PROCESSING') response = authenticated_client.post(f'/api/v1/jobs/{sample_job.job_uuid}/cancel') assert response.status_code == 400 data = response.get_json() assert data['success'] is False assert data['error'] == 'CANNOT_CANCEL' def test_cancel_job_not_found(self, authenticated_client): """測試取消不存在的任務""" fake_uuid = '00000000-0000-0000-0000-000000000000' response = authenticated_client.post(f'/api/v1/jobs/{fake_uuid}/cancel') assert response.status_code == 404 data = response.get_json() assert data['success'] is False assert data['error'] == 'JOB_NOT_FOUND'