Test PDF renderer
This commit is contained in:
parent
bb4cfa962a
commit
8b914d8ae2
3 changed files with 126 additions and 17 deletions
|
@ -13,8 +13,8 @@ DEFAULT_MARGIN_VERTICAL = '1.5cm'
|
|||
DEFAULT_MARGIN_HORIZONTAL = '2.5cm'
|
||||
|
||||
STYLE_FILE = os.path.join(STATIC_DIR, 'style.css')
|
||||
HEADER_FILE = os.path.join(TEMPLATES_DIR, 'header.html')
|
||||
FOOTER_FILE = os.path.join(TEMPLATES_DIR, 'footer.html')
|
||||
HEADER_FILE = FILE_NAME_FORMAT.format('header')
|
||||
FOOTER_FILE = FILE_NAME_FORMAT.format('footer')
|
||||
|
||||
TOC_OPTIONS = {
|
||||
'xsl-style-sheet': os.path.join(TEMPLATES_DIR, 'toc.xsl')
|
||||
|
@ -37,23 +37,25 @@ def export_pdf(content, config):
|
|||
if logger.getEffectiveLevel() > logging.DEBUG:
|
||||
PDF_OPTIONS['quiet'] = ""
|
||||
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['margin-bottom'] = config['context'].get('margin_vertical', DEFAULT_MARGIN_VERTICAL)
|
||||
PDF_OPTIONS['margin-left'] = config['context'].get('margin_horizontal', DEFAULT_MARGIN_HORIZONTAL)
|
||||
PDF_OPTIONS['margin-right'] = config['context'].get('margin_horizontal', DEFAULT_MARGIN_HORIZONTAL)
|
||||
PDF_OPTIONS['replace'] = [(key, str(value)) for key, value in context.items()]
|
||||
PDF_OPTIONS['margin-top'] = context.get('margin_vertical', DEFAULT_MARGIN_VERTICAL)
|
||||
PDF_OPTIONS['margin-bottom'] = context.get('margin_vertical', DEFAULT_MARGIN_VERTICAL)
|
||||
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...")
|
||||
render_ok = pdfkit.from_string(
|
||||
content,
|
||||
os.path.join(os.path.abspath(config['output_dir']), 'output.pdf'),
|
||||
options=PDF_OPTIONS,
|
||||
cover=FILE_NAME_FORMAT.format('cover'),
|
||||
toc=TOC_OPTIONS if config.get('toc') else {},
|
||||
cover_first=True
|
||||
)
|
||||
if not render_ok:
|
||||
raise PDFRenderException('Failed to render PDF. ' + render_ok)
|
||||
try:
|
||||
pdfkit.from_string(
|
||||
content,
|
||||
os.path.join(os.path.abspath(config['output_dir']), 'output.pdf'),
|
||||
options=PDF_OPTIONS,
|
||||
cover=FILE_NAME_FORMAT.format('cover'),
|
||||
toc=TOC_OPTIONS if config.get('toc') else {},
|
||||
cover_first=True
|
||||
)
|
||||
except OSError as e:
|
||||
raise PDFRenderException('Failed to render PDF. ' + str(e))
|
||||
return PDF_OPTIONS # mostly for testing
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import unittest
|
||||
import os
|
||||
from md_pdf.consts import TEMPLATES_DIR, STATIC_DIR
|
||||
from md_pdf.build.templates import FILE_NAME_FORMAT
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
|
||||
|
@ -26,6 +27,17 @@ class BaseTestCase(unittest.TestCase):
|
|||
except OSError:
|
||||
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):
|
||||
base_config = self.BASE_VALID_CONFIG.copy()
|
||||
for arg in args:
|
||||
|
@ -45,3 +57,8 @@ class BaseTestCase(unittest.TestCase):
|
|||
self.delete_templates()
|
||||
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
90
tests/test_pdf.py
Normal 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'))
|
||||
|
||||
|
||||
|
Reference in a new issue