Files
gh-christianlouis-inboxconv…/backend/tests/unit/test_gmail_labels.py
T

184 lines
6.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.
"""
Unit tests for Gmail label utilities (utils/gmail_labels.py).
Pure function tests no database or HTTP layer required.
"""
from app.utils.gmail_labels import (
DEFAULT_IMPORT_LABEL_TEMPLATES,
MAX_IMPORT_LABELS,
_normalize_string_list,
normalize_import_label_templates,
extract_granted_scopes,
extract_import_label_templates,
build_gmail_credential_scopes,
render_import_labels,
)
class TestNormalizeStringList:
def test_basic_dedup(self):
result = _normalize_string_list(["a", "A", "b"])
assert result == ["a", "b"]
def test_strips_whitespace(self):
result = _normalize_string_list([" hello ", "world"])
assert result == ["hello", "world"]
def test_empty_strings_filtered(self):
result = _normalize_string_list(["", " ", "real"])
assert result == ["real"]
def test_none_returns_empty(self):
assert _normalize_string_list(None) == []
def test_preserves_case_in_output(self):
# Case-insensitive dedup but preserves original casing
result = _normalize_string_list(["Hello", "hello"])
assert result == ["Hello"]
def test_order_preserved(self):
items = ["c", "a", "b"]
assert _normalize_string_list(items) == ["c", "a", "b"]
class TestNormalizeImportLabelTemplates:
def test_none_returns_defaults(self):
result = normalize_import_label_templates(None)
assert result == DEFAULT_IMPORT_LABEL_TEMPLATES
def test_empty_list_returns_defaults(self):
result = normalize_import_label_templates([])
assert result == DEFAULT_IMPORT_LABEL_TEMPLATES
def test_custom_templates(self):
result = normalize_import_label_templates(["archive", "inbox"])
assert result == ["archive", "inbox"]
def test_deduplicates(self):
result = normalize_import_label_templates(["tag", "TAG"])
assert result == ["tag"]
def test_returns_copy_of_defaults(self):
result = normalize_import_label_templates(None)
result.append("extra")
assert "extra" not in DEFAULT_IMPORT_LABEL_TEMPLATES
class TestExtractGrantedScopes:
def test_list_format(self):
result = extract_granted_scopes(["scope1", "scope2"])
assert result == ["scope1", "scope2"]
def test_list_filters_non_strings(self):
result = extract_granted_scopes(["valid", 42, None, "other"])
assert result == ["valid", "other"]
def test_dict_format(self):
data = {"granted_scopes": ["https://mail.google.com/", "openid"]}
result = extract_granted_scopes(data)
assert result == ["https://mail.google.com/", "openid"]
def test_dict_missing_granted_scopes(self):
result = extract_granted_scopes({})
assert result == []
def test_dict_non_list_granted_scopes(self):
result = extract_granted_scopes({"granted_scopes": "not-a-list"})
assert result == []
def test_unrecognized_type(self):
assert extract_granted_scopes(None) == []
assert extract_granted_scopes(42) == []
assert extract_granted_scopes("string") == []
class TestExtractImportLabelTemplates:
def test_dict_with_templates(self):
data = {"import_label_templates": ["archive", "imported"]}
result = extract_import_label_templates(data)
assert result == ["archive", "imported"]
def test_dict_missing_key(self):
result = extract_import_label_templates({})
assert result == DEFAULT_IMPORT_LABEL_TEMPLATES
def test_non_dict(self):
assert extract_import_label_templates(None) == DEFAULT_IMPORT_LABEL_TEMPLATES
assert extract_import_label_templates([]) == DEFAULT_IMPORT_LABEL_TEMPLATES
def test_empty_templates_falls_back_to_defaults(self):
result = extract_import_label_templates({"import_label_templates": []})
assert result == DEFAULT_IMPORT_LABEL_TEMPLATES
def test_filters_non_strings(self):
data = {"import_label_templates": ["valid", 123, None]}
result = extract_import_label_templates(data)
assert result == ["valid"]
class TestBuildGmailCredentialScopes:
def test_basic(self):
result = build_gmail_credential_scopes(
["https://mail.google.com/"], ["{{source_email}}", "imported"]
)
assert "granted_scopes" in result
assert "import_label_templates" in result
assert result["granted_scopes"] == ["https://mail.google.com/"]
def test_none_granted_scopes(self):
result = build_gmail_credential_scopes(None)
assert result["granted_scopes"] == []
assert result["import_label_templates"] == DEFAULT_IMPORT_LABEL_TEMPLATES
def test_deduplication(self):
result = build_gmail_credential_scopes(["scope", "SCOPE"])
assert result["granted_scopes"] == ["scope"]
class TestRenderImportLabels:
def test_source_email_substitution(self):
result = render_import_labels(["{{source_email}}"], "user@example.com")
assert result == ["user@example.com"]
def test_literal_template(self):
result = render_import_labels(["imported"], "user@example.com")
assert result == ["imported"]
def test_mixed_templates(self):
result = render_import_labels(
["{{source_email}}", "imported"], "user@example.com"
)
assert result == ["user@example.com", "imported"]
def test_deduplication(self):
result = render_import_labels(["tag", "TAG"], "user@example.com")
assert result == ["tag"]
def test_none_source_email(self):
# Template containing source_email placeholder with no email → empty string,
# gets stripped, filtered out.
result = render_import_labels(["{{source_email}}"], None)
assert result == []
def test_empty_source_email(self):
result = render_import_labels(["{{source_email}}"], "")
assert result == []
def test_none_templates_uses_defaults(self):
result = render_import_labels(None, "user@example.com")
assert "user@example.com" in result
assert "imported" in result
def test_whitespace_only_template_filtered(self):
# Whitespace-only entries are stripped to empty strings and then filtered
# by normalize_import_label_templates. When no valid templates remain,
# defaults are returned. The source_email template then renders to the
# source email, and "imported" is included too.
result = render_import_labels([" "], "user@example.com")
# normalize_import_label_templates falls back to defaults → includes
# {{source_email}} (renders to "user@example.com") and "imported"
assert result == ["user@example.com", "imported"]
def test_max_labels_constant(self):
assert MAX_IMPORT_LABELS == 10