survey_custom_certificate_t.../tests/test_multi_survey_isolation.py
2025-11-29 08:46:04 +07:00

518 lines
21 KiB
Python

# -*- coding: utf-8 -*-
import base64
import json
from odoo.tests import TransactionCase
from odoo.exceptions import UserError
class TestMultiSurveyTemplateIsolation(TransactionCase):
"""
Test cases for multi-survey template management and isolation.
These tests verify that:
- Templates are stored per survey record (Requirement 7.2)
- Template loading works correctly by survey_id (Requirement 7.3)
- Templates from one survey do not affect other surveys
"""
def setUp(self):
super().setUp()
# Create multiple test surveys
self.survey_1 = self.env['survey.survey'].create({
'title': 'Python Programming Course',
'description': 'Learn Python programming',
})
self.survey_2 = self.env['survey.survey'].create({
'title': 'JavaScript Fundamentals',
'description': 'Learn JavaScript basics',
})
self.survey_3 = self.env['survey.survey'].create({
'title': 'Data Science Bootcamp',
'description': 'Master data science',
})
def _create_test_docx(self, text_content):
"""
Helper method to create a DOCX file with given text content.
Args:
text_content: String or list of strings to add as paragraphs
Returns:
bytes: Binary content of the created DOCX file
"""
try:
from docx import Document
from io import BytesIO
except ImportError:
self.skipTest("python-docx not installed")
doc = Document()
if isinstance(text_content, str):
text_content = [text_content]
for text in text_content:
doc.add_paragraph(text)
# Save to BytesIO
doc_stream = BytesIO()
doc.save(doc_stream)
doc_stream.seek(0)
return doc_stream.read()
def test_template_storage_per_survey(self):
"""
Test that templates are stored separately for each survey.
Validates Requirement 7.2: Templates should be stored per survey record.
"""
# Create different templates for each survey
template_1 = self._create_test_docx("Certificate for {key.name} - Python Course")
template_2 = self._create_test_docx("Certificate for {key.name} - JavaScript Course")
template_3 = self._create_test_docx("Certificate for {key.name} - Data Science Course")
# Configure survey 1 with template 1
self.survey_1.write({
'custom_cert_template': base64.b64encode(template_1),
'custom_cert_template_filename': 'python_cert.docx',
'has_custom_certificate': True,
'custom_cert_mappings': json.dumps({
'placeholders': [
{'key': '{key.name}', 'value_type': 'user_field', 'value_field': 'partner_name'}
]
})
})
# Configure survey 2 with template 2
self.survey_2.write({
'custom_cert_template': base64.b64encode(template_2),
'custom_cert_template_filename': 'javascript_cert.docx',
'has_custom_certificate': True,
'custom_cert_mappings': json.dumps({
'placeholders': [
{'key': '{key.name}', 'value_type': 'user_field', 'value_field': 'partner_name'}
]
})
})
# Configure survey 3 with template 3
self.survey_3.write({
'custom_cert_template': base64.b64encode(template_3),
'custom_cert_template_filename': 'datascience_cert.docx',
'has_custom_certificate': True,
'custom_cert_mappings': json.dumps({
'placeholders': [
{'key': '{key.name}', 'value_type': 'user_field', 'value_field': 'partner_name'}
]
})
})
# Verify each survey has its own template
self.assertTrue(self.survey_1.has_custom_certificate)
self.assertTrue(self.survey_2.has_custom_certificate)
self.assertTrue(self.survey_3.has_custom_certificate)
# Verify filenames are different
self.assertEqual(self.survey_1.custom_cert_template_filename, 'python_cert.docx')
self.assertEqual(self.survey_2.custom_cert_template_filename, 'javascript_cert.docx')
self.assertEqual(self.survey_3.custom_cert_template_filename, 'datascience_cert.docx')
# Verify templates are different (by comparing binary content)
template_1_stored = base64.b64decode(self.survey_1.custom_cert_template)
template_2_stored = base64.b64decode(self.survey_2.custom_cert_template)
template_3_stored = base64.b64decode(self.survey_3.custom_cert_template)
self.assertNotEqual(template_1_stored, template_2_stored)
self.assertNotEqual(template_2_stored, template_3_stored)
self.assertNotEqual(template_1_stored, template_3_stored)
def test_template_loading_by_survey_id(self):
"""
Test that the correct template is loaded for each survey.
Validates Requirement 7.3: Switching between surveys should load
the correct custom template for that survey.
"""
# Create different templates
template_1 = self._create_test_docx("Python Certificate")
template_2 = self._create_test_docx("JavaScript Certificate")
# Configure survey 1
self.survey_1.write({
'custom_cert_template': base64.b64encode(template_1),
'custom_cert_template_filename': 'python_cert.docx',
'has_custom_certificate': True,
'custom_cert_mappings': json.dumps({
'placeholders': [
{'key': '{key.name}', 'value_type': 'user_field', 'value_field': 'partner_name'}
]
})
})
# Configure survey 2
self.survey_2.write({
'custom_cert_template': base64.b64encode(template_2),
'custom_cert_template_filename': 'javascript_cert.docx',
'has_custom_certificate': True,
'custom_cert_mappings': json.dumps({
'placeholders': [
{'key': '{key.name}', 'value_type': 'user_field', 'value_field': 'partner_name'}
]
})
})
# Load survey 1 and verify its template
survey_1_loaded = self.env['survey.survey'].browse(self.survey_1.id)
self.assertEqual(survey_1_loaded.custom_cert_template_filename, 'python_cert.docx')
self.assertTrue(survey_1_loaded.has_custom_certificate)
# Load survey 2 and verify its template
survey_2_loaded = self.env['survey.survey'].browse(self.survey_2.id)
self.assertEqual(survey_2_loaded.custom_cert_template_filename, 'javascript_cert.docx')
self.assertTrue(survey_2_loaded.has_custom_certificate)
# Verify templates are different
self.assertNotEqual(
survey_1_loaded.custom_cert_template,
survey_2_loaded.custom_cert_template
)
def test_template_isolation_no_cross_contamination(self):
"""
Test that modifying one survey's template does not affect other surveys.
This ensures complete isolation between survey templates.
"""
# Create initial templates
template_1 = self._create_test_docx("Original Template 1")
template_2 = self._create_test_docx("Original Template 2")
# Configure both surveys
self.survey_1.write({
'custom_cert_template': base64.b64encode(template_1),
'custom_cert_template_filename': 'template_1.docx',
'has_custom_certificate': True,
'custom_cert_mappings': json.dumps({
'placeholders': [
{'key': '{key.name}', 'value_type': 'user_field', 'value_field': 'partner_name'}
]
})
})
self.survey_2.write({
'custom_cert_template': base64.b64encode(template_2),
'custom_cert_template_filename': 'template_2.docx',
'has_custom_certificate': True,
'custom_cert_mappings': json.dumps({
'placeholders': [
{'key': '{key.name}', 'value_type': 'user_field', 'value_field': 'partner_name'}
]
})
})
# Store original values for survey 2
original_template_2 = self.survey_2.custom_cert_template
original_filename_2 = self.survey_2.custom_cert_template_filename
original_mappings_2 = self.survey_2.custom_cert_mappings
# Modify survey 1's template
new_template_1 = self._create_test_docx("Modified Template 1")
self.survey_1.write({
'custom_cert_template': base64.b64encode(new_template_1),
'custom_cert_template_filename': 'modified_template_1.docx',
'custom_cert_mappings': json.dumps({
'placeholders': [
{'key': '{key.name}', 'value_type': 'custom_text', 'custom_text': 'Modified'}
]
})
})
# Verify survey 1 was modified
self.assertEqual(self.survey_1.custom_cert_template_filename, 'modified_template_1.docx')
# Verify survey 2 was NOT affected
self.assertEqual(self.survey_2.custom_cert_template, original_template_2)
self.assertEqual(self.survey_2.custom_cert_template_filename, original_filename_2)
self.assertEqual(self.survey_2.custom_cert_mappings, original_mappings_2)
def test_survey_without_template_unaffected(self):
"""
Test that surveys without custom templates are not affected by other surveys.
This ensures that the default behavior is preserved for surveys
that don't use custom templates.
"""
# Configure only survey 1 with a custom template
template_1 = self._create_test_docx("Custom Template")
self.survey_1.write({
'custom_cert_template': base64.b64encode(template_1),
'custom_cert_template_filename': 'custom_cert.docx',
'has_custom_certificate': True,
'custom_cert_mappings': json.dumps({
'placeholders': [
{'key': '{key.name}', 'value_type': 'user_field', 'value_field': 'partner_name'}
]
})
})
# Verify survey 1 has custom template
self.assertTrue(self.survey_1.has_custom_certificate)
self.assertIsNotNone(self.survey_1.custom_cert_template)
# Verify survey 2 and 3 do NOT have custom templates
self.assertFalse(self.survey_2.has_custom_certificate)
self.assertFalse(self.survey_3.has_custom_certificate)
self.assertFalse(self.survey_2.custom_cert_template)
self.assertFalse(self.survey_3.custom_cert_template)
def test_wizard_associates_template_with_correct_survey(self):
"""
Test that the wizard correctly associates templates with the intended survey.
This verifies that the wizard workflow maintains survey-specific isolation.
"""
# Create template content
template_content = self._create_test_docx("Certificate for {key.name}")
# Create wizard for survey 1
wizard_1 = self.env['survey.custom.certificate.wizard'].create({
'survey_id': self.survey_1.id,
'template_file': base64.b64encode(template_content),
'template_filename': 'survey1_cert.docx',
})
# Create placeholder for wizard 1
self.env['survey.certificate.placeholder'].create({
'wizard_id': wizard_1.id,
'source_key': '{key.name}',
'value_type': 'user_field',
'value_field': 'partner_name',
'sequence': 1,
})
# Save template via wizard
wizard_1.action_save_template()
# Verify survey 1 has the template
self.assertTrue(self.survey_1.has_custom_certificate)
self.assertEqual(self.survey_1.custom_cert_template_filename, 'survey1_cert.docx')
# Verify survey 2 does NOT have the template
self.assertFalse(self.survey_2.has_custom_certificate)
self.assertFalse(self.survey_2.custom_cert_template)
# Now create wizard for survey 2 with different template
template_content_2 = self._create_test_docx("Different Certificate for {key.name}")
wizard_2 = self.env['survey.custom.certificate.wizard'].create({
'survey_id': self.survey_2.id,
'template_file': base64.b64encode(template_content_2),
'template_filename': 'survey2_cert.docx',
})
# Create placeholder for wizard 2
self.env['survey.certificate.placeholder'].create({
'wizard_id': wizard_2.id,
'source_key': '{key.name}',
'value_type': 'user_field',
'value_field': 'partner_name',
'sequence': 1,
})
# Save template via wizard
wizard_2.action_save_template()
# Verify survey 2 now has its own template
self.assertTrue(self.survey_2.has_custom_certificate)
self.assertEqual(self.survey_2.custom_cert_template_filename, 'survey2_cert.docx')
# Verify survey 1's template is unchanged
self.assertEqual(self.survey_1.custom_cert_template_filename, 'survey1_cert.docx')
# Verify templates are different
self.assertNotEqual(
self.survey_1.custom_cert_template,
self.survey_2.custom_cert_template
)
def test_multiple_surveys_with_same_placeholder_names(self):
"""
Test that multiple surveys can use the same placeholder names independently.
This ensures that placeholder mappings are survey-specific.
"""
# Create template with same placeholders for both surveys
template_content = self._create_test_docx(
"Certificate for {key.name} - Course: {key.course}"
)
# Configure survey 1 with specific mappings
self.survey_1.write({
'custom_cert_template': base64.b64encode(template_content),
'custom_cert_template_filename': 'cert1.docx',
'has_custom_certificate': True,
'custom_cert_mappings': json.dumps({
'placeholders': [
{'key': '{key.name}', 'value_type': 'user_field', 'value_field': 'partner_name'},
{'key': '{key.course}', 'value_type': 'survey_field', 'value_field': 'survey_title'}
]
})
})
# Configure survey 2 with DIFFERENT mappings for same placeholders
self.survey_2.write({
'custom_cert_template': base64.b64encode(template_content),
'custom_cert_template_filename': 'cert2.docx',
'has_custom_certificate': True,
'custom_cert_mappings': json.dumps({
'placeholders': [
{'key': '{key.name}', 'value_type': 'custom_text', 'custom_text': 'Student Name'},
{'key': '{key.course}', 'value_type': 'custom_text', 'custom_text': 'Course Name'}
]
})
})
# Parse mappings
mappings_1 = json.loads(self.survey_1.custom_cert_mappings)
mappings_2 = json.loads(self.survey_2.custom_cert_mappings)
# Verify survey 1 mappings
self.assertEqual(mappings_1['placeholders'][0]['value_type'], 'user_field')
self.assertEqual(mappings_1['placeholders'][0]['value_field'], 'partner_name')
self.assertEqual(mappings_1['placeholders'][1]['value_type'], 'survey_field')
# Verify survey 2 mappings are different
self.assertEqual(mappings_2['placeholders'][0]['value_type'], 'custom_text')
self.assertEqual(mappings_2['placeholders'][0]['custom_text'], 'Student Name')
self.assertEqual(mappings_2['placeholders'][1]['value_type'], 'custom_text')
# Verify they are independent
self.assertNotEqual(
mappings_1['placeholders'][0]['value_type'],
mappings_2['placeholders'][0]['value_type']
)
def test_certificate_generation_uses_correct_survey_template(self):
"""
Test that certificate generation uses the correct template for each survey.
This is an integration test that verifies the complete workflow
maintains survey-specific template isolation.
"""
# Create test partner
partner = self.env['res.partner'].create({
'name': 'Test Student',
'email': 'student@example.com',
})
# Create user inputs for both surveys
user_input_1 = self.env['survey.user_input'].create({
'survey_id': self.survey_1.id,
'partner_id': partner.id,
'email': partner.email,
'state': 'done',
})
user_input_2 = self.env['survey.user_input'].create({
'survey_id': self.survey_2.id,
'partner_id': partner.id,
'email': partner.email,
'state': 'done',
})
# Configure templates for both surveys
template_1 = self._create_test_docx("Python Certificate for {key.name}")
template_2 = self._create_test_docx("JavaScript Certificate for {key.name}")
self.survey_1.write({
'custom_cert_template': base64.b64encode(template_1),
'custom_cert_template_filename': 'python_cert.docx',
'has_custom_certificate': True,
'custom_cert_mappings': json.dumps({
'placeholders': [
{'key': '{key.name}', 'value_type': 'user_field', 'value_field': 'partner_name'}
]
})
})
self.survey_2.write({
'custom_cert_template': base64.b64encode(template_2),
'custom_cert_template_filename': 'javascript_cert.docx',
'has_custom_certificate': True,
'custom_cert_mappings': json.dumps({
'placeholders': [
{'key': '{key.name}', 'value_type': 'user_field', 'value_field': 'partner_name'}
]
})
})
# Get certificate data for both surveys
data_1 = self.survey_1._get_certificate_data(user_input_1.id)
data_2 = self.survey_2._get_certificate_data(user_input_2.id)
# Verify data includes correct survey information
self.assertEqual(data_1['survey_title'], 'Python Programming Course')
self.assertEqual(data_2['survey_title'], 'JavaScript Fundamentals')
# Verify both have same participant data
self.assertEqual(data_1['partner_name'], 'Test Student')
self.assertEqual(data_2['partner_name'], 'Test Student')
# Note: Actual certificate generation would require LibreOffice
# This test verifies the data retrieval is survey-specific
def test_template_deletion_only_affects_target_survey(self):
"""
Test that deleting a template from one survey doesn't affect others.
"""
# Configure templates for both surveys
template_1 = self._create_test_docx("Template 1")
template_2 = self._create_test_docx("Template 2")
self.survey_1.write({
'custom_cert_template': base64.b64encode(template_1),
'custom_cert_template_filename': 'cert1.docx',
'has_custom_certificate': True,
'custom_cert_mappings': json.dumps({
'placeholders': [
{'key': '{key.name}', 'value_type': 'user_field', 'value_field': 'partner_name'}
]
})
})
self.survey_2.write({
'custom_cert_template': base64.b64encode(template_2),
'custom_cert_template_filename': 'cert2.docx',
'has_custom_certificate': True,
'custom_cert_mappings': json.dumps({
'placeholders': [
{'key': '{key.name}', 'value_type': 'user_field', 'value_field': 'partner_name'}
]
})
})
# Store survey 2's original values
original_template_2 = self.survey_2.custom_cert_template
original_filename_2 = self.survey_2.custom_cert_template_filename
# Delete template from survey 1
self.survey_1.write({
'custom_cert_template': False,
'custom_cert_template_filename': False,
'has_custom_certificate': False,
'custom_cert_mappings': False,
})
# Verify survey 1 template is deleted
self.assertFalse(self.survey_1.has_custom_certificate)
self.assertFalse(self.survey_1.custom_cert_template)
# Verify survey 2 template is unchanged
self.assertTrue(self.survey_2.has_custom_certificate)
self.assertEqual(self.survey_2.custom_cert_template, original_template_2)
self.assertEqual(self.survey_2.custom_cert_template_filename, original_filename_2)