bottleneckcrm/backend/common/tests/test_models.py
2026-10-21 09:25:18 +05:30

266 lines
9.4 KiB
Python

"""
Tests for common/models.py and common/base.py - model methods and properties.
Covers:
- CommentFiles.save() auto-populate org
- Attachments.file_type() with various extensions
- Document.file_type() with various extensions
- SessionToken.revoke() and cleanup_expired()
- Activity.created_on_arrow property
- AssignableMixin properties (get_team_users, etc.)
Run with: pytest common/tests/test_models.py -v
"""
import uuid
from unittest.mock import MagicMock
import pytest
from django.contrib.contenttypes.models import ContentType
from accounts.models import Account
from common.models import (
Activity,
Attachments,
Comment,
CommentFiles,
Document,
Org,
Teams,
)
# ---------------------------------------------------------------------------
# CommentFiles.save() auto-populate org
# ---------------------------------------------------------------------------
@pytest.mark.django_db
class TestCommentFilesSave:
"""Test CommentFiles.save() auto-populates org from parent comment."""
def test_auto_populate_org_from_comment(self, org_a, admin_profile):
"""CommentFiles should inherit org from parent comment if not set."""
ct = ContentType.objects.get_for_model(Org)
comment = Comment.objects.create(
content_type=ct,
object_id=org_a.pk,
comment="Test comment",
commented_by=admin_profile,
org=org_a,
)
cf = CommentFiles(comment=comment)
cf.save()
assert cf.org_id == org_a.pk
def test_explicit_org_not_overridden(self, org_a, org_b, admin_profile):
"""CommentFiles with explicitly set org should keep it."""
ct = ContentType.objects.get_for_model(Org)
comment = Comment.objects.create(
content_type=ct,
object_id=org_a.pk,
comment="Test comment",
commented_by=admin_profile,
org=org_a,
)
cf = CommentFiles(comment=comment, org=org_b)
cf.save()
# org_b was explicitly set, so it should remain
assert cf.org_id == org_b.pk
# ---------------------------------------------------------------------------
# Attachments.file_type()
# ---------------------------------------------------------------------------
@pytest.mark.django_db
class TestAttachmentsFileType:
"""Test Attachments.file_type() returns correct type tuples."""
def _make_attachment(self, org, filename):
"""Create an Attachment instance with a mocked file URL."""
ct = ContentType.objects.get_for_model(Org)
att = Attachments(
content_type=ct,
object_id=org.pk,
file_name=filename,
org=org,
)
att.attachment = MagicMock()
att.attachment.url = f"/media/attachments/{filename}"
return att
def test_audio_file(self, org_a):
att = self._make_attachment(org_a, "song.mp3")
assert att.file_type() == ("audio", "fa fa-file-audio")
def test_video_file(self, org_a):
att = self._make_attachment(org_a, "clip.mp4")
assert att.file_type() == ("video", "fa fa-file-video")
def test_image_file(self, org_a):
att = self._make_attachment(org_a, "photo.png")
assert att.file_type() == ("image", "fa fa-file-image")
def test_pdf_file(self, org_a):
att = self._make_attachment(org_a, "document.pdf")
assert att.file_type() == ("pdf", "fa fa-file-pdf")
def test_code_file(self, org_a):
att = self._make_attachment(org_a, "app.json")
assert att.file_type() == ("code", "fa fa-file-code")
def test_text_file(self, org_a):
att = self._make_attachment(org_a, "readme.doc")
assert att.file_type() == ("text", "fa fa-file-alt")
def test_sheet_file(self, org_a):
att = self._make_attachment(org_a, "data.xlsx")
assert att.file_type() == ("sheet", "fa fa-file-excel")
def test_zip_file(self, org_a):
att = self._make_attachment(org_a, "archive.zip")
assert att.file_type() == ("zip", "fa fa-file-archive")
def test_unknown_extension(self, org_a):
att = self._make_attachment(org_a, "file.xyz")
assert att.file_type() == ("file", "fa fa-file")
def test_no_extension(self, org_a):
att = self._make_attachment(org_a, "README")
att.attachment.url = "/media/attachments/README"
assert att.file_type() == ("file", "fa fa-file")
# ---------------------------------------------------------------------------
# Document.file_type()
# ---------------------------------------------------------------------------
@pytest.mark.django_db
class TestDocumentFileType:
"""Test Document.file_type() returns correct type tuples."""
def _make_document(self, org, filename):
doc = Document(title="Test", org=org)
doc.document_file = MagicMock()
doc.document_file.url = f"/media/docs/{filename}"
return doc
def test_audio_file(self, org_a):
doc = self._make_document(org_a, "song.wav")
assert doc.file_type() == ("audio", "fa fa-file-audio")
def test_video_file(self, org_a):
doc = self._make_document(org_a, "clip.avi")
assert doc.file_type() == ("video", "fa fa-file-video")
def test_image_file(self, org_a):
doc = self._make_document(org_a, "photo.jpg")
assert doc.file_type() == ("image", "fa fa-file-image")
def test_pdf_file(self, org_a):
doc = self._make_document(org_a, "report.pdf")
assert doc.file_type() == ("pdf", "fa fa-file-pdf")
def test_code_file(self, org_a):
doc = self._make_document(org_a, "script.py")
assert doc.file_type() == ("code", "fa fa-file-code")
def test_text_file(self, org_a):
doc = self._make_document(org_a, "letter.docx")
assert doc.file_type() == ("text", "fa fa-file-alt")
def test_sheet_file(self, org_a):
doc = self._make_document(org_a, "budget.csv")
assert doc.file_type() == ("sheet", "fa fa-file-excel")
def test_zip_file(self, org_a):
doc = self._make_document(org_a, "backup.tar")
assert doc.file_type() == ("zip", "fa fa-file-archive")
def test_unknown_extension(self, org_a):
doc = self._make_document(org_a, "data.bin")
assert doc.file_type() == ("file", "fa fa-file")
def test_no_extension(self, org_a):
doc = self._make_document(org_a, "Makefile")
doc.document_file.url = "/media/docs/Makefile"
assert doc.file_type() == ("file", "fa fa-file")
# ---------------------------------------------------------------------------
# Activity.created_on_arrow
# ---------------------------------------------------------------------------
@pytest.mark.django_db
class TestActivityCreatedOnArrow:
"""Test Activity.created_on_arrow property."""
def test_created_on_arrow_format(self, org_a, admin_profile):
activity = Activity.objects.create(
user=admin_profile,
action="CREATE",
entity_type="Account",
entity_id=uuid.uuid4(),
entity_name="Test Account",
org=org_a,
)
result = activity.created_on_arrow
assert result.endswith(" ago")
# Should contain a time unit like "seconds", "minutes", etc.
assert len(result) > 4
# ---------------------------------------------------------------------------
# AssignableMixin properties (via Account model which uses it)
# ---------------------------------------------------------------------------
@pytest.mark.django_db
class TestAssignableMixin:
"""Test AssignableMixin properties on Account model."""
def test_get_team_users(self, org_a, admin_profile, user_profile):
team = Teams.objects.create(name="Sales", description="Sales team", org=org_a)
team.users.add(admin_profile, user_profile)
account = Account.objects.create(name="Test Account Mixin1", org=org_a)
account.teams.add(team)
team_users = account.get_team_users
assert admin_profile in team_users
assert user_profile in team_users
def test_get_team_and_assigned_users(self, org_a, admin_profile, user_profile):
team = Teams.objects.create(name="Sales", description="Sales team", org=org_a)
team.users.add(admin_profile)
account = Account.objects.create(name="Test Account Mixin2", org=org_a)
account.teams.add(team)
account.assigned_to.add(user_profile)
all_users = account.get_team_and_assigned_users
assert admin_profile in all_users
assert user_profile in all_users
def test_get_assigned_users_not_in_teams(self, org_a, admin_profile, user_profile):
team = Teams.objects.create(name="Sales", description="Sales team", org=org_a)
team.users.add(admin_profile)
account = Account.objects.create(name="Test Account Mixin3", org=org_a)
account.teams.add(team)
account.assigned_to.add(admin_profile, user_profile)
not_in_teams = account.get_assigned_users_not_in_teams
# admin_profile is in team AND assigned, so excluded
assert admin_profile not in not_in_teams
# user_profile is assigned but not in team
assert user_profile in not_in_teams
def test_no_teams_no_assignments(self, org_a):
account = Account.objects.create(name="Test Account Mixin4", org=org_a)
assert account.get_team_users.count() == 0
assert account.get_team_and_assigned_users.count() == 0
assert account.get_assigned_users_not_in_teams.count() == 0