[SILO-316] Migration: Added cover_image_asset to Template model (#3404)

* Added cover_image_asset to Template model

* use the right property

* Test case for Template Model

* Added is_mentionable boolean field to Application
This commit is contained in:
Dheeraj Kumar Ketireddy
2025-06-13 18:51:52 +05:30
committed by GitHub
parent 3cdc29b9ba
commit c91d632e97
6 changed files with 268 additions and 1 deletions

View File

@@ -0,0 +1,18 @@
# Generated by Django 4.2.21 on 2025-06-13 11:15
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('authentication', '0003_application_website_applicationcategory_is_active'),
]
operations = [
migrations.AddField(
model_name='application',
name='is_mentionable',
field=models.BooleanField(default=False),
),
]

View File

@@ -66,6 +66,8 @@ class Application(AbstractApplication, UserAuditModel, SoftDeleteModel):
video_url = models.URLField(max_length=800, null=True, blank=True)
website = models.URLField(max_length=800, null=True, blank=True)
is_mentionable = models.BooleanField(default=False)
objects = ApplicationManager()
class Meta(AbstractApplication.Meta):

View File

@@ -0,0 +1,20 @@
# Generated by Django 4.2.21 on 2025-06-13 08:02
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('db', '0097_project_external_id_project_external_source'),
('ee', '0038_importreport_completed_batch_count_and_more'),
]
operations = [
migrations.AddField(
model_name='template',
name='cover_image_asset',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='cover_image_templates', to='db.fileasset'),
),
]

View File

