Files
Document_Translator/tests/test_files_api.py
beabigegg b11a8272c4 2ND
2025-09-02 13:11:48 +08:00

266 lines
9.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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