Files
gh-christianlouis-docuelevate/tests/test_send_to_all.py
T
copilot-swe-agent[bot] a08b103271 fix: merge main into feature branch - resolve all merge conflicts cleanly
Merges origin/main (v0.156.0) into the classification feature branch,
properly resolving all 23 merge conflicts:

- Auto-generated files (BUILD_DATE, VERSION, etc.): accept main's version
- Non-classification files (SharePoint, QR auth, session mgmt, mobile): accept main's version
- Classification files (api/__init__.py, models.py, migrations/env.py, conftest.py):
  keep classification additions alongside main's content

Previously the branch was incorrectly removing files from main (SharePoint
integration, QR scanner, session management). This merge properly preserves
all main branch content while maintaining the classification feature additions.

Migration chain validated: 038_add_classification_rules chains from
037_add_user_sessions_and_qr_challenges.

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-03-17 16:14:45 +00:00

907 lines
36 KiB
Python

"""Tests for app/tasks/send_to_all.py module."""
from unittest.mock import MagicMock, patch
import pytest
from app.tasks.send_to_all import (
_should_upload_to_dropbox,
_should_upload_to_email,
_should_upload_to_ftp,
_should_upload_to_google_drive,
_should_upload_to_icloud,
_should_upload_to_nextcloud,
_should_upload_to_onedrive,
_should_upload_to_paperless,
_should_upload_to_s3,
_should_upload_to_sftp,
_should_upload_to_webdav,
get_configured_services_from_validator,
send_to_all_destinations,
)
@pytest.mark.unit
class TestShouldUploadFunctions:
"""Test the _should_upload_to_* helper functions."""
@patch("app.tasks.send_to_all.settings")
def test_should_upload_to_dropbox_all_configured(self, mock_settings):
"""Test Dropbox upload check when all credentials are configured."""
mock_settings.dropbox_app_key = "key"
mock_settings.dropbox_app_secret = "secret"
mock_settings.dropbox_refresh_token = "token"
assert _should_upload_to_dropbox() is True
@patch("app.tasks.send_to_all.settings")
def test_should_upload_to_dropbox_missing_credentials(self, mock_settings):
"""Test Dropbox upload check when credentials are missing."""
mock_settings.dropbox_app_key = None
mock_settings.dropbox_app_secret = None
mock_settings.dropbox_refresh_token = None
assert _should_upload_to_dropbox() is False
@patch("app.tasks.send_to_all.settings")
def test_should_upload_to_nextcloud_configured(self, mock_settings):
"""Test Nextcloud upload check."""
mock_settings.nextcloud_upload_url = "https://nextcloud.example.com"
mock_settings.nextcloud_username = "user"
mock_settings.nextcloud_password = "pass"
assert _should_upload_to_nextcloud() is True
@patch("app.tasks.send_to_all.settings")
def test_should_upload_to_paperless_configured(self, mock_settings):
"""Test Paperless upload check."""
mock_settings.paperless_ngx_api_token = "token"
mock_settings.paperless_host = "https://paperless.example.com"
assert _should_upload_to_paperless() is True
@patch("app.tasks.send_to_all.settings")
def test_should_upload_to_google_drive_oauth(self, mock_settings):
"""Test Google Drive upload check with OAuth."""
mock_settings.google_drive_use_oauth = True
mock_settings.google_drive_client_id = "client_id"
mock_settings.google_drive_client_secret = "client_secret"
mock_settings.google_drive_refresh_token = "refresh_token"
mock_settings.google_drive_folder_id = "folder_id"
assert _should_upload_to_google_drive() is True
@patch("app.tasks.send_to_all.settings")
def test_should_upload_to_google_drive_service_account(self, mock_settings):
"""Test Google Drive upload check with service account."""
mock_settings.google_drive_use_oauth = False
mock_settings.google_drive_credentials_json = '{"type": "service_account"}'
mock_settings.google_drive_folder_id = "folder_id"
assert _should_upload_to_google_drive() is True
@patch("app.tasks.send_to_all.settings")
def test_should_upload_to_webdav_configured(self, mock_settings):
"""Test WebDAV upload check."""
mock_settings.webdav_url = "https://webdav.example.com"
mock_settings.webdav_username = "user"
mock_settings.webdav_password = "pass"
assert _should_upload_to_webdav() is True
@patch("app.tasks.send_to_all.settings")
def test_should_upload_to_ftp_configured(self, mock_settings):
"""Test FTP upload check."""
mock_settings.ftp_host = "ftp.example.com"
mock_settings.ftp_username = "user"
mock_settings.ftp_password = "pass"
assert _should_upload_to_ftp() is True
@patch("app.tasks.send_to_all.settings")
def test_should_upload_to_sftp_with_password(self, mock_settings):
"""Test SFTP upload check with password auth."""
mock_settings.sftp_host = "sftp.example.com"
mock_settings.sftp_username = "user"
mock_settings.sftp_password = "pass"
mock_settings.sftp_private_key = None
assert _should_upload_to_sftp() is True
@patch("app.tasks.send_to_all.settings")
def test_should_upload_to_sftp_with_key(self, mock_settings):
"""Test SFTP upload check with key auth."""
mock_settings.sftp_host = "sftp.example.com"
mock_settings.sftp_username = "user"
mock_settings.sftp_password = None
mock_settings.sftp_private_key = "/path/to/key"
assert _should_upload_to_sftp() is True
@patch("app.tasks.send_to_all.settings")
def test_should_upload_to_email_configured(self, mock_settings):
"""Test email upload check."""
mock_settings.dest_email_host = "smtp.example.com"
mock_settings.dest_email_username = "user"
mock_settings.dest_email_password = "pass"
mock_settings.dest_email_default_recipient = "recipient@example.com"
assert _should_upload_to_email() is True
@patch("app.tasks.send_to_all.settings")
def test_should_upload_to_onedrive_configured(self, mock_settings):
"""Test OneDrive upload check."""
mock_settings.onedrive_client_id = "client_id"
mock_settings.onedrive_client_secret = "client_secret"
mock_settings.onedrive_refresh_token = "refresh_token"
assert _should_upload_to_onedrive() is True
@patch("app.tasks.send_to_all.settings")
def test_should_upload_to_s3_configured(self, mock_settings):
"""Test S3 upload check."""
mock_settings.s3_bucket_name = "my-bucket"
mock_settings.aws_access_key_id = "key_id"
mock_settings.aws_secret_access_key = "secret_key"
assert _should_upload_to_s3() is True
@patch("app.tasks.send_to_all.settings")
def test_should_upload_to_icloud_configured(self, mock_settings):
"""Test iCloud upload check."""
mock_settings.icloud_username = "user@example.com"
mock_settings.icloud_password = "app-specific-password"
assert _should_upload_to_icloud() is True
@patch("app.tasks.send_to_all.settings")
def test_should_upload_to_icloud_not_configured(self, mock_settings):
"""Test iCloud upload check when not configured."""
mock_settings.icloud_username = None
mock_settings.icloud_password = None
assert _should_upload_to_icloud() is False
@pytest.mark.unit
class TestShouldUploadEnabledFlag:
"""Test that the _should_upload_to_* functions respect the explicit enabled flag."""
@patch("app.tasks.send_to_all.settings")
def test_dropbox_disabled_with_credentials(self, mock_settings):
"""Test Dropbox upload is blocked when disabled even with valid credentials."""
mock_settings.dropbox_enabled = False
mock_settings.dropbox_app_key = "key"
mock_settings.dropbox_app_secret = "secret"
mock_settings.dropbox_refresh_token = "token"
assert _should_upload_to_dropbox() is False
@patch("app.tasks.send_to_all.settings")
def test_nextcloud_disabled_with_credentials(self, mock_settings):
"""Test Nextcloud upload is blocked when disabled even with valid credentials."""
mock_settings.nextcloud_enabled = False
mock_settings.nextcloud_upload_url = "https://nextcloud.example.com"
mock_settings.nextcloud_username = "user"
mock_settings.nextcloud_password = "pass"
assert _should_upload_to_nextcloud() is False
@patch("app.tasks.send_to_all.settings")
def test_paperless_disabled_with_credentials(self, mock_settings):
"""Test Paperless upload is blocked when disabled even with valid credentials."""
mock_settings.paperless_enabled = False
mock_settings.paperless_ngx_api_token = "token"
mock_settings.paperless_host = "https://paperless.example.com"
assert _should_upload_to_paperless() is False
@patch("app.tasks.send_to_all.settings")
def test_google_drive_disabled_with_credentials(self, mock_settings):
"""Test Google Drive upload is blocked when disabled even with valid credentials."""
mock_settings.google_drive_enabled = False
mock_settings.google_drive_use_oauth = False
mock_settings.google_drive_credentials_json = '{"type": "service_account"}'
mock_settings.google_drive_folder_id = "folder_id"
assert _should_upload_to_google_drive() is False
@patch("app.tasks.send_to_all.settings")
def test_webdav_disabled_with_credentials(self, mock_settings):
"""Test WebDAV upload is blocked when disabled even with valid credentials."""
mock_settings.webdav_enabled = False
mock_settings.webdav_url = "https://webdav.example.com"
mock_settings.webdav_username = "user"
mock_settings.webdav_password = "pass"
assert _should_upload_to_webdav() is False
@patch("app.tasks.send_to_all.settings")
def test_ftp_disabled_with_credentials(self, mock_settings):
"""Test FTP upload is blocked when disabled even with valid credentials."""
mock_settings.ftp_enabled = False
mock_settings.ftp_host = "ftp.example.com"
mock_settings.ftp_username = "user"
mock_settings.ftp_password = "pass"
assert _should_upload_to_ftp() is False
@patch("app.tasks.send_to_all.settings")
def test_sftp_disabled_with_credentials(self, mock_settings):
"""Test SFTP upload is blocked when disabled even with valid credentials."""
mock_settings.sftp_enabled = False
mock_settings.sftp_host = "sftp.example.com"
mock_settings.sftp_username = "user"
mock_settings.sftp_password = "pass"
mock_settings.sftp_private_key = None
assert _should_upload_to_sftp() is False
@patch("app.tasks.send_to_all.settings")
def test_email_disabled_with_credentials(self, mock_settings):
"""Test email upload is blocked when disabled even with valid credentials."""
mock_settings.dest_email_enabled = False
mock_settings.dest_email_host = "smtp.example.com"
mock_settings.dest_email_username = "user"
mock_settings.dest_email_password = "pass"
mock_settings.dest_email_default_recipient = "recipient@example.com"
assert _should_upload_to_email() is False
@patch("app.tasks.send_to_all.settings")
def test_onedrive_disabled_with_credentials(self, mock_settings):
"""Test OneDrive upload is blocked when disabled even with valid credentials."""
mock_settings.onedrive_enabled = False
mock_settings.onedrive_client_id = "client_id"
mock_settings.onedrive_client_secret = "client_secret"
mock_settings.onedrive_refresh_token = "refresh_token"
assert _should_upload_to_onedrive() is False
@patch("app.tasks.send_to_all.settings")
def test_s3_disabled_with_credentials(self, mock_settings):
"""Test S3 upload is blocked when disabled even with valid credentials."""
mock_settings.s3_enabled = False
mock_settings.s3_bucket_name = "my-bucket"
mock_settings.aws_access_key_id = "key_id"
mock_settings.aws_secret_access_key = "secret_key"
assert _should_upload_to_s3() is False
@patch("app.tasks.send_to_all.settings")
def test_icloud_disabled_with_credentials(self, mock_settings):
"""Test iCloud upload is blocked when disabled even with valid credentials."""
mock_settings.icloud_enabled = False
mock_settings.icloud_username = "user@example.com"
mock_settings.icloud_password = "app-specific-password"
assert _should_upload_to_icloud() is False
@pytest.mark.unit
class TestGetConfiguredServicesFromValidator:
"""Test get_configured_services_from_validator function."""
@patch("app.tasks.send_to_all.get_provider_status")
def test_returns_configured_services(self, mock_get_status):
"""Test that configured services are returned correctly."""
mock_get_status.return_value = {
"Dropbox": {"configured": True, "enabled": True},
"NextCloud": {"configured": False, "enabled": True},
"S3 Storage": {"configured": True, "enabled": True},
}
result = get_configured_services_from_validator()
assert result["dropbox"] is True
assert result["nextcloud"] is False
assert result["s3"] is True
@patch("app.tasks.send_to_all.get_provider_status")
def test_handles_missing_providers(self, mock_get_status):
"""Test handling when some providers are not in status."""
mock_get_status.return_value = {
"Dropbox": {"configured": True, "enabled": True},
}
result = get_configured_services_from_validator()
assert result["dropbox"] is True
# Other services not in result
@patch("app.tasks.send_to_all.get_provider_status")
def test_configured_but_disabled_service_not_active(self, mock_get_status):
"""Test that a configured but disabled service is not returned as active."""
mock_get_status.return_value = {
"Dropbox": {"configured": True, "enabled": False},
"S3 Storage": {"configured": True, "enabled": True},
}
result = get_configured_services_from_validator()
assert result["dropbox"] is False
assert result["s3"] is True
@patch("app.tasks.send_to_all.get_provider_status")
def test_missing_enabled_field_defaults_to_true_for_backward_compatibility(self, mock_get_status):
"""Test that missing 'enabled' key defaults to True (backward compatible)."""
mock_get_status.return_value = {
"Dropbox": {"configured": True},
}
result = get_configured_services_from_validator()
assert result["dropbox"] is True
@pytest.mark.unit
class TestSendToAllDestinations:
"""Test send_to_all_destinations task."""
@patch("app.tasks.send_to_all.log_task_progress")
def test_file_not_found_error(self, mock_log):
"""Test that FileNotFoundError is raised when file doesn't exist."""
result = send_to_all_destinations.apply(args=["/nonexistent/file.pdf"])
# When task raises an exception, result.failed() returns True
assert result.failed()
# The exception should be FileNotFoundError
assert isinstance(result.result, FileNotFoundError)
@patch("app.tasks.send_to_all.SessionLocal")
@patch("app.tasks.send_to_all.log_task_progress")
@patch("app.tasks.send_to_all.settings")
@patch("app.tasks.send_to_all._should_upload_to_dropbox")
@patch("app.tasks.send_to_all._should_upload_to_nextcloud")
@patch("app.tasks.send_to_all._should_upload_to_paperless")
@patch("app.tasks.send_to_all._should_upload_to_google_drive")
@patch("app.tasks.send_to_all._should_upload_to_webdav")
@patch("app.tasks.send_to_all._should_upload_to_ftp")
@patch("app.tasks.send_to_all._should_upload_to_sftp")
@patch("app.tasks.send_to_all._should_upload_to_email")
@patch("app.tasks.send_to_all._should_upload_to_onedrive")
@patch("app.tasks.send_to_all._should_upload_to_sharepoint")
@patch("app.tasks.send_to_all._should_upload_to_icloud")
@patch("app.tasks.send_to_all._should_upload_to_s3")
@patch("app.tasks.send_to_all.upload_to_dropbox")
def test_queues_single_configured_service(
self,
mock_upload,
mock_s3,
mock_icloud,
mock_sharepoint,
mock_onedrive,
mock_email,
mock_sftp,
mock_ftp,
mock_webdav,
mock_google,
mock_paperless,
mock_nextcloud,
mock_should,
mock_settings,
mock_log,
mock_session_local,
tmp_path,
):
"""Test queueing upload to a single configured service."""
test_file = tmp_path / "test.pdf"
test_file.write_text("test")
mock_should.return_value = True
# Mock all other services to return False
mock_nextcloud.return_value = False
mock_paperless.return_value = False
mock_google.return_value = False
mock_webdav.return_value = False
mock_ftp.return_value = False
mock_sftp.return_value = False
mock_email.return_value = False
mock_onedrive.return_value = False
mock_s3.return_value = False
mock_sharepoint.return_value = False
mock_icloud.return_value = False
mock_upload.delay.return_value = MagicMock(id="task-123")
result = send_to_all_destinations.apply(args=[str(test_file), False, 1])
assert result.result["status"] == "Queued"
mock_upload.delay.assert_called_once()
@patch("app.tasks.send_to_all.SessionLocal")
@patch("app.tasks.send_to_all.log_task_progress")
@patch("app.tasks.send_to_all.settings")
@patch("app.tasks.send_to_all._should_upload_to_dropbox")
@patch("app.tasks.send_to_all._should_upload_to_icloud")
@patch("app.tasks.send_to_all._should_upload_to_sharepoint")
@patch("app.tasks.send_to_all._should_upload_to_s3")
@patch("app.tasks.send_to_all._should_upload_to_nextcloud")
@patch("app.tasks.send_to_all._should_upload_to_paperless")
@patch("app.tasks.send_to_all._should_upload_to_google_drive")
@patch("app.tasks.send_to_all._should_upload_to_webdav")
@patch("app.tasks.send_to_all._should_upload_to_ftp")
@patch("app.tasks.send_to_all._should_upload_to_sftp")
@patch("app.tasks.send_to_all._should_upload_to_email")
@patch("app.tasks.send_to_all._should_upload_to_onedrive")
@patch("app.tasks.send_to_all.upload_to_dropbox")
@patch("app.tasks.send_to_all.upload_to_s3")
def test_queues_multiple_services(
self,
mock_s3_upload,
mock_dropbox_upload,
mock_onedrive,
mock_email,
mock_sftp,
mock_ftp,
mock_webdav,
mock_google,
mock_paperless,
mock_nextcloud,
mock_should_s3,
mock_sharepoint,
mock_icloud,
mock_should_dropbox,
mock_settings,
mock_log,
mock_session_local,
tmp_path,
):
"""Test queueing uploads to multiple services."""
test_file = tmp_path / "test.pdf"
test_file.write_text("test")
mock_should_dropbox.return_value = True
mock_should_s3.return_value = True
# Mock all other services to return False
mock_nextcloud.return_value = False
mock_paperless.return_value = False
mock_google.return_value = False
mock_webdav.return_value = False
mock_ftp.return_value = False
mock_sftp.return_value = False
mock_email.return_value = False
mock_onedrive.return_value = False
mock_sharepoint.return_value = False
mock_icloud.return_value = False
mock_dropbox_upload.delay.return_value = MagicMock(id="dropbox-task")
mock_s3_upload.delay.return_value = MagicMock(id="s3-task")
result = send_to_all_destinations.apply(args=[str(test_file), False, 1])
assert result.result["status"] == "Queued"
mock_dropbox_upload.delay.assert_called_once()
mock_s3_upload.delay.assert_called_once()
@patch("app.tasks.send_to_all.SessionLocal")
@patch("app.tasks.send_to_all.log_task_progress")
@patch("app.tasks.send_to_all.settings")
@patch("app.tasks.send_to_all._should_upload_to_dropbox")
@patch("app.tasks.send_to_all._should_upload_to_nextcloud")
@patch("app.tasks.send_to_all._should_upload_to_paperless")
@patch("app.tasks.send_to_all._should_upload_to_google_drive")
@patch("app.tasks.send_to_all._should_upload_to_webdav")
@patch("app.tasks.send_to_all._should_upload_to_ftp")
@patch("app.tasks.send_to_all._should_upload_to_sftp")
@patch("app.tasks.send_to_all._should_upload_to_email")
@patch("app.tasks.send_to_all._should_upload_to_onedrive")
@patch("app.tasks.send_to_all._should_upload_to_sharepoint")
@patch("app.tasks.send_to_all._should_upload_to_icloud")
@patch("app.tasks.send_to_all._should_upload_to_s3")
def test_skips_unconfigured_services(
self,
mock_s3,
mock_icloud,
mock_sharepoint,
mock_onedrive,
mock_email,
mock_sftp,
mock_ftp,
mock_webdav,
mock_google,
mock_paperless,
mock_nextcloud,
mock_should,
mock_settings,
mock_log,
mock_session_local,
tmp_path,
):
"""Test that unconfigured services are skipped."""
test_file = tmp_path / "test.pdf"
test_file.write_text("test")
# Set all _should_upload_* functions to return False
mock_should.return_value = False
mock_nextcloud.return_value = False
mock_paperless.return_value = False
mock_google.return_value = False
mock_webdav.return_value = False
mock_ftp.return_value = False
mock_sftp.return_value = False
mock_email.return_value = False
mock_onedrive.return_value = False
mock_s3.return_value = False
mock_sharepoint.return_value = False
mock_icloud.return_value = False
result = send_to_all_destinations.apply(args=[str(test_file), False, 1])
# No uploads should be queued
assert result.result["status"] == "Queued"
# Check that message indicates 0 uploads
assert "0 upload" in result.result["tasks"] or len(result.result["tasks"]) == 0
@patch("app.tasks.send_to_all.log_task_progress")
@patch("app.tasks.send_to_all.SessionLocal")
@patch("app.tasks.send_to_all.settings")
@patch("app.tasks.send_to_all._should_upload_to_dropbox")
@patch("app.tasks.send_to_all._should_upload_to_nextcloud")
@patch("app.tasks.send_to_all._should_upload_to_paperless")
@patch("app.tasks.send_to_all._should_upload_to_google_drive")
@patch("app.tasks.send_to_all._should_upload_to_webdav")
@patch("app.tasks.send_to_all._should_upload_to_ftp")
@patch("app.tasks.send_to_all._should_upload_to_sftp")
@patch("app.tasks.send_to_all._should_upload_to_email")
@patch("app.tasks.send_to_all._should_upload_to_onedrive")
@patch("app.tasks.send_to_all._should_upload_to_sharepoint")
@patch("app.tasks.send_to_all._should_upload_to_icloud")
@patch("app.tasks.send_to_all._should_upload_to_s3")
@patch("app.tasks.send_to_all.upload_to_dropbox")
def test_with_file_id_parameter(
self,
mock_upload,
mock_s3,
mock_icloud,
mock_sharepoint,
mock_onedrive,
mock_email,
mock_sftp,
mock_ftp,
mock_webdav,
mock_google,
mock_paperless,
mock_nextcloud,
mock_should,
mock_settings,
mock_session_local,
mock_log,
tmp_path,
):
"""Test send_to_all with explicit file_id parameter."""
test_file = tmp_path / "test.pdf"
test_file.write_text("test")
mock_should.return_value = True
# Mock all other services to return False
mock_nextcloud.return_value = False
mock_paperless.return_value = False
mock_google.return_value = False
mock_webdav.return_value = False
mock_ftp.return_value = False
mock_sftp.return_value = False
mock_email.return_value = False
mock_onedrive.return_value = False
mock_s3.return_value = False
mock_sharepoint.return_value = False
mock_icloud.return_value = False
mock_upload.delay.return_value = MagicMock(id="task-123")
result = send_to_all_destinations.apply(args=[str(test_file), False, 42])
mock_upload.delay.assert_called_once()
# Verify file_id was passed to the upload task
call_kwargs = mock_upload.delay.call_args[1]
assert call_kwargs.get("file_id") == 42
@patch("app.tasks.send_to_all.SessionLocal")
@patch("app.tasks.send_to_all.log_task_progress")
@patch("app.tasks.send_to_all.settings")
@patch("app.tasks.send_to_all._should_upload_to_dropbox")
@patch("app.tasks.send_to_all._should_upload_to_nextcloud")
@patch("app.tasks.send_to_all._should_upload_to_paperless")
@patch("app.tasks.send_to_all._should_upload_to_google_drive")
@patch("app.tasks.send_to_all._should_upload_to_webdav")
@patch("app.tasks.send_to_all._should_upload_to_ftp")
@patch("app.tasks.send_to_all._should_upload_to_sftp")
@patch("app.tasks.send_to_all._should_upload_to_email")
@patch("app.tasks.send_to_all._should_upload_to_onedrive")
@patch("app.tasks.send_to_all._should_upload_to_sharepoint")
@patch("app.tasks.send_to_all._should_upload_to_icloud")
@patch("app.tasks.send_to_all._should_upload_to_s3")
@patch("app.tasks.send_to_all.get_configured_services_from_validator")
@patch("app.tasks.send_to_all.upload_to_dropbox")
def test_uses_validator_when_enabled(
self,
mock_upload,
mock_validator,
mock_s3,
mock_icloud,
mock_sharepoint,
mock_onedrive,
mock_email,
mock_sftp,
mock_ftp,
mock_webdav,
mock_google,
mock_paperless,
mock_nextcloud,
mock_should_dropbox,
mock_settings,
mock_log,
mock_session_local,
tmp_path,
):
"""Test that validator is used when use_validator=True."""
test_file = tmp_path / "test.pdf"
test_file.write_text("test")
mock_validator.return_value = {"dropbox": True}
# Mock all should_upload functions to return False (they won't be called when validator is used, but just in case)
mock_should_dropbox.return_value = False
mock_nextcloud.return_value = False
mock_paperless.return_value = False
mock_google.return_value = False
mock_webdav.return_value = False
mock_ftp.return_value = False
mock_sftp.return_value = False
mock_email.return_value = False
mock_onedrive.return_value = False
mock_s3.return_value = False
mock_sharepoint.return_value = False
mock_icloud.return_value = False
mock_upload.delay.return_value = MagicMock(id="task-123")
result = send_to_all_destinations.apply(args=[str(test_file), True, 1])
mock_validator.assert_called_once()
mock_upload.delay.assert_called_once()
@patch("app.tasks.send_to_all.SessionLocal")
@patch("app.tasks.send_to_all.log_task_progress")
@patch("app.tasks.send_to_all.settings")
@patch("app.tasks.send_to_all._should_upload_to_dropbox")
@patch("app.tasks.send_to_all._should_upload_to_nextcloud")
@patch("app.tasks.send_to_all._should_upload_to_paperless")
@patch("app.tasks.send_to_all._should_upload_to_google_drive")
@patch("app.tasks.send_to_all._should_upload_to_webdav")
@patch("app.tasks.send_to_all._should_upload_to_ftp")
@patch("app.tasks.send_to_all._should_upload_to_sftp")
@patch("app.tasks.send_to_all._should_upload_to_email")
@patch("app.tasks.send_to_all._should_upload_to_onedrive")
@patch("app.tasks.send_to_all._should_upload_to_sharepoint")
@patch("app.tasks.send_to_all._should_upload_to_icloud")
@patch("app.tasks.send_to_all._should_upload_to_s3")
@patch("app.tasks.send_to_all.get_configured_services_from_validator")
def test_validator_exception_fallback(
self,
mock_validator,
mock_s3,
mock_icloud,
mock_sharepoint,
mock_onedrive,
mock_email,
mock_sftp,
mock_ftp,
mock_webdav,
mock_google,
mock_paperless,
mock_nextcloud,
mock_should_dropbox,
mock_settings,
mock_log,
mock_session_local,
tmp_path,
):
"""Test fallback to individual checks when validator fails."""
test_file = tmp_path / "test.pdf"
test_file.write_text("test")
mock_validator.side_effect = Exception("Validator error")
# Set all _should_upload_* functions to return False
mock_should_dropbox.return_value = False
mock_nextcloud.return_value = False
mock_paperless.return_value = False
mock_google.return_value = False
mock_webdav.return_value = False
mock_ftp.return_value = False
mock_sftp.return_value = False
mock_email.return_value = False
mock_onedrive.return_value = False
mock_s3.return_value = False
mock_sharepoint.return_value = False
mock_icloud.return_value = False
# Should not raise, should fall back to individual checks
result = send_to_all_destinations.apply(args=[str(test_file), True, 1])
assert result.result["status"] == "Queued"
@patch("app.tasks.send_to_all.SessionLocal")
@patch("app.tasks.send_to_all.log_task_progress")
@patch("app.tasks.send_to_all.settings")
@patch("app.tasks.send_to_all._should_upload_to_dropbox")
@patch("app.tasks.send_to_all._should_upload_to_nextcloud")
@patch("app.tasks.send_to_all._should_upload_to_paperless")
@patch("app.tasks.send_to_all._should_upload_to_google_drive")
@patch("app.tasks.send_to_all._should_upload_to_webdav")
@patch("app.tasks.send_to_all._should_upload_to_ftp")
@patch("app.tasks.send_to_all._should_upload_to_sftp")
@patch("app.tasks.send_to_all._should_upload_to_email")
@patch("app.tasks.send_to_all._should_upload_to_onedrive")
@patch("app.tasks.send_to_all._should_upload_to_sharepoint")
@patch("app.tasks.send_to_all._should_upload_to_icloud")
@patch("app.tasks.send_to_all._should_upload_to_s3")
@patch("app.tasks.send_to_all.upload_to_dropbox")
def test_handles_upload_task_queue_error(
self,
mock_upload,
mock_s3,
mock_icloud,
mock_sharepoint,
mock_onedrive,
mock_email,
mock_sftp,
mock_ftp,
mock_webdav,
mock_google,
mock_paperless,
mock_nextcloud,
mock_should,
mock_settings,
mock_log,
mock_session_local,
tmp_path,
):
"""Test handling when queueing upload task fails."""
test_file = tmp_path / "test.pdf"
test_file.write_text("test")
mock_should.return_value = True
# Mock all other services to return False
mock_nextcloud.return_value = False
mock_paperless.return_value = False
mock_google.return_value = False
mock_webdav.return_value = False
mock_ftp.return_value = False
mock_sftp.return_value = False
mock_email.return_value = False
mock_onedrive.return_value = False
mock_s3.return_value = False
mock_sharepoint.return_value = False
mock_icloud.return_value = False
mock_upload.delay.side_effect = Exception("Queue error")
# Should not raise, should log error
result = send_to_all_destinations.apply(args=[str(test_file), False, 1])
assert result.result["status"] == "Queued"
# Error should be recorded in results
assert "dropbox_error" in result.result["tasks"]
@patch("app.tasks.send_to_all._should_upload_to_icloud")
@patch("app.tasks.send_to_all._should_upload_to_sharepoint")
@patch("app.tasks.send_to_all._should_upload_to_s3")
@patch("app.tasks.send_to_all._should_upload_to_onedrive")
@patch("app.tasks.send_to_all._should_upload_to_email")
@patch("app.tasks.send_to_all._should_upload_to_sftp")
@patch("app.tasks.send_to_all._should_upload_to_ftp")
@patch("app.tasks.send_to_all._should_upload_to_webdav")
@patch("app.tasks.send_to_all._should_upload_to_google_drive")
@patch("app.tasks.send_to_all._should_upload_to_paperless")
@patch("app.tasks.send_to_all._should_upload_to_nextcloud")
@patch("app.tasks.send_to_all._should_upload_to_dropbox")
@patch("app.tasks.send_to_all.log_task_progress")
@patch("app.tasks.send_to_all.SessionLocal")
@patch("app.tasks.send_to_all.settings")
def test_fallback_file_id_lookup(
self,
mock_settings,
mock_session_local,
mock_log,
mock_dropbox,
mock_nextcloud,
mock_paperless,
mock_google,
mock_webdav,
mock_ftp,
mock_sftp,
mock_email,
mock_onedrive,
mock_s3,
mock_sharepoint,
mock_icloud,
tmp_path,
):
"""Test file_id lookup fallback when not provided."""
from app.models import FileRecord
test_file = tmp_path / "test.pdf"
test_file.write_text("test")
mock_settings.workdir = str(tmp_path)
# Disable all upload services — this test only checks the DB lookup fallback
mock_dropbox.return_value = False
mock_nextcloud.return_value = False
mock_paperless.return_value = False
mock_google.return_value = False
mock_webdav.return_value = False
mock_ftp.return_value = False
mock_sftp.return_value = False
mock_email.return_value = False
mock_onedrive.return_value = False
mock_s3.return_value = False
mock_sharepoint.return_value = False
mock_icloud.return_value = False
# Mock database session
mock_db = MagicMock()
mock_query = MagicMock()
mock_file_record = MagicMock(spec=FileRecord)
mock_file_record.id = 123
mock_query.first.return_value = mock_file_record
mock_db.query.return_value.filter.return_value = mock_query
mock_session_local.return_value.__enter__.return_value = mock_db
result = send_to_all_destinations.apply(args=[str(test_file), False, None])
# Should attempt database lookup
mock_db.query.assert_called()
@patch("app.tasks.send_to_all.SessionLocal")
@patch("app.tasks.send_to_all.log_task_progress")
@patch("app.tasks.send_to_all.settings")
@patch("app.tasks.send_to_all._should_upload_to_dropbox")
@patch("app.tasks.send_to_all._should_upload_to_nextcloud")
@patch("app.tasks.send_to_all._should_upload_to_paperless")
@patch("app.tasks.send_to_all._should_upload_to_google_drive")
@patch("app.tasks.send_to_all._should_upload_to_webdav")
@patch("app.tasks.send_to_all._should_upload_to_ftp")
@patch("app.tasks.send_to_all._should_upload_to_sftp")
@patch("app.tasks.send_to_all._should_upload_to_email")
@patch("app.tasks.send_to_all._should_upload_to_onedrive")
@patch("app.tasks.send_to_all._should_upload_to_sharepoint")
@patch("app.tasks.send_to_all._should_upload_to_icloud")
@patch("app.tasks.send_to_all._should_upload_to_s3")
def test_should_upload_check_exception_handling(
self,
mock_s3,
mock_icloud,
mock_sharepoint,
mock_onedrive,
mock_email,
mock_sftp,
mock_ftp,
mock_webdav,
mock_google,
mock_paperless,
mock_nextcloud,
mock_should,
mock_settings,
mock_log,
mock_session_local,
tmp_path,
):
"""Test that exceptions in should_upload checks are handled."""
test_file = tmp_path / "test.pdf"
test_file.write_text("test")
mock_should.side_effect = Exception("Configuration check error")
# Mock all other services to return False
mock_nextcloud.return_value = False
mock_paperless.return_value = False
mock_google.return_value = False
mock_webdav.return_value = False
mock_ftp.return_value = False
mock_sftp.return_value = False
mock_email.return_value = False
mock_onedrive.return_value = False
mock_s3.return_value = False
mock_sharepoint.return_value = False
mock_icloud.return_value = False
# Should not raise, should treat as not configured
result = send_to_all_destinations.apply(args=[str(test_file), False, 1])
assert result.result["status"] == "Queued"