Test PDF renderer

This commit is contained in:
Jake Howard 2017-06-01 22:04:21 +01:00
parent bb4cfa962a
commit 8b914d8ae2
3 changed files with 126 additions and 17 deletions

View file

@ -13,8 +13,8 @@ DEFAULT_MARGIN_VERTICAL = '1.5cm'
DEFAULT_MARGIN_HORIZONTAL = '2.5cm' DEFAULT_MARGIN_HORIZONTAL = '2.5cm'
STYLE_FILE = os.path.join(STATIC_DIR, 'style.css') STYLE_FILE = os.path.join(STATIC_DIR, 'style.css')
HEADER_FILE = os.path.join(TEMPLATES_DIR, 'header.html') HEADER_FILE = FILE_NAME_FORMAT.format('header')
FOOTER_FILE = os.path.join(TEMPLATES_DIR, 'footer.html') FOOTER_FILE = FILE_NAME_FORMAT.format('footer')
TOC_OPTIONS = { TOC_OPTIONS = {
'xsl-style-sheet': os.path.join(TEMPLATES_DIR, 'toc.xsl') 'xsl-style-sheet': os.path.join(TEMPLATES_DIR, 'toc.xsl')
@ -37,15 +37,17 @@ def export_pdf(content, config):
if logger.getEffectiveLevel() > logging.DEBUG: if logger.getEffectiveLevel() > logging.DEBUG:
PDF_OPTIONS['quiet'] = "" PDF_OPTIONS['quiet'] = ""
PDF_OPTIONS['title'] = config.get('title', 'Output') PDF_OPTIONS['title'] = config.get('title', 'Output')
PDF_OPTIONS['replace'] = [(key, str(value)) for key, value in config['context'].items()] context = config.get('context', {})
PDF_OPTIONS['margin-top'] = config['context'].get('margin_vertical', DEFAULT_MARGIN_VERTICAL) PDF_OPTIONS['replace'] = [(key, str(value)) for key, value in context.items()]
PDF_OPTIONS['margin-bottom'] = config['context'].get('margin_vertical', DEFAULT_MARGIN_VERTICAL) PDF_OPTIONS['margin-top'] = context.get('margin_vertical', DEFAULT_MARGIN_VERTICAL)
PDF_OPTIONS['margin-left'] = config['context'].get('margin_horizontal', DEFAULT_MARGIN_HORIZONTAL) PDF_OPTIONS['margin-bottom'] = context.get('margin_vertical', DEFAULT_MARGIN_VERTICAL)
PDF_OPTIONS['margin-right'] = config['context'].get('margin_horizontal', DEFAULT_MARGIN_HORIZONTAL) PDF_OPTIONS['margin-left'] = context.get('margin_horizontal', DEFAULT_MARGIN_HORIZONTAL)
PDF_OPTIONS['margin-right'] = context.get('margin_horizontal', DEFAULT_MARGIN_HORIZONTAL)
logger.info("Rendering PDF...") logger.info("Rendering PDF...")
render_ok = pdfkit.from_string( try:
pdfkit.from_string(
content, content,
os.path.join(os.path.abspath(config['output_dir']), 'output.pdf'), os.path.join(os.path.abspath(config['output_dir']), 'output.pdf'),
options=PDF_OPTIONS, options=PDF_OPTIONS,
@ -53,7 +55,7 @@ def export_pdf(content, config):
toc=TOC_OPTIONS if config.get('toc') else {}, toc=TOC_OPTIONS if config.get('toc') else {},
cover_first=True cover_first=True
) )
if not render_ok: except OSError as e:
raise PDFRenderException('Failed to render PDF. ' + render_ok) raise PDFRenderException('Failed to render PDF. ' + str(e))
return PDF_OPTIONS # mostly for testing return PDF_OPTIONS # mostly for testing

View file

@ -1,6 +1,7 @@
import unittest import unittest
import os import os
from md_pdf.consts import TEMPLATES_DIR, STATIC_DIR from md_pdf.consts import TEMPLATES_DIR, STATIC_DIR
from md_pdf.build.templates import FILE_NAME_FORMAT
from bs4 import BeautifulSoup from bs4 import BeautifulSoup
@ -26,6 +27,17 @@ class BaseTestCase(unittest.TestCase):
except OSError: except OSError:
pass pass
def touch_file(self, file):
open(file, 'w').close()
def create_fake_templates(self):
for template in [
'header',
'footer',
'cover'
]:
self.touch_file(FILE_NAME_FORMAT.format(template))
def extend_config(self, *args): def extend_config(self, *args):
base_config = self.BASE_VALID_CONFIG.copy() base_config = self.BASE_VALID_CONFIG.copy()
for arg in args: for arg in args:
@ -45,3 +57,8 @@ class BaseTestCase(unittest.TestCase):
self.delete_templates() self.delete_templates()
self.remove_file(os.path.join(STATIC_DIR, 'style.css')) self.remove_file(os.path.join(STATIC_DIR, 'style.css'))
def call_to_args(self, call):
args = tuple(call.call_args)[0]
kwargs = tuple(call.call_args)[1]
return args, kwargs

90
tests/test_pdf.py Normal file
View file

@ -0,0 +1,90 @@
from tests import BaseTestCase
import os
from md_pdf.build.pdf import export_pdf, TOC_OPTIONS, DEFAULT_MARGIN_VERTICAL, DEFAULT_MARGIN_HORIZONTAL
from unittest.mock import patch
from md_pdf.build.templates import FILE_NAME_FORMAT
from md_pdf.exceptions import PDFRenderException
import pdfkit
class PDFRendererTestCase(BaseTestCase):
def setUp(self):
super().setUp()
self.content = 'test content'
self.output_file_path = os.path.join(self.BASE_VALID_CONFIG['output_dir'], 'output.pdf')
self.assertFalse(os.path.isfile(self.output_file_path))
self.create_fake_templates()
def tearDown(self):
super().tearDown()
self.remove_file(self.output_file_path)
def test_renders(self):
export_pdf(self.content, self.BASE_VALID_CONFIG)
def test_title(self):
context = export_pdf(self.content, self.BASE_VALID_CONFIG)
self.assertEqual(context['title'], self.BASE_VALID_CONFIG['title'])
def test_replace_context(self):
self.BASE_VALID_CONFIG['context'] = {
'1': 2,
'2': '1'
}
context = export_pdf(self.content, self.BASE_VALID_CONFIG)
self.assertEqual(context['replace'], [
('1', '2'),
('2', '1'),
])
def test_default_margins(self):
context = export_pdf(self.content, self.BASE_VALID_CONFIG)
self.assertEqual(context['margin-top'], DEFAULT_MARGIN_VERTICAL)
self.assertEqual(context['margin-bottom'], DEFAULT_MARGIN_VERTICAL)
self.assertEqual(context['margin-left'], DEFAULT_MARGIN_HORIZONTAL)
self.assertEqual(context['margin-right'], DEFAULT_MARGIN_HORIZONTAL)
def test_override_margin(self):
self.BASE_VALID_CONFIG['context'] = {
'margin_vertical': '1cm',
'margin_horizontal': '2cm'
}
context = export_pdf(self.content, self.BASE_VALID_CONFIG)
self.assertEqual(context['margin-top'], '1cm')
self.assertEqual(context['margin-bottom'], '1cm')
self.assertEqual(context['margin-left'], '2cm')
self.assertEqual(context['margin-right'], '2cm')
@patch.object(pdfkit, 'from_string')
def test_kit_call(self, pdf_render):
context = export_pdf(self.content, self.BASE_VALID_CONFIG)
self.assertTrue(pdf_render.called)
args, kwargs = self.call_to_args(pdf_render)
self.assertEqual(args[0], self.content)
self.assertIn(self.output_file_path, args[1])
self.assertEqual(kwargs['options'], context)
self.assertTrue(kwargs['cover_first'])
self.assertEqual(kwargs['cover'], FILE_NAME_FORMAT.format('cover'))
self.assertEqual(kwargs['toc'], {})
@patch.object(pdfkit, 'from_string')
def test_toc(self, pdf_render):
self.BASE_VALID_CONFIG['toc'] = True
export_pdf(self.content, self.BASE_VALID_CONFIG)
args, kwargs = self.call_to_args(pdf_render)
self.assertEqual(kwargs['toc'], TOC_OPTIONS)
def test_fails_if_missing_templates(self):
self.remove_file(FILE_NAME_FORMAT.format('cover'))
with self.assertRaises(PDFRenderException):
export_pdf(self.content, self.BASE_VALID_CONFIG)
def test_files_exist(self):
context = export_pdf(self.content, self.BASE_VALID_CONFIG)
self.assertTrue(os.path.isfile(context['header-html']))
self.assertTrue(os.path.isfile(context['footer-html']))
self.assertEqual(context['header-html'], FILE_NAME_FORMAT.format('header'))
self.assertEqual(context['footer-html'], FILE_NAME_FORMAT.format('footer'))