test: add 150 new unit tests covering auth, users, notifications, logs, settings, GDPR, and Gmail label utilities
Agent-Logs-Url: https://github.com/christianlouis/InboxConverge/sessions/8cb47b1c-b744-4212-8b6d-8132d6642d98 Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
6e7139645b
commit
58f9ad72ed
@@ -0,0 +1,184 @@
|
||||
"""
|
||||
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 "https://mail.google.com/" in result
|
||||
|
||||
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 "https://mail.google.com/" in result["granted_scopes"]
|
||||
|
||||
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
|
||||
Reference in New Issue
Block a user