# -*- coding: utf-8 -*-
from __future__ import absolute_import
import os
import sys
import warnings
from django.test import TestCase
from django.test.client import RequestFactory
from .subprocess import CalledProcessError
from .utils import (override_settings,
_options_to_args, template_to_temp_file, wkhtmltopdf)
from .views import (PDFResponse, PdfResponse, PDFTemplateResponse,
PDFTemplateView, PdfTemplateView)
class TestUtils(TestCase):
def setUp(self):
# Clear standard error
self._stderr = sys.stderr
sys.stderr = open(os.devnull, 'w')
def tearDown(self):
sys.stderr = self._stderr
def test_options_to_args(self):
self.assertEqual(_options_to_args(), [])
self.assertEqual(_options_to_args(heart=u'♥', verbose=True,
file_name='file-name'),
['--file-name', 'file-name',
'--heart', u'♥',
'--verbose'])
def test_wkhtmltopdf(self):
"""Should run wkhtmltopdf to generate a PDF"""
title = 'A test template.'
temp_file = template_to_temp_file('sample.html', {'title': title})
pdf_output = None
try:
# Standard call
pdf_output = wkhtmltopdf(pages=[temp_file])
self.assertTrue(pdf_output.startswith('%PDF'), pdf_output)
# Single page
pdf_output = wkhtmltopdf(pages=temp_file)
self.assertTrue(pdf_output.startswith('%PDF'), pdf_output)
# Unicode
pdf_output = wkhtmltopdf(pages=[temp_file], title=u'♥')
self.assertTrue(pdf_output.startswith('%PDF'), pdf_output)
# Invalid arguments
self.assertRaises(CalledProcessError,
wkhtmltopdf, pages=[])
finally:
if os.path.exists(temp_file):
os.remove(temp_file)
def test_template_to_temp_file(self):
"""Should render a template to a temporary file."""
title = 'A test template.'
temp_file = template_to_temp_file('sample.html', {'title': title})
try:
with open(temp_file, 'r') as f:
saved_content = f.read()
self.assertTrue(title in saved_content)
finally:
if os.path.exists(temp_file):
os.remove(temp_file)
class TestViews(TestCase):
def test_pdf_response(self):
"""Should generate the correct HttpResponse object and mimetype"""
# 404
response = PDFResponse(content='', status=404)
self.assertEqual(response.status_code, 404)
self.assertEqual(response.content, '')
self.assertEqual(response['Content-Type'], 'application/pdf')
self.assertFalse(response.has_header('Content-Disposition'))
content = '%PDF-1.4\n%%EOF'
# Without filename
response = PDFResponse(content=content)
self.assertEqual(response.status_code, 200)
self.assertEqual(response.content, content)
self.assertEqual(response['Content-Type'], 'application/pdf')
self.assertFalse(response.has_header('Content-Disposition'))
# With filename
response = PDFResponse(content=content, filename="nospace.pdf")
self.assertEqual(response['Content-Disposition'],
'attachment; filename="nospace.pdf"')
response = PDFResponse(content=content, filename="one space.pdf")
self.assertEqual(response['Content-Disposition'],
'attachment; filename="one space.pdf"')
response = PDFResponse(content=content, filename="4'5\".pdf")
self.assertEqual(response['Content-Disposition'],
'attachment; filename="4\'5.pdf"')
response = PDFResponse(content=content, filename=u"♥.pdf")
self.assertEqual(response['Content-Disposition'],
'attachment; filename="?.pdf"')
# Content-Type
response = PDFResponse(content=content,
content_type='application/x-pdf')
self.assertEqual(response['Content-Type'], 'application/x-pdf')
response = PDFResponse(content=content,
mimetype='application/x-pdf')
self.assertEqual(response['Content-Type'], 'application/x-pdf')
def test_pdf_template_response(self):
"""Test PDFTemplateResponse."""
from django.conf import settings
with override_settings(
MEDIA_URL='/media/',
MEDIA_ROOT='/tmp/media',
STATIC_URL='/static/',
STATIC_ROOT='/tmp/static',
TEMPLATE_CONTEXT_PROCESSORS=[
'django.core.context_processors.media',
'django.core.context_processors.static',
],
TEMPLATE_LOADERS=['django.template.loaders.filesystem.Loader'],
TEMPLATE_DIRS=[os.path.join(os.path.dirname(__file__),
'_testproject', 'templates')],
WKHTMLTOPDF_DEBUG=False,
):
# Setup sample.html
template = 'sample.html'
context = {'title': 'Heading'}
request = RequestFactory().get('/')
response = PDFTemplateResponse(request=request,
template=template,
context=context)
self.assertEqual(response._request, request)
self.assertEqual(response.template_name, template)
self.assertEqual(response.context_data, context)
self.assertEqual(response.filename, None)
self.assertEqual(response.header_template, None)
self.assertEqual(response.footer_template, None)
self.assertEqual(response.cmd_options, {})
self.assertFalse(response.has_header('Content-Disposition'))
# Render to temporary file
tempfile = response.render_to_temporary_file(template)
tempfile.seek(0)
html_content = tempfile.read()
self.assertTrue(html_content.startswith(''))
self.assertTrue('
{title}
'.format(**context)
in html_content)
pdf_content = response.rendered_content
self.assertTrue(pdf_content.startswith('%PDF-'))
self.assertTrue(pdf_content.endswith('%%EOF\n'))
# Footer
filename = 'output.pdf'
footer_template = 'footer.html'
cmd_options = {'title': 'Test PDF'}
response = PDFTemplateResponse(request=request,
template=template,
context=context,
filename=filename,
footer_template=footer_template,
cmd_options=cmd_options)
self.assertEqual(response.filename, filename)
self.assertEqual(response.header_template, None)
self.assertEqual(response.footer_template, footer_template)
self.assertEqual(response.cmd_options, cmd_options)
self.assertTrue(response.has_header('Content-Disposition'))
tempfile = response.render_to_temporary_file(footer_template)
tempfile.seek(0)
footer_content = tempfile.read()
media_url = 'MEDIA_URL = file://{}/'.format(settings.MEDIA_ROOT)
self.assertTrue(
media_url in footer_content,
"{!r} not in {!r}".format(media_url, footer_content)
)
static_url = 'STATIC_URL = file://{}/'.format(settings.STATIC_ROOT)
self.assertTrue(
static_url in footer_content,
"{!r} not in {!r}".format(static_url, footer_content)
)
pdf_content = response.rendered_content
self.assertTrue('\0'.join('{title}'.format(**cmd_options))
in pdf_content)
# Override settings
response = PDFTemplateResponse(request=request,
template=template,
context=context,
filename=filename,
footer_template=footer_template,
cmd_options=cmd_options,
override_settings={
'STATIC_URL': 'file:///tmp/s/'
})
tempfile = response.render_to_temporary_file(footer_template)
tempfile.seek(0)
footer_content = tempfile.read()
static_url = 'STATIC_URL = {}'.format('file:///tmp/s/')
self.assertTrue(
static_url in footer_content,
"{!r} not in {!r}".format(static_url, footer_content)
)
self.assertEqual(settings.STATIC_URL, '/static/')
def test_pdf_template_view(self):
"""Test PDFTemplateView."""
with override_settings(
MEDIA_URL='/media/',
STATIC_URL='/static/',
TEMPLATE_CONTEXT_PROCESSORS=[
'django.core.context_processors.media',
'django.core.context_processors.static',
],
TEMPLATE_LOADERS=['django.template.loaders.filesystem.Loader'],
TEMPLATE_DIRS=[os.path.join(os.path.dirname(__file__),
'_testproject', 'templates')],
WKHTMLTOPDF_DEBUG=False,
):
# Setup sample.html
template = 'sample.html'
filename = 'output.pdf'
view = PDFTemplateView.as_view(filename=filename,
template_name=template,
footer_template='footer.html')
# As PDF
request = RequestFactory().get('/')
response = view(request)
self.assertEqual(response.status_code, 200)
response.render()
self.assertEqual(response['Content-Disposition'],
'attachment; filename="{}"'.format(filename))
self.assertTrue(response.content.startswith('%PDF-'))
self.assertTrue(response.content.endswith('%%EOF\n'))
# As HTML
request = RequestFactory().get('/?as=html')
response = view(request)
self.assertEqual(response.status_code, 200)
response.render()
self.assertFalse(response.has_header('Content-Disposition'))
self.assertTrue(response.content.startswith(''))
# POST
request = RequestFactory().post('/')
response = view(request)
self.assertEqual(response.status_code, 405)
def test_get_cmd_options(self):
# Default cmd_options
view = PDFTemplateView()
self.assertEqual(view.cmd_options, PDFTemplateView.cmd_options)
self.assertEqual(PDFTemplateView.cmd_options, {})
# Instantiate with new cmd_options
cmd_options = {'orientation': 'landscape'}
view = PDFTemplateView(cmd_options=cmd_options)
self.assertEqual(view.cmd_options, cmd_options)
self.assertEqual(PDFTemplateView.cmd_options, {})
# Update local instance of cmd_options
view = PDFTemplateView()
view.cmd_options.update(cmd_options)
self.assertEqual(view.cmd_options, cmd_options)
self.assertEqual(PDFTemplateView.cmd_options, {})
def test_deprecated(self):
"""Should warn when using deprecated views."""
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
PdfTemplateView()
self.assertEqual(len(w), 1)
self.assertEqual(w[0].category, PendingDeprecationWarning)
self.assertTrue(
'PDFTemplateView' in str(w[0].message),
"'PDFTemplateView' not in {!r}".format(w[0].message))
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
PdfResponse(None, None)
self.assertEqual(len(w), 1)
self.assertEqual(w[0].category, PendingDeprecationWarning)
self.assertTrue(
'PDFResponse' in str(w[0].message),
"'PDFResponse' not in {!r}".format(w[0].message))
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter('always')
PDFTemplateView().get_pdf_kwargs()
self.assertEqual(len(w), 1)
self.assertEqual(w[0].category, PendingDeprecationWarning)
self.assertTrue(
'get_pdf_kwargs()' in str(w[0].message),
"'get_pdf_kwargs()' not in {!r}".format(w[0].message))