test: add tests for gmail_apply_labels=False and cloud source type dispatching
Add test_gmail_labels_disabled_when_gmail_apply_labels_false to verify that Gmail star/label operations are skipped when gmail_apply_labels=False. Add four tests to TestPullUserIntegrationWatchFolders for cloud source type dispatching: S3, Dropbox, unknown provider, and explicit local type. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -687,6 +687,59 @@ class TestPullInbox:
|
||||
mock_star.assert_called_once_with(mock_mail, b"1")
|
||||
mock_label.assert_called_once_with(mock_mail, b"1", label="Ingested")
|
||||
|
||||
@patch("app.tasks.imap_tasks.email_already_has_label")
|
||||
@patch("app.tasks.imap_tasks.mark_as_processed_with_label")
|
||||
@patch("app.tasks.imap_tasks.mark_as_processed_with_star")
|
||||
@patch("app.tasks.imap_tasks.fetch_attachments_and_enqueue")
|
||||
@patch("app.tasks.imap_tasks.imaplib.IMAP4_SSL")
|
||||
@patch("app.tasks.imap_tasks.load_processed_emails")
|
||||
@patch("app.tasks.imap_tasks.save_processed_emails")
|
||||
@patch("app.tasks.imap_tasks.settings")
|
||||
def test_gmail_labels_disabled_when_gmail_apply_labels_false(
|
||||
self,
|
||||
mock_settings,
|
||||
mock_save,
|
||||
mock_load,
|
||||
mock_imap_class,
|
||||
mock_fetch,
|
||||
mock_star,
|
||||
mock_label,
|
||||
mock_has_label,
|
||||
):
|
||||
"""Gmail star/label operations should be skipped when gmail_apply_labels=False."""
|
||||
mock_settings.workdir = "/tmp"
|
||||
mock_settings.imap_readonly_mode = False
|
||||
mock_load.return_value = {}
|
||||
mock_mail = MagicMock()
|
||||
mock_imap_class.return_value = mock_mail
|
||||
|
||||
import email
|
||||
|
||||
msg = email.message.EmailMessage()
|
||||
msg["Message-ID"] = "<test-no-labels@gmail.com>"
|
||||
raw_email = msg.as_bytes()
|
||||
|
||||
mock_mail.login.return_value = ("OK", [])
|
||||
mock_mail.select.return_value = ("OK", [])
|
||||
mock_mail.search.return_value = ("OK", [b"1"])
|
||||
mock_mail.fetch.return_value = ("OK", [[None, raw_email]])
|
||||
|
||||
pull_inbox(
|
||||
mailbox_key="imap2",
|
||||
host="imap.gmail.com",
|
||||
port=993,
|
||||
username="user@gmail.com",
|
||||
password=_TEST_CREDENTIAL,
|
||||
use_ssl=True,
|
||||
delete_after_process=False,
|
||||
gmail_apply_labels=False,
|
||||
)
|
||||
|
||||
mock_star.assert_not_called()
|
||||
mock_label.assert_not_called()
|
||||
mock_has_label.assert_not_called()
|
||||
mock_fetch.assert_called()
|
||||
|
||||
@patch("app.tasks.imap_tasks.email_already_has_label")
|
||||
@patch("app.tasks.imap_tasks.imaplib.IMAP4_SSL")
|
||||
@patch("app.tasks.imap_tasks.load_processed_emails")
|
||||
|
||||
@@ -3843,6 +3843,134 @@ class TestPullUserIntegrationWatchFolders:
|
||||
result = _pull_user_integration_watch_folders()
|
||||
assert result["status"] == "ok"
|
||||
|
||||
@patch("app.tasks.watch_folder_tasks._get_db_session")
|
||||
@patch("app.tasks.watch_folder_tasks._load_cache", return_value={})
|
||||
@patch("app.tasks.watch_folder_tasks._save_cache")
|
||||
def test_dispatches_s3_source_type(self, mock_save, mock_load, mock_session_factory):
|
||||
"""WATCH_FOLDER with source_type 's3' should dispatch to _scan_user_s3_folder."""
|
||||
from app.tasks.watch_folder_tasks import (
|
||||
_USER_WF_CLOUD_HANDLERS,
|
||||
_pull_user_integration_watch_folders,
|
||||
)
|
||||
|
||||
mock_integ = MagicMock()
|
||||
mock_integ.id = 30
|
||||
mock_integ.owner_id = "owner-s3"
|
||||
mock_integ.config = (
|
||||
'{"source_type": "s3", "bucket": "test-bucket", "prefix": "inbox/", "delete_after_process": false}'
|
||||
)
|
||||
mock_integ.is_active = True
|
||||
mock_integ.credentials = "encrypted-s3-creds"
|
||||
|
||||
mock_db = MagicMock()
|
||||
mock_db.query.return_value.filter.return_value.all.return_value = [mock_integ]
|
||||
mock_session_factory.return_value = mock_db
|
||||
|
||||
mock_s3_handler = MagicMock(return_value=3)
|
||||
original_handler = _USER_WF_CLOUD_HANDLERS.get("s3")
|
||||
_USER_WF_CLOUD_HANDLERS["s3"] = mock_s3_handler
|
||||
try:
|
||||
with patch(
|
||||
"app.utils.encryption.decrypt_value",
|
||||
return_value='{"access_key_id": "AKI", "secret_access_key": "SK"}',
|
||||
):
|
||||
result = _pull_user_integration_watch_folders()
|
||||
|
||||
assert result["status"] == "ok"
|
||||
assert result["files_enqueued"] == 3
|
||||
mock_s3_handler.assert_called_once()
|
||||
args = mock_s3_handler.call_args
|
||||
assert args[0][0]["source_type"] == "s3"
|
||||
assert args[0][4] == "owner-s3"
|
||||
finally:
|
||||
if original_handler is not None:
|
||||
_USER_WF_CLOUD_HANDLERS["s3"] = original_handler
|
||||
|
||||
@patch("app.tasks.watch_folder_tasks._get_db_session")
|
||||
@patch("app.tasks.watch_folder_tasks._load_cache", return_value={})
|
||||
@patch("app.tasks.watch_folder_tasks._save_cache")
|
||||
def test_dispatches_dropbox_source_type(self, mock_save, mock_load, mock_session_factory):
|
||||
"""WATCH_FOLDER with source_type 'dropbox' should dispatch to _scan_user_dropbox_folder."""
|
||||
from app.tasks.watch_folder_tasks import (
|
||||
_USER_WF_CLOUD_HANDLERS,
|
||||
_pull_user_integration_watch_folders,
|
||||
)
|
||||
|
||||
mock_integ = MagicMock()
|
||||
mock_integ.id = 31
|
||||
mock_integ.owner_id = "owner-dbx"
|
||||
mock_integ.config = '{"source_type": "dropbox", "folder_path": "/Inbox", "delete_after_process": false}'
|
||||
mock_integ.is_active = True
|
||||
mock_integ.credentials = "encrypted-dbx-creds"
|
||||
|
||||
mock_db = MagicMock()
|
||||
mock_db.query.return_value.filter.return_value.all.return_value = [mock_integ]
|
||||
mock_session_factory.return_value = mock_db
|
||||
|
||||
mock_dbx_handler = MagicMock(return_value=5)
|
||||
original_handler = _USER_WF_CLOUD_HANDLERS.get("dropbox")
|
||||
_USER_WF_CLOUD_HANDLERS["dropbox"] = mock_dbx_handler
|
||||
try:
|
||||
with patch(
|
||||
"app.utils.encryption.decrypt_value",
|
||||
return_value='{"refresh_token": "tok", "app_key": "ak", "app_secret": "as"}',
|
||||
):
|
||||
result = _pull_user_integration_watch_folders()
|
||||
|
||||
assert result["status"] == "ok"
|
||||
assert result["files_enqueued"] == 5
|
||||
mock_dbx_handler.assert_called_once()
|
||||
args = mock_dbx_handler.call_args
|
||||
assert args[0][0]["source_type"] == "dropbox"
|
||||
assert args[0][4] == "owner-dbx"
|
||||
finally:
|
||||
if original_handler is not None:
|
||||
_USER_WF_CLOUD_HANDLERS["dropbox"] = original_handler
|
||||
|
||||
@patch("app.tasks.watch_folder_tasks._get_db_session")
|
||||
def test_unknown_source_type_skipped(self, mock_session_factory):
|
||||
"""Unknown source_type should be skipped gracefully."""
|
||||
from app.tasks.watch_folder_tasks import _pull_user_integration_watch_folders
|
||||
|
||||
mock_integ = MagicMock()
|
||||
mock_integ.id = 32
|
||||
mock_integ.owner_id = "owner-unknown"
|
||||
mock_integ.config = '{"source_type": "unknown_provider", "delete_after_process": false}'
|
||||
mock_integ.is_active = True
|
||||
|
||||
mock_db = MagicMock()
|
||||
mock_db.query.return_value.filter.return_value.all.return_value = [mock_integ]
|
||||
mock_session_factory.return_value = mock_db
|
||||
|
||||
result = _pull_user_integration_watch_folders()
|
||||
assert result["status"] == "ok"
|
||||
assert result["files_enqueued"] == 0
|
||||
|
||||
@patch("app.tasks.watch_folder_tasks._get_db_session")
|
||||
@patch("app.tasks.watch_folder_tasks._scan_user_watch_folder", return_value=4)
|
||||
@patch("app.tasks.watch_folder_tasks._load_cache", return_value={})
|
||||
@patch("app.tasks.watch_folder_tasks._save_cache")
|
||||
def test_local_source_type_uses_local_scanner(self, mock_save, mock_load, mock_scan_local, mock_session_factory):
|
||||
"""Explicit source_type 'local' should use the local filesystem scanner."""
|
||||
from app.tasks.watch_folder_tasks import _pull_user_integration_watch_folders
|
||||
|
||||
mock_integ = MagicMock()
|
||||
mock_integ.id = 33
|
||||
mock_integ.owner_id = "owner-local"
|
||||
mock_integ.config = '{"source_type": "local", "folder_path": "/data/scans", "delete_after_process": false}'
|
||||
mock_integ.is_active = True
|
||||
|
||||
mock_db = MagicMock()
|
||||
mock_db.query.return_value.filter.return_value.all.return_value = [mock_integ]
|
||||
mock_session_factory.return_value = mock_db
|
||||
|
||||
result = _pull_user_integration_watch_folders()
|
||||
assert result["status"] == "ok"
|
||||
assert result["files_enqueued"] == 4
|
||||
mock_scan_local.assert_called_once()
|
||||
assert mock_scan_local.call_args[0][0] == "/data/scans"
|
||||
assert mock_scan_local.call_args[0][3] == "owner-local"
|
||||
|
||||
|
||||
@pytest.mark.unit
|
||||
class TestScanAllWatchFoldersIncludesUserIntegrations:
|
||||
|
||||
Reference in New Issue
Block a user