This commit is contained in:
beabigegg
2025-09-02 13:11:48 +08:00
parent a60d965317
commit b11a8272c4
76 changed files with 15321 additions and 200 deletions

266
tests/test_files_api.py Normal file
View File

@@ -0,0 +1,266 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
檔案管理 API 測試
Author: PANJIT IT Team
Created: 2024-01-28
Modified: 2024-01-28
"""
import pytest
import io
import json
from unittest.mock import patch, MagicMock
from app.models.job import TranslationJob
class TestFilesAPI:
"""檔案管理 API 測試類別"""
def test_upload_file_success(self, authenticated_client, auth_user):
"""測試成功上傳檔案"""
# 建立測試檔案
file_data = b'Mock DOCX file content'
file_obj = (io.BytesIO(file_data), 'test.docx')
with patch('app.utils.helpers.save_uploaded_file') as mock_save:
mock_save.return_value = {
'success': True,
'filename': 'original_test_12345678.docx',
'file_path': '/tmp/test_job_uuid/original_test_12345678.docx',
'file_size': len(file_data)
}
response = authenticated_client.post('/api/v1/files/upload', data={
'file': file_obj,
'source_language': 'auto',
'target_languages': json.dumps(['en', 'vi'])
})
assert response.status_code == 200
data = response.get_json()
assert data['success'] is True
assert 'job_uuid' in data['data']
assert data['data']['original_filename'] == 'test.docx'
def test_upload_file_no_file(self, authenticated_client):
"""測試未選擇檔案"""
response = authenticated_client.post('/api/v1/files/upload', data={
'source_language': 'auto',
'target_languages': json.dumps(['en'])
})
assert response.status_code == 400
data = response.get_json()
assert data['success'] is False
assert data['error'] == 'NO_FILE'
def test_upload_file_invalid_type(self, authenticated_client):
"""測試上傳無效檔案類型"""
file_data = b'Mock text file content'
file_obj = (io.BytesIO(file_data), 'test.txt')
response = authenticated_client.post('/api/v1/files/upload', data={
'file': file_obj,
'source_language': 'auto',
'target_languages': json.dumps(['en'])
})
assert response.status_code == 400
data = response.get_json()
assert data['success'] is False
assert data['error'] == 'INVALID_FILE_TYPE'
def test_upload_file_too_large(self, authenticated_client, app):
"""測試上傳過大檔案"""
# 建立超過限制的檔案26MB+
large_file_data = b'x' * (26 * 1024 * 1024 + 1)
file_obj = (io.BytesIO(large_file_data), 'large.docx')
response = authenticated_client.post('/api/v1/files/upload', data={
'file': file_obj,
'source_language': 'auto',
'target_languages': json.dumps(['en'])
})
assert response.status_code == 400
data = response.get_json()
assert data['success'] is False
assert data['error'] == 'FILE_TOO_LARGE'
def test_upload_file_invalid_target_languages(self, authenticated_client):
"""測試無效的目標語言"""
file_data = b'Mock DOCX file content'
file_obj = (io.BytesIO(file_data), 'test.docx')
response = authenticated_client.post('/api/v1/files/upload', data={
'file': file_obj,
'source_language': 'auto',
'target_languages': 'invalid_json'
})
assert response.status_code == 400
data = response.get_json()
assert data['success'] is False
assert data['error'] == 'INVALID_TARGET_LANGUAGES'
def test_upload_file_empty_target_languages(self, authenticated_client):
"""測試空的目標語言"""
file_data = b'Mock DOCX file content'
file_obj = (io.BytesIO(file_data), 'test.docx')
response = authenticated_client.post('/api/v1/files/upload', data={
'file': file_obj,
'source_language': 'auto',
'target_languages': json.dumps([])
})
assert response.status_code == 400
data = response.get_json()
assert data['success'] is False
assert data['error'] == 'NO_TARGET_LANGUAGES'
def test_upload_file_without_auth(self, client):
"""測試未認證上傳檔案"""
file_data = b'Mock DOCX file content'
file_obj = (io.BytesIO(file_data), 'test.docx')
response = client.post('/api/v1/files/upload', data={
'file': file_obj,
'source_language': 'auto',
'target_languages': json.dumps(['en'])
})
assert response.status_code == 401
data = response.get_json()
assert data['success'] is False
assert data['error'] == 'AUTHENTICATION_REQUIRED'
def test_download_translated_file_success(self, authenticated_client, sample_job, auth_user):
"""測試成功下載翻譯檔案"""
# 設定任務為已完成
sample_job.update_status('COMPLETED')
# 添加翻譯檔案記錄
sample_job.add_translated_file(
language_code='en',
filename='test_en_translated.docx',
file_path='/tmp/test_en_translated.docx',
file_size=1024
)
with patch('pathlib.Path.exists') as mock_exists, \
patch('flask.send_file') as mock_send_file:
mock_exists.return_value = True
mock_send_file.return_value = 'file_content'
response = authenticated_client.get(f'/api/v1/files/{sample_job.job_uuid}/download/en')
# send_file 被呼叫表示成功
mock_send_file.assert_called_once()
def test_download_file_not_found(self, authenticated_client, sample_job):
"""測試下載不存在的檔案"""
response = authenticated_client.get(f'/api/v1/files/nonexistent-uuid/download/en')
assert response.status_code == 404
data = response.get_json()
assert data['success'] is False
assert data['error'] == 'JOB_NOT_FOUND'
def test_download_file_permission_denied(self, authenticated_client, sample_job, 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='COMPLETED'
)
db.session.add(other_job)
db.session.commit()
response = authenticated_client.get(f'/api/v1/files/{other_job.job_uuid}/download/en')
assert response.status_code == 403
data = response.get_json()
assert data['success'] is False
assert data['error'] == 'PERMISSION_DENIED'
def test_download_file_not_completed(self, authenticated_client, sample_job):
"""測試下載未完成任務的檔案"""
response = authenticated_client.get(f'/api/v1/files/{sample_job.job_uuid}/download/en')
assert response.status_code == 400
data = response.get_json()
assert data['success'] is False
assert data['error'] == 'JOB_NOT_COMPLETED'
def test_download_original_file_success(self, authenticated_client, sample_job):
"""測試下載原始檔案"""
# 添加原始檔案記錄
sample_job.add_original_file(
filename='original_test.docx',
file_path='/tmp/original_test.docx',
file_size=1024
)
with patch('pathlib.Path.exists') as mock_exists, \
patch('flask.send_file') as mock_send_file:
mock_exists.return_value = True
mock_send_file.return_value = 'file_content'
response = authenticated_client.get(f'/api/v1/files/{sample_job.job_uuid}/download/original')
mock_send_file.assert_called_once()
def test_get_supported_formats(self, client):
"""測試取得支援的檔案格式"""
response = client.get('/api/v1/files/supported-formats')
assert response.status_code == 200
data = response.get_json()
assert data['success'] is True
assert 'supported_formats' in data['data']
assert 'max_file_size' in data['data']
# 檢查是否包含基本格式
formats = data['data']['supported_formats']
assert '.docx' in formats
assert '.pdf' in formats
def test_get_supported_languages(self, client):
"""測試取得支援的語言"""
response = client.get('/api/v1/files/supported-languages')
assert response.status_code == 200
data = response.get_json()
assert data['success'] is True
assert 'supported_languages' in data['data']
# 檢查是否包含基本語言
languages = data['data']['supported_languages']
assert 'en' in languages
assert 'zh-TW' in languages
assert 'auto' in languages