@@ -47,6 +47,13 @@ class Template(WorkspaceBaseModel):
through="ee.TemplateAttachment",
blank=True,
)
cover_image_asset = models.ForeignKey(
"db.FileAsset",
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="cover_image_templates",
)
short_description = models.TextField(blank=True, null=True)
privacy_policy_url = models.URLField(max_length=800, null=True, blank=True)
terms_of_service_url = models.URLField(max_length=800, null=True, blank=True)
@@ -71,6 +78,14 @@ class Template(WorkspaceBaseModel):
)
super(Template, self).save(*args, **kwargs)
@property
def cover_image_url(self):
# Return cover image url
if self.cover_image_asset:
return self.cover_image_asset.asset_url
return None
class TemplateAttachment(BaseModel):
template = models.ForeignKey(

View File

@@ -3,8 +3,9 @@ from django.conf import settings
from rest_framework.test import APIClient
from pytest_django.fixtures import django_db_setup
from unittest.mock import patch, MagicMock
from uuid import uuid4
from plane.db.models import User
from plane.db.models import User, Workspace, FileAsset
from plane.db.models.api import APIToken
@@ -44,6 +45,48 @@ def create_user(db, user_data):
return user
@pytest.fixture
def workspace(db, create_user):
"""Create and return a workspace instance"""
workspace = Workspace.objects.create(
name="Test Workspace", slug="test-workspace", id=uuid4(), owner=create_user
)
return workspace
@pytest.fixture
def file_asset(db, workspace):
"""Create and return a basic FileAsset instance for testing"""
file_asset = FileAsset.objects.create(
workspace=workspace,
asset="test_file.txt",
attributes={
"name": "test_file.txt",
"size": 1024,
"mime_type": "text/plain",
},
size=1024,
)
return file_asset
@pytest.fixture
def cover_image_asset(db, workspace):
"""Create and return a FileAsset instance specifically for cover images"""
file_asset = FileAsset.objects.create(
workspace=workspace,
asset="cover_image.jpg",
attributes={
"name": "cover_image.jpg",
"size": 2048,
"mime_type": "image/jpeg",
},
size=2048,
entity_type=FileAsset.EntityTypeContext.PROJECT_COVER,
)
return file_asset
@pytest.fixture
def api_token(db, create_user):
"""Create and return an API token for testing the external API"""

View File

@@ -0,0 +1,169 @@
import pytest
from django.core.exceptions import ValidationError
from plane.ee.models.template import Template
@pytest.mark.unit
class TestTemplateModel:
"""Test the Template model"""
@pytest.mark.django_db
def test_template_creation(self, workspace):
"""Test creating a template with basic fields"""
# Arrange
template_data = {
"name": "Test Template",
"workspace": workspace,
"template_type": Template.TemplateType.WORKITEM,
"description": {"content": "Test description"},
"description_html": "<p>Test description</p>",
"company_name": "Test Company",
"short_description": "Short test description",
}
# Act
template = Template.objects.create(**template_data)
# Assert
# Basic fields
assert template.id is not None
assert template.name == template_data["name"]
assert template.template_type == template_data["template_type"]
assert template.description == template_data["description"]
assert template.description_html == template_data["description_html"]
assert template.company_name == template_data["company_name"]
assert template.short_description == template_data["short_description"]
# Default values
assert template.is_published is False
assert template.is_verified is False
assert template.supported_languages == {}
assert template.support == {}
assert template.resources == {}
assert template.keywords == []
@pytest.mark.django_db
def test_template_description_stripping(self, workspace):
"""Test that HTML tags are stripped from description_html"""
# Arrange
html_content = "<p>Test <b>description</b> with <i>HTML</i></p>"
expected_stripped = "Test description with HTML"
# Act
template = Template.objects.create(
name="Test Template",
workspace=workspace,
description_html=html_content,
)
# Assert
assert template.description_stripped == expected_stripped
@pytest.mark.django_db
def test_template_empty_description(self, workspace):
"""Test template with empty description"""
# Arrange
empty_html = ""
# Act
template = Template.objects.create(
name="Test Template",
workspace=workspace,
description_html=empty_html,
)
# Assert
assert template.description_stripped is None
@pytest.mark.django_db
def test_template_type_choices(self, workspace):
"""Test template type choices"""
# Arrange
valid_types = Template.TemplateType.values
invalid_type = "invalid_type"
# Act & Assert for valid types
for template_type in valid_types:
template = Template.objects.create(
name=f"Test {template_type}",
workspace=workspace,
template_type=template_type,
)
assert template.template_type == template_type
# Act & Assert for invalid type
template = Template(
name="Invalid Template",
workspace=workspace,
template_type=invalid_type,
)
with pytest.raises(ValidationError):
template.full_clean()
@pytest.mark.django_db
def test_template_url_fields(self, workspace):
"""Test template URL fields"""
# Arrange
url_data = {
"privacy_policy_url": "https://example.com/privacy",
"terms_of_service_url": "https://example.com/terms",
"support_url": "https://example.com/support",
"video_url": "https://example.com/video",
"website": "https://example.com",
}
# Act
template = Template.objects.create(
name="Test Template",
workspace=workspace,
**url_data,
)
# Assert
for field, expected_url in url_data.items():
assert getattr(template, field) == expected_url
@pytest.mark.django_db
def test_template_contact_email(self, workspace):
"""Test template contact email field"""
# Arrange
valid_email = "test@example.com"
invalid_email = "invalid-email"
# Act & Assert for valid email
template = Template.objects.create(
name="Test Template",
workspace=workspace,
contact_email=valid_email,
)
assert template.contact_email == valid_email
# Act & Assert for invalid email
template = Template(
name="Invalid Template",
workspace=workspace,
contact_email=invalid_email,
)
with pytest.raises(ValidationError):
template.full_clean()
@pytest.mark.django_db
def test_template_cover_image_url(self, workspace, cover_image_asset):
"""Test template cover image URL property"""
# Arrange
template_name = "Test Template"
# Act - Test without cover image
template = Template.objects.create(
name=template_name,
workspace=workspace,
)
assert template.cover_image_url is None
# Act - Test with cover image
template.cover_image_asset = cover_image_asset
template.save()
# Assert
assert template.cover_image_url == cover_image_asset.asset_url