""" Integration tests for markdown rendering in feedback detail pages. These tests verify end-to-end behavior: from accessing the detail route through to seeing properly formatted HTML in the response. """ import pytest from flask import url_for # Skip all tests if markdown_utils not yet implemented try: from app.utils.markdown_utils import markdown_filter MARKDOWN_UTILS_EXISTS = True except ImportError: MARKDOWN_UTILS_EXISTS = False pytestmark = pytest.mark.skipif( not MARKDOWN_UTILS_EXISTS, reason="markdown_utils module not yet implemented" ) @pytest.fixture def sample_feedback_with_markdown(authenticated_owner_client, app): """Create a feedback item with markdown-formatted AI analysis.""" from app.models.feedback import Feedback import os feedback_id = "test-md-001" product_id = "prod_0001" # Create feedback using correct API feedback = Feedback( feedback_id=feedback_id, product_id=product_id, content_preview="Test feedback for markdown rendering" ) feedback.save_metadata() # Save content feedback_dir = Feedback._get_feedback_dir(product_id, feedback_id) content_file = os.path.join(feedback_dir, 'content.txt') with open(content_file, 'w') as f: f.write("Test feedback for markdown rendering") # Save analysis analysis_content = """## Summary The customer feedback is **highly positive** with some *minor concerns*. ### Key Points - Easy to use - Great performance - Excellent support ### Recommendations 1. Improve documentation 2. Add more features 3. Fix known bugs ### Technical Details The system uses `Flask` framework with the following code: ```python @app.route('/dashboard') def dashboard(): return render_template('dashboard.html') ``` ### External References See [Flask Documentation](https://flask.palletsprojects.com/) for more info. ### Data Summary | Metric | Value | |-----------|-------| | Score | 9/10 | | Sentiment | Positive | """ analysis_file = os.path.join(feedback_dir, 'analysis.md') with open(analysis_file, 'w') as f: f.write(analysis_content) yield feedback # Cleanup import shutil if os.path.exists(feedback_dir): shutil.rmtree(feedback_dir) @pytest.fixture def sample_feedback_with_xss_attempt(authenticated_owner_client, app): """Create feedback with XSS attempt in analysis for security testing.""" from app.models.feedback import Feedback import os feedback_id = "test-xss-001" product_id = "prod_0001" # Create feedback using correct API feedback = Feedback( feedback_id=feedback_id, product_id=product_id, content_preview="Test feedback" ) feedback.save_metadata() # Save content feedback_dir = Feedback._get_feedback_dir(product_id, feedback_id) content_file = os.path.join(feedback_dir, 'content.txt') with open(content_file, 'w') as f: f.write("Test feedback") # Analysis with XSS attempts analysis_content = """## Analysis This is safe content. **Bold text** is fine. Bad link  """ analysis_file = os.path.join(feedback_dir, 'analysis.md') with open(analysis_file, 'w') as f: f.write(analysis_content) yield feedback # Cleanup import shutil if os.path.exists(feedback_dir): shutil.rmtree(feedback_dir) class TestMarkdownRenderingIntegration: """Test markdown rendering in full feedback detail page context.""" def test_feedback_detail_renders_markdown_headings( self, authenticated_owner_client, sample_feedback_with_markdown ): """T015: Feedback detail page renders markdown headings as HTML.""" response = authenticated_owner_client.get( url_for('dashboard.detail', feedback_id=sample_feedback_with_markdown.feedback_id) ) assert response.status_code == 200 html = response.data.decode('utf-8') # Check headings are rendered assert "
Flask" in html
# Check code block (code is HTML-escaped, so check for the function name)
assert "@app.route" in html
assert "def dashboard()" in html
# Should be in pre or code tags
assert ("" in html or "" in html)
def test_feedback_detail_renders_markdown_tables(
self, authenticated_owner_client, sample_feedback_with_markdown
):
"""T015: Feedback detail page renders tables as HTML."""
response = authenticated_owner_client.get(
url_for('dashboard.detail', feedback_id=sample_feedback_with_markdown.feedback_id)
)
html = response.data.decode('utf-8')
# Check table structure
assert "" in html
assert "" in html
assert "" in html
assert "Metric " in html or "Value " in html
assert "9/10 " in html or "Positive " in html
def test_feedback_detail_renders_links_with_security(
self, authenticated_owner_client, sample_feedback_with_markdown
):
"""T015: Feedback detail page renders links with security attributes."""
response = authenticated_owner_client.get(
url_for('dashboard.detail', feedback_id=sample_feedback_with_markdown.feedback_id)
)
html = response.data.decode('utf-8')
# Check link exists
assert 'href="https://flask.palletsprojects.com/"' in html or \
'href="http://flask.palletsprojects.com/"' in html
assert "Flask Documentation" in html
# Check security attributes
assert 'target="_blank"' in html
assert 'rel="noopener noreferrer nofollow"' in html or \
('noopener' in html and 'noreferrer' in html and 'nofollow' in html)
class TestMarkdownSecurityIntegration:
"""Test security features in full page context."""
def test_feedback_detail_removes_script_tags(
self, authenticated_owner_client, sample_feedback_with_xss_attempt
):
"""T015: Feedback detail page removes script tags from analysis."""
response = authenticated_owner_client.get(
url_for('dashboard.detail', feedback_id=sample_feedback_with_xss_attempt.feedback_id)
)
html = response.data.decode('utf-8')
# Script tag and content should be removed
assert "