mirror of
https://github.com/makeplane/plane.git
synced 2026-07-14 06:25:58 +02:00
[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:
committed by
GitHub
parent
3cdc29b9ba
commit
c91d632e97
@@ -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),
|
||||
),
|
||||
]
|
||||
@@ -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):
|
||||
|
||||
@@ -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'),
|
||||
),
|
||||
]
|
||||
@@ -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(
|
||||
|
||||
@@ -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"""
|
||||
|
||||
169
apiserver/plane/tests/unit/models/test_template.py
Normal file
169
apiserver/plane/tests/unit/models/test_template.py
Normal 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
|
||||
Reference in New Issue
Block a user