mirror of
https://github.com/Kozea/WeasyPrint.git
synced 2024-08-17 00:20:42 +03:00
Clean more and more tests
This commit is contained in:
parent
cffa1f35d4
commit
6a35d779a1
2
.gitignore
vendored
2
.gitignore
vendored
@ -19,4 +19,4 @@
|
||||
|
||||
# Tests
|
||||
/weasyprint/tests/.cache
|
||||
/weasyprint/tests/results
|
||||
/weasyprint/tests/test_draw/results
|
||||
|
@ -9,41 +9,27 @@
|
||||
|
||||
"""
|
||||
|
||||
import contextlib
|
||||
import gzip
|
||||
import io
|
||||
import math
|
||||
import os
|
||||
import sys
|
||||
import threading
|
||||
import unicodedata
|
||||
import zlib
|
||||
from urllib.parse import urljoin, uses_relative
|
||||
|
||||
import cairocffi as cairo
|
||||
import py
|
||||
import pytest
|
||||
from pdfrw import PdfReader
|
||||
|
||||
from .. import CSS, HTML, __main__, default_url_fetcher
|
||||
from ..urls import path2url
|
||||
from .test_draw import B, _, assert_pixels_equal, image_to_pixels, r
|
||||
from .test_draw import assert_pixels_equal, image_to_pixels
|
||||
from .test_draw.test_draw import B, _, r
|
||||
from .testing_utils import (
|
||||
FakeHTML, assert_no_logs, capture_logs, http_server, resource_filename)
|
||||
|
||||
CHDIR_LOCK = threading.Lock()
|
||||
|
||||
|
||||
@contextlib.contextmanager
|
||||
def chdir(path):
|
||||
"""Change the current directory in a context manager."""
|
||||
with CHDIR_LOCK:
|
||||
old_dir = os.getcwd()
|
||||
try:
|
||||
os.chdir(path)
|
||||
yield
|
||||
finally:
|
||||
os.chdir(old_dir)
|
||||
|
||||
|
||||
def _test_resource(class_, basename, check, **kwargs):
|
||||
"""Common code for testing the HTML and CSS classes."""
|
||||
@ -63,13 +49,13 @@ def _test_resource(class_, basename, check, **kwargs):
|
||||
check(class_(file_obj=fd, **kwargs))
|
||||
with open(absolute_filename, 'rb') as fd:
|
||||
content = fd.read()
|
||||
with chdir(os.path.dirname(__file__)):
|
||||
relative_filename = os.path.join('resources', basename)
|
||||
check(class_(relative_filename, **kwargs))
|
||||
check(class_(string=content, base_url=relative_filename, **kwargs))
|
||||
encoding = kwargs.get('encoding') or 'utf8'
|
||||
check(class_(string=content.decode(encoding), # unicode
|
||||
base_url=relative_filename, **kwargs))
|
||||
py.path.local(os.path.dirname(__file__)).chdir()
|
||||
relative_filename = os.path.join('resources', basename)
|
||||
check(class_(relative_filename, **kwargs))
|
||||
check(class_(string=content, base_url=relative_filename, **kwargs))
|
||||
encoding = kwargs.get('encoding') or 'utf8'
|
||||
check(class_(string=content.decode(encoding), # unicode
|
||||
base_url=relative_filename, **kwargs))
|
||||
with pytest.raises(TypeError):
|
||||
class_(filename='foo', url='bar')
|
||||
|
||||
@ -90,38 +76,89 @@ def _assert_equivalent_pdf(pdf_bytes1, pdf_bytes2):
|
||||
assert page1.BleedBox == page2.BleedBox
|
||||
|
||||
|
||||
def _check_doc1(html, has_base_url=True):
|
||||
"""Check that a parsed HTML document looks like resources/doc1.html"""
|
||||
root = html.etree_element
|
||||
assert root.tag == 'html'
|
||||
assert [child.tag for child in root] == ['head', 'body']
|
||||
_head, body = root
|
||||
assert [child.tag for child in body] == ['h1', 'p', 'ul', 'div']
|
||||
h1, p, ul, div = body
|
||||
assert h1.text == 'WeasyPrint test document (with Ünicōde)'
|
||||
if has_base_url:
|
||||
url = urljoin(html.base_url, 'pattern.png')
|
||||
assert url.startswith('file:')
|
||||
assert url.endswith('weasyprint/tests/resources/pattern.png')
|
||||
else:
|
||||
assert html.base_url is None
|
||||
|
||||
|
||||
def _run(args, stdin=b''):
|
||||
stdin = io.BytesIO(stdin)
|
||||
stdout = io.BytesIO()
|
||||
try:
|
||||
__main__.HTML = FakeHTML
|
||||
__main__.main(args.split(), stdin=stdin, stdout=stdout)
|
||||
finally:
|
||||
__main__.HTML = HTML
|
||||
return stdout.getvalue()
|
||||
|
||||
|
||||
class _fake_file(object):
|
||||
def __init__(self):
|
||||
self.chunks = []
|
||||
|
||||
def write(self, data):
|
||||
self.chunks.append(bytes(data[:]))
|
||||
|
||||
def getvalue(self):
|
||||
return b''.join(self.chunks)
|
||||
|
||||
|
||||
def _png_size(result):
|
||||
png_bytes, width, height = result
|
||||
surface = cairo.ImageSurface.create_from_png(io.BytesIO(png_bytes))
|
||||
assert (surface.get_width(), surface.get_height()) == (width, height)
|
||||
return width, height
|
||||
|
||||
|
||||
def _round_meta(pages):
|
||||
"""Eliminate errors of floating point arithmetic for metadata.
|
||||
(eg. 49.99999999999994 instead of 50)
|
||||
|
||||
"""
|
||||
for page in pages:
|
||||
anchors = page.anchors
|
||||
for anchor_name, (pos_x, pos_y) in anchors.items():
|
||||
anchors[anchor_name] = round(pos_x, 6), round(pos_y, 6)
|
||||
links = page.links
|
||||
for i, link in enumerate(links):
|
||||
link_type, target, (pos_x, pos_y, width, height) = link
|
||||
link = (
|
||||
link_type, target, (round(pos_x, 6), round(pos_y, 6),
|
||||
round(width, 6), round(height, 6)))
|
||||
links[i] = link
|
||||
bookmarks = page.bookmarks
|
||||
for i, (level, label, (pos_x, pos_y)) in enumerate(bookmarks):
|
||||
bookmarks[i] = level, label, (round(pos_x, 6), round(pos_y, 6))
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
def test_html_parsing():
|
||||
"""Test the constructor for the HTML class."""
|
||||
def check_doc1(html, has_base_url=True):
|
||||
"""Check that a parsed HTML document looks like resources/doc1.html"""
|
||||
root = html.etree_element
|
||||
assert root.tag == 'html'
|
||||
assert [child.tag for child in root] == ['head', 'body']
|
||||
_head, body = root
|
||||
assert [child.tag for child in body] == ['h1', 'p', 'ul', 'div']
|
||||
h1, p, ul, div = body
|
||||
assert h1.text == 'WeasyPrint test document (with Ünicōde)'
|
||||
if has_base_url:
|
||||
url = urljoin(html.base_url, 'pattern.png')
|
||||
assert url.startswith('file:')
|
||||
assert url.endswith('weasyprint/tests/resources/pattern.png')
|
||||
else:
|
||||
assert html.base_url is None
|
||||
|
||||
_test_resource(FakeHTML, 'doc1.html', check_doc1)
|
||||
_test_resource(FakeHTML, 'doc1_UTF-16BE.html', check_doc1,
|
||||
_test_resource(FakeHTML, 'doc1.html', _check_doc1)
|
||||
_test_resource(FakeHTML, 'doc1_UTF-16BE.html', _check_doc1,
|
||||
encoding='UTF-16BE')
|
||||
|
||||
with chdir(os.path.dirname(__file__)):
|
||||
filename = os.path.join('resources', 'doc1.html')
|
||||
with open(filename) as fd:
|
||||
string = fd.read()
|
||||
check_doc1(FakeHTML(string=string, base_url=filename))
|
||||
check_doc1(FakeHTML(string=string), has_base_url=False)
|
||||
string_with_meta = string.replace(
|
||||
'<meta', '<base href="resources/"><meta')
|
||||
check_doc1(FakeHTML(string=string_with_meta, base_url='.'))
|
||||
py.path.local(os.path.dirname(__file__)).chdir()
|
||||
filename = os.path.join('resources', 'doc1.html')
|
||||
with open(filename) as fd:
|
||||
string = fd.read()
|
||||
_check_doc1(FakeHTML(string=string, base_url=filename))
|
||||
_check_doc1(FakeHTML(string=string), has_base_url=False)
|
||||
string_with_meta = string.replace(
|
||||
'<meta', '<base href="resources/"><meta')
|
||||
_check_doc1(FakeHTML(string=string_with_meta, base_url='.'))
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
@ -226,23 +263,13 @@ def test_python_render(tmpdir):
|
||||
pdf_bytes = html.write_pdf(stylesheets=[css])
|
||||
assert png_bytes.startswith(b'\211PNG\r\n\032\n')
|
||||
assert pdf_bytes.startswith(b'%PDF')
|
||||
|
||||
check_png_pattern(png_bytes)
|
||||
# TODO: check PDF content? How?
|
||||
|
||||
class fake_file(object):
|
||||
def __init__(self):
|
||||
self.chunks = []
|
||||
|
||||
def write(self, data):
|
||||
self.chunks.append(bytes(data[:]))
|
||||
|
||||
def getvalue(self):
|
||||
return b''.join(self.chunks)
|
||||
png_file = fake_file()
|
||||
png_file = _fake_file()
|
||||
html.write_png(png_file, stylesheets=[css])
|
||||
assert png_file.getvalue() == png_bytes
|
||||
pdf_file = fake_file()
|
||||
pdf_file = _fake_file()
|
||||
html.write_pdf(pdf_file, stylesheets=[css])
|
||||
_assert_equivalent_pdf(pdf_file.getvalue(), pdf_bytes)
|
||||
|
||||
@ -282,7 +309,6 @@ def test_python_render(tmpdir):
|
||||
|
||||
@assert_no_logs
|
||||
def test_command_line_render(tmpdir):
|
||||
"""Test rendering with the command-line API."""
|
||||
css = b'''
|
||||
@page { margin: 2px; size: 8px; background: #fff }
|
||||
@media screen { img { transform: rotate(-90deg) } }
|
||||
@ -292,30 +318,20 @@ def test_command_line_render(tmpdir):
|
||||
combined = b'<style>' + css + b'</style>' + html
|
||||
linked = b'<link rel=stylesheet href=style.css>' + html
|
||||
|
||||
with chdir(resource_filename('')):
|
||||
# Reference
|
||||
html_obj = FakeHTML(string=combined, base_url='dummy.html')
|
||||
pdf_bytes = html_obj.write_pdf()
|
||||
png_bytes = html_obj.write_png()
|
||||
x2_png_bytes = html_obj.write_png(resolution=192)
|
||||
rotated_png_bytes = FakeHTML(string=combined, base_url='dummy.html',
|
||||
media_type='screen').write_png()
|
||||
empty_png_bytes = FakeHTML(
|
||||
string=b'<style>' + css + b'</style>').write_png()
|
||||
py.path.local(resource_filename('')).chdir()
|
||||
# Reference
|
||||
html_obj = FakeHTML(string=combined, base_url='dummy.html')
|
||||
pdf_bytes = html_obj.write_pdf()
|
||||
png_bytes = html_obj.write_png()
|
||||
x2_png_bytes = html_obj.write_png(resolution=192)
|
||||
rotated_png_bytes = FakeHTML(string=combined, base_url='dummy.html',
|
||||
media_type='screen').write_png()
|
||||
empty_png_bytes = FakeHTML(
|
||||
string=b'<style>' + css + b'</style>').write_png()
|
||||
check_png_pattern(png_bytes)
|
||||
check_png_pattern(rotated_png_bytes, rotated=True)
|
||||
check_png_pattern(empty_png_bytes, blank=True)
|
||||
|
||||
def run(args, stdin=b''):
|
||||
stdin = io.BytesIO(stdin)
|
||||
stdout = io.BytesIO()
|
||||
try:
|
||||
__main__.HTML = FakeHTML
|
||||
__main__.main(args.split(), stdin=stdin, stdout=stdout)
|
||||
finally:
|
||||
__main__.HTML = HTML
|
||||
return stdout.getvalue()
|
||||
|
||||
tmpdir.chdir()
|
||||
with open(resource_filename('pattern.png'), 'rb') as pattern_fd:
|
||||
pattern_bytes = pattern_fd.read()
|
||||
@ -327,72 +343,72 @@ def test_command_line_render(tmpdir):
|
||||
tmpdir.join('linked.html').write_binary(linked)
|
||||
tmpdir.join('style.css').write_binary(css)
|
||||
|
||||
run('combined.html out1.png')
|
||||
run('combined.html out2.pdf')
|
||||
_run('combined.html out1.png')
|
||||
_run('combined.html out2.pdf')
|
||||
assert tmpdir.join('out1.png').read_binary() == png_bytes
|
||||
_assert_equivalent_pdf(tmpdir.join('out2.pdf').read_binary(), pdf_bytes)
|
||||
|
||||
run('combined-UTF-16BE.html out3.png --encoding UTF-16BE')
|
||||
_run('combined-UTF-16BE.html out3.png --encoding UTF-16BE')
|
||||
assert tmpdir.join('out3.png').read_binary() == png_bytes
|
||||
|
||||
run(tmpdir.join('combined.html').strpath + ' out4.png')
|
||||
_run(tmpdir.join('combined.html').strpath + ' out4.png')
|
||||
assert tmpdir.join('out4.png').read_binary() == png_bytes
|
||||
|
||||
run(path2url(tmpdir.join('combined.html')) + ' out5.png')
|
||||
_run(path2url(tmpdir.join('combined.html')) + ' out5.png')
|
||||
assert tmpdir.join('out5.png').read_binary() == png_bytes
|
||||
|
||||
run('linked.html out6.png') # test relative URLs
|
||||
_run('linked.html out6.png') # test relative URLs
|
||||
assert tmpdir.join('out6.png').read_binary() == png_bytes
|
||||
|
||||
run('combined.html out7 -f png')
|
||||
run('combined.html out8 --format pdf')
|
||||
_run('combined.html out7 -f png')
|
||||
_run('combined.html out8 --format pdf')
|
||||
assert tmpdir.join('out7').read_binary() == png_bytes
|
||||
_assert_equivalent_pdf(tmpdir.join('out8').read_binary(), pdf_bytes)
|
||||
|
||||
run('no_css.html out9.png')
|
||||
run('no_css.html out10.png -s style.css')
|
||||
_run('no_css.html out9.png')
|
||||
_run('no_css.html out10.png -s style.css')
|
||||
assert tmpdir.join('out9.png').read_binary() != png_bytes
|
||||
assert tmpdir.join('out10.png').read_binary() == png_bytes
|
||||
|
||||
stdout = run('--format png combined.html -')
|
||||
stdout = _run('--format png combined.html -')
|
||||
assert stdout == png_bytes
|
||||
|
||||
run('- out11.png', stdin=combined)
|
||||
_run('- out11.png', stdin=combined)
|
||||
check_png_pattern(tmpdir.join('out11.png').read_binary())
|
||||
assert tmpdir.join('out11.png').read_binary() == png_bytes
|
||||
|
||||
stdout = run('--format png - -', stdin=combined)
|
||||
stdout = _run('--format png - -', stdin=combined)
|
||||
assert stdout == png_bytes
|
||||
|
||||
run('combined.html out13.png --media-type screen')
|
||||
run('combined.html out12.png -m screen')
|
||||
run('linked.html out14.png -m screen')
|
||||
_run('combined.html out13.png --media-type screen')
|
||||
_run('combined.html out12.png -m screen')
|
||||
_run('linked.html out14.png -m screen')
|
||||
assert tmpdir.join('out12.png').read_binary() == rotated_png_bytes
|
||||
assert tmpdir.join('out13.png').read_binary() == rotated_png_bytes
|
||||
assert tmpdir.join('out14.png').read_binary() == rotated_png_bytes
|
||||
|
||||
stdout = run('-f pdf combined.html -')
|
||||
stdout = _run('-f pdf combined.html -')
|
||||
assert stdout.count(b'attachment') == 0
|
||||
stdout = run('-f pdf -a pattern.png combined.html -')
|
||||
stdout = _run('-f pdf -a pattern.png combined.html -')
|
||||
assert stdout.count(b'attachment') == 1
|
||||
stdout = run('-f pdf -a style.css -a pattern.png combined.html -')
|
||||
stdout = _run('-f pdf -a style.css -a pattern.png combined.html -')
|
||||
assert stdout.count(b'attachment') == 2
|
||||
|
||||
stdout = run('-f png -r 192 linked.html -')
|
||||
stdout = _run('-f png -r 192 linked.html -')
|
||||
assert stdout == x2_png_bytes
|
||||
stdout = run('-f png --resolution 192 linked.html -')
|
||||
assert run('linked.html - -f png --resolution 192') == x2_png_bytes
|
||||
stdout = _run('-f png --resolution 192 linked.html -')
|
||||
assert _run('linked.html - -f png --resolution 192') == x2_png_bytes
|
||||
assert stdout == x2_png_bytes
|
||||
|
||||
os.mkdir('subdirectory')
|
||||
os.chdir('subdirectory')
|
||||
py.path.local('subdirectory').chdir()
|
||||
with capture_logs() as logs:
|
||||
stdout = run('--format png - -', stdin=combined)
|
||||
stdout = _run('--format png - -', stdin=combined)
|
||||
assert len(logs) == 1
|
||||
assert logs[0].startswith('ERROR: Failed to load image')
|
||||
assert stdout == empty_png_bytes
|
||||
|
||||
stdout = run('--format png --base-url .. - -', stdin=combined)
|
||||
stdout = _run('--format png --base-url .. - -', stdin=combined)
|
||||
assert stdout == png_bytes
|
||||
|
||||
|
||||
@ -473,17 +489,11 @@ def test_low_level_api():
|
||||
assert (width, height) == (16, 16)
|
||||
check_png_pattern(png_bytes, x2=True)
|
||||
|
||||
def png_size(result):
|
||||
png_bytes, width, height = result
|
||||
surface = cairo.ImageSurface.create_from_png(io.BytesIO(png_bytes))
|
||||
assert (surface.get_width(), surface.get_height()) == (width, height)
|
||||
return width, height
|
||||
|
||||
document = html.render([css], enable_hinting=True)
|
||||
page, = document.pages
|
||||
assert (page.width, page.height) == (8, 8)
|
||||
# A resolution that is not multiple of 96:
|
||||
assert png_size(document.write_png(resolution=145.2)) == (13, 13)
|
||||
assert _png_size(document.write_png(resolution=145.2)) == (13, 13)
|
||||
|
||||
document = FakeHTML(string='''
|
||||
<style>
|
||||
@ -499,31 +509,10 @@ def test_low_level_api():
|
||||
|
||||
result = document.write_png()
|
||||
# (Max of both widths, Sum of both heights)
|
||||
assert png_size(result) == (6, 14)
|
||||
assert _png_size(result) == (6, 14)
|
||||
assert document.copy([page_1, page_2]).write_png() == result
|
||||
assert png_size(document.copy([page_1]).write_png()) == (5, 10)
|
||||
assert png_size(document.copy([page_2]).write_png()) == (6, 4)
|
||||
|
||||
|
||||
def round_meta(pages):
|
||||
"""Eliminate errors of floating point arithmetic for metadata.
|
||||
(eg. 49.99999999999994 instead of 50)
|
||||
|
||||
"""
|
||||
for page in pages:
|
||||
anchors = page.anchors
|
||||
for anchor_name, (pos_x, pos_y) in anchors.items():
|
||||
anchors[anchor_name] = round(pos_x, 6), round(pos_y, 6)
|
||||
links = page.links
|
||||
for i, link in enumerate(links):
|
||||
link_type, target, (pos_x, pos_y, width, height) = link
|
||||
link = (
|
||||
link_type, target, (round(pos_x, 6), round(pos_y, 6),
|
||||
round(width, 6), round(height, 6)))
|
||||
links[i] = link
|
||||
bookmarks = page.bookmarks
|
||||
for i, (level, label, (pos_x, pos_y)) in enumerate(bookmarks):
|
||||
bookmarks[i] = level, label, (round(pos_x, 6), round(pos_y, 6))
|
||||
assert _png_size(document.copy([page_1]).write_png()) == (5, 10)
|
||||
assert _png_size(document.copy([page_2]).write_png()) == (6, 4)
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
@ -531,7 +520,7 @@ def test_bookmarks():
|
||||
def assert_bookmarks(html, expected_by_page, expected_tree, round=False):
|
||||
document = FakeHTML(string=html).render()
|
||||
if round:
|
||||
round_meta(document.pages)
|
||||
_round_meta(document.pages)
|
||||
assert [p.bookmarks for p in document.pages] == expected_by_page
|
||||
assert document.make_bookmark_tree() == expected_tree
|
||||
assert_bookmarks('''
|
||||
@ -670,7 +659,7 @@ def test_links():
|
||||
with capture_logs() as logs:
|
||||
document = FakeHTML(string=html, base_url=base_url).render()
|
||||
if round:
|
||||
round_meta(document.pages)
|
||||
_round_meta(document.pages)
|
||||
resolved_links = list(document.resolve_links())
|
||||
assert len(logs) == len(warnings)
|
||||
for message, expected in zip(logs, warnings):
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -16,8 +16,7 @@ from .testing_utils import assert_no_logs, capture_logs
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
def test_font_face():
|
||||
"""Test the ``font-face`` rule."""
|
||||
def test_font_face_1():
|
||||
stylesheet = tinycss2.parse_stylesheet(
|
||||
'@font-face {'
|
||||
' font-family: Gentium Hard;'
|
||||
@ -32,6 +31,9 @@ def test_font_face():
|
||||
assert src == (
|
||||
'src', (('external', 'http://example.com/fonts/Gentium.woff'),))
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
def test_font_face_2():
|
||||
stylesheet = tinycss2.parse_stylesheet(
|
||||
'@font-face {'
|
||||
' font-family: "Fonty Smiley";'
|
||||
@ -53,6 +55,9 @@ def test_font_face():
|
||||
assert font_weight == ('font_weight', 200)
|
||||
assert font_stretch == ('font_stretch', 'condensed')
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
def test_font_face_3():
|
||||
stylesheet = tinycss2.parse_stylesheet(
|
||||
'@font-face {'
|
||||
' font-family: Gentium Hard;'
|
||||
@ -66,6 +71,9 @@ def test_font_face():
|
||||
assert font_family == ('font_family', 'Gentium Hard')
|
||||
assert src == ('src', (('local', None),))
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
def test_font_face_4():
|
||||
# See bug #487
|
||||
stylesheet = tinycss2.parse_stylesheet(
|
||||
'@font-face {'
|
||||
@ -81,8 +89,7 @@ def test_font_face():
|
||||
assert src == ('src', (('local', 'Gentium Hard'),))
|
||||
|
||||
|
||||
def test_bad_font_face():
|
||||
"""Test bad ``font-face`` rules."""
|
||||
def test_font_face_bad_1():
|
||||
stylesheet = tinycss2.parse_stylesheet(
|
||||
'@font-face {'
|
||||
' font-family: "Bad Font";'
|
||||
@ -108,6 +115,8 @@ def test_bad_font_face():
|
||||
'WARNING: Ignored `font-weight: bolder` at 1:111, invalid value.',
|
||||
'WARNING: Ignored `font-stretch: wrong` at 1:133, invalid value.']
|
||||
|
||||
|
||||
def test_font_face_bad_2():
|
||||
stylesheet = tinycss2.parse_stylesheet('@font-face{}')
|
||||
with capture_logs() as logs:
|
||||
descriptors = []
|
||||
@ -118,6 +127,8 @@ def test_bad_font_face():
|
||||
assert logs == [
|
||||
"WARNING: Missing src descriptor in '@font-face' rule at 1:1"]
|
||||
|
||||
|
||||
def test_font_face_bad_3():
|
||||
stylesheet = tinycss2.parse_stylesheet('@font-face{src: url(test.woff)}')
|
||||
with capture_logs() as logs:
|
||||
descriptors = []
|
||||
@ -128,6 +139,8 @@ def test_bad_font_face():
|
||||
assert logs == [
|
||||
"WARNING: Missing font-family descriptor in '@font-face' rule at 1:1"]
|
||||
|
||||
|
||||
def test_font_face_bad_4():
|
||||
stylesheet = tinycss2.parse_stylesheet('@font-face{font-family: test}')
|
||||
with capture_logs() as logs:
|
||||
descriptors = []
|
||||
@ -138,6 +151,8 @@ def test_bad_font_face():
|
||||
assert logs == [
|
||||
"WARNING: Missing src descriptor in '@font-face' rule at 1:1"]
|
||||
|
||||
|
||||
def test_font_face_bad_5():
|
||||
stylesheet = tinycss2.parse_stylesheet(
|
||||
'@font-face { font-family: test; src: wrong }')
|
||||
with capture_logs() as logs:
|
||||
@ -150,6 +165,8 @@ def test_bad_font_face():
|
||||
'WARNING: Ignored `src: wrong ` at 1:33, invalid value.',
|
||||
"WARNING: Missing src descriptor in '@font-face' rule at 1:1"]
|
||||
|
||||
|
||||
def test_font_face_bad_6():
|
||||
stylesheet = tinycss2.parse_stylesheet(
|
||||
'@font-face { font-family: good, bad; src: url(test.woff) }')
|
||||
with capture_logs() as logs:
|
||||
@ -162,6 +179,8 @@ def test_bad_font_face():
|
||||
'WARNING: Ignored `font-family: good, bad` at 1:14, invalid value.',
|
||||
"WARNING: Missing font-family descriptor in '@font-face' rule at 1:1"]
|
||||
|
||||
|
||||
def test_font_face_bad_7():
|
||||
stylesheet = tinycss2.parse_stylesheet(
|
||||
'@font-face { font-family: good, bad; src: really bad }')
|
||||
with capture_logs() as logs:
|
||||
|
@ -53,182 +53,224 @@ def test_not_print():
|
||||
def test_function():
|
||||
assert expand_to_dict('clip: rect(1px, 3em, auto, auto)') == {
|
||||
'clip': ((1, 'px'), (3, 'em'), 'auto', 'auto')}
|
||||
assert_invalid('clip: square(1px, 3em, auto, auto)')
|
||||
assert_invalid('clip: rect(1px, 3em, auto auto)', 'invalid')
|
||||
assert_invalid('clip: rect(1px, 3em, auto)')
|
||||
assert_invalid('clip: rect(1px, 3em / auto)')
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
def test_counters():
|
||||
assert expand_to_dict('counter-reset: foo bar 2 baz') == {
|
||||
'counter_reset': (('foo', 0), ('bar', 2), ('baz', 0))}
|
||||
assert expand_to_dict('counter-increment: foo bar 2 baz') == {
|
||||
'counter_increment': (('foo', 1), ('bar', 2), ('baz', 1))}
|
||||
assert expand_to_dict('counter-reset: foo') == {
|
||||
'counter_reset': (('foo', 0),)}
|
||||
assert expand_to_dict('counter-reset: FoO') == {
|
||||
'counter_reset': (('FoO', 0),)}
|
||||
assert expand_to_dict('counter-increment: foo bAr 2 Bar') == {
|
||||
'counter_increment': (('foo', 1), ('bAr', 2), ('Bar', 1))}
|
||||
assert expand_to_dict('counter-reset: none') == {
|
||||
'counter_reset': ()}
|
||||
assert expand_to_dict(
|
||||
'counter-reset: foo none', 'Invalid counter name') == {}
|
||||
assert expand_to_dict(
|
||||
'counter-reset: foo initial', 'Invalid counter name') == {}
|
||||
assert_invalid('counter-reset: foo 3px')
|
||||
assert_invalid('counter-reset: 3')
|
||||
@pytest.mark.parametrize('rule', (
|
||||
'clip: square(1px, 3em, auto, auto)',
|
||||
'clip: rect(1px, 3em, auto auto)',
|
||||
'clip: rect(1px, 3em, auto)',
|
||||
'clip: rect(1px, 3em / auto)',
|
||||
))
|
||||
def test_function_invalid(rule):
|
||||
assert_invalid(rule)
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
def test_spacing():
|
||||
assert expand_to_dict('letter-spacing: normal') == {
|
||||
'letter_spacing': 'normal'}
|
||||
assert expand_to_dict('letter-spacing: 3px') == {
|
||||
'letter_spacing': (3, 'px')}
|
||||
assert_invalid('letter-spacing: 3')
|
||||
assert expand_to_dict(
|
||||
'letter_spacing: normal', 'did you mean letter-spacing') == {}
|
||||
@pytest.mark.parametrize('rule, result', (
|
||||
('counter-reset: foo bar 2 baz', {
|
||||
'counter_reset': (('foo', 0), ('bar', 2), ('baz', 0))}),
|
||||
('counter-increment: foo bar 2 baz', {
|
||||
'counter_increment': (('foo', 1), ('bar', 2), ('baz', 1))}),
|
||||
('counter-reset: foo', {'counter_reset': (('foo', 0),)}),
|
||||
('counter-reset: FoO', {'counter_reset': (('FoO', 0),)}),
|
||||
('counter-increment: foo bAr 2 Bar', {
|
||||
'counter_increment': (('foo', 1), ('bAr', 2), ('Bar', 1))}),
|
||||
('counter-reset: none', {'counter_reset': ()}),
|
||||
))
|
||||
def test_counters(rule, result):
|
||||
assert expand_to_dict(rule) == result
|
||||
|
||||
assert expand_to_dict('word-spacing: normal') == {
|
||||
'word_spacing': 'normal'}
|
||||
assert expand_to_dict('word-spacing: 3px') == {
|
||||
'word_spacing': (3, 'px')}
|
||||
assert_invalid('word-spacing: 3')
|
||||
|
||||
@pytest.mark.parametrize('rule, warning, result', (
|
||||
('counter-reset: foo initial', 'Invalid counter name: initial.', {}),
|
||||
('counter-reset: foo none', 'Invalid counter name: none.', {}),
|
||||
))
|
||||
def test_counters_warning(rule, warning, result):
|
||||
assert expand_to_dict(rule, warning) == result
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
def test_decoration():
|
||||
assert expand_to_dict('text-decoration: none') == {
|
||||
'text_decoration': 'none'}
|
||||
assert expand_to_dict('text-decoration: overline') == {
|
||||
'text_decoration': frozenset(['overline'])}
|
||||
# blink is accepted but ignored
|
||||
assert expand_to_dict('text-decoration: overline blink line-through') == {
|
||||
'text_decoration': frozenset(['line-through', 'overline'])}
|
||||
@pytest.mark.parametrize('rule', (
|
||||
'counter-reset: foo 3px',
|
||||
'counter-reset: 3',
|
||||
))
|
||||
def test_counters_invalid(rule):
|
||||
assert_invalid(rule)
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
def test_size():
|
||||
assert expand_to_dict('size: 200px') == {
|
||||
'size': ((200, 'px'), (200, 'px'))}
|
||||
assert expand_to_dict('size: 200px 300pt') == {
|
||||
'size': ((200, 'px'), (300, 'pt'))}
|
||||
assert expand_to_dict('size: auto') == {
|
||||
'size': ((210, 'mm'), (297, 'mm'))}
|
||||
assert expand_to_dict('size: portrait') == {
|
||||
'size': ((210, 'mm'), (297, 'mm'))}
|
||||
assert expand_to_dict('size: landscape') == {
|
||||
'size': ((297, 'mm'), (210, 'mm'))}
|
||||
assert expand_to_dict('size: A3 portrait') == {
|
||||
'size': ((297, 'mm'), (420, 'mm'))}
|
||||
assert expand_to_dict('size: A3 landscape') == {
|
||||
'size': ((420, 'mm'), (297, 'mm'))}
|
||||
assert expand_to_dict('size: portrait A3') == {
|
||||
'size': ((297, 'mm'), (420, 'mm'))}
|
||||
assert expand_to_dict('size: landscape A3') == {
|
||||
'size': ((420, 'mm'), (297, 'mm'))}
|
||||
assert_invalid('size: A3 landscape A3')
|
||||
assert_invalid('size: A9')
|
||||
assert_invalid('size: foo')
|
||||
assert_invalid('size: foo bar')
|
||||
assert_invalid('size: 20%')
|
||||
@pytest.mark.parametrize('rule, result', (
|
||||
('letter-spacing: normal', {'letter_spacing': 'normal'}),
|
||||
('letter-spacing: 3px', {'letter_spacing': (3, 'px')}),
|
||||
('word-spacing: normal', {'word_spacing': 'normal'}),
|
||||
('word-spacing: 3px', {'word_spacing': (3, 'px')}),
|
||||
))
|
||||
def test_spacing(rule, result):
|
||||
assert expand_to_dict(rule) == result
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
def test_transforms():
|
||||
assert expand_to_dict('transform: none') == {
|
||||
'transform': ()}
|
||||
def test_spacing_warning():
|
||||
assert expand_to_dict(
|
||||
'transform: translate(6px) rotate(90deg)'
|
||||
) == {'transform': (('translate', ((6, 'px'), (0, 'px'))),
|
||||
('rotate', math.pi / 2))}
|
||||
assert expand_to_dict(
|
||||
'transform: translate(-4px, 0)'
|
||||
) == {'transform': (('translate', ((-4, 'px'), (0, None))),)}
|
||||
assert expand_to_dict(
|
||||
'transform: translate(6px, 20%)'
|
||||
) == {'transform': (('translate', ((6, 'px'), (20, '%'))),)}
|
||||
assert expand_to_dict(
|
||||
'transform: scale(2)'
|
||||
) == {'transform': (('scale', (2, 2)),)}
|
||||
assert_invalid('transform: translate(6px 20%)') # missing comma
|
||||
assert_invalid('transform: lipsumize(6px)')
|
||||
assert_invalid('transform: foo')
|
||||
assert_invalid('transform: scale(2) foo')
|
||||
assert_invalid('transform: 6px')
|
||||
'letter_spacing: normal', 'did you mean letter-spacing?') == {}
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
def test_expand_four_sides():
|
||||
"""Test the 4-value properties."""
|
||||
assert expand_to_dict('margin: inherit') == {
|
||||
@pytest.mark.parametrize('rule', (
|
||||
'letter-spacing: 3',
|
||||
'word-spacing: 3',
|
||||
))
|
||||
def test_spacing_invalid(rule):
|
||||
assert_invalid(rule)
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
@pytest.mark.parametrize('rule, result', (
|
||||
('text-decoration: none', {'text_decoration': 'none'}),
|
||||
('text-decoration: overline', {
|
||||
'text_decoration': frozenset(['overline'])}),
|
||||
('text-decoration: overline blink line-through', {
|
||||
'text_decoration': frozenset(['line-through', 'overline'])}),
|
||||
))
|
||||
def test_decoration(rule, result):
|
||||
assert expand_to_dict(rule) == result
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
@pytest.mark.parametrize('rule, result', (
|
||||
('size: 200px', {'size': ((200, 'px'), (200, 'px'))}),
|
||||
('size: 200px 300pt', {'size': ((200, 'px'), (300, 'pt'))}),
|
||||
('size: auto', {'size': ((210, 'mm'), (297, 'mm'))}),
|
||||
('size: portrait', {'size': ((210, 'mm'), (297, 'mm'))}),
|
||||
('size: landscape', {'size': ((297, 'mm'), (210, 'mm'))}),
|
||||
('size: A3 portrait', {'size': ((297, 'mm'), (420, 'mm'))}),
|
||||
('size: A3 landscape', {'size': ((420, 'mm'), (297, 'mm'))}),
|
||||
('size: portrait A3', {'size': ((297, 'mm'), (420, 'mm'))}),
|
||||
('size: landscape A3', {'size': ((420, 'mm'), (297, 'mm'))}),
|
||||
))
|
||||
def test_size(rule, result):
|
||||
assert expand_to_dict(rule) == result
|
||||
|
||||
|
||||
@pytest.mark.parametrize('rule', (
|
||||
'size: A3 landscape A3',
|
||||
'size: A9',
|
||||
'size: foo',
|
||||
'size: foo bar',
|
||||
'size: 20%',
|
||||
))
|
||||
def test_size_invalid(rule):
|
||||
assert_invalid(rule)
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
@pytest.mark.parametrize('rule, result', (
|
||||
('transform: none', {'transform': ()}),
|
||||
('transform: translate(6px) rotate(90deg)', {
|
||||
'transform': (
|
||||
('translate', ((6, 'px'), (0, 'px'))),
|
||||
('rotate', math.pi / 2))}),
|
||||
('transform: translate(-4px, 0)', {
|
||||
'transform': (('translate', ((-4, 'px'), (0, None))),)}),
|
||||
('transform: translate(6px, 20%)', {
|
||||
'transform': (('translate', ((6, 'px'), (20, '%'))),)}),
|
||||
('transform: scale(2)', {'transform': (('scale', (2, 2)),)}),
|
||||
))
|
||||
def test_transforms(rule, result):
|
||||
assert expand_to_dict(rule) == result
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
@pytest.mark.parametrize('rule', (
|
||||
'transform: translate(6px 20%)', # missing comma
|
||||
'transform: lipsumize(6px)',
|
||||
'transform: foo',
|
||||
'transform: scale(2) foo',
|
||||
'transform: 6px',
|
||||
))
|
||||
def test_transforms_invalid(rule):
|
||||
assert_invalid(rule)
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
@pytest.mark.parametrize('rule, result', (
|
||||
('margin: inherit', {
|
||||
'margin_top': 'inherit',
|
||||
'margin_right': 'inherit',
|
||||
'margin_bottom': 'inherit',
|
||||
'margin_left': 'inherit',
|
||||
}
|
||||
assert expand_to_dict('margin: 1em') == {
|
||||
}),
|
||||
('margin: 1em', {
|
||||
'margin_top': (1, 'em'),
|
||||
'margin_right': (1, 'em'),
|
||||
'margin_bottom': (1, 'em'),
|
||||
'margin_left': (1, 'em'),
|
||||
}
|
||||
assert expand_to_dict('margin: -1em auto 20%') == {
|
||||
}),
|
||||
('margin: -1em auto 20%', {
|
||||
'margin_top': (-1, 'em'),
|
||||
'margin_right': 'auto',
|
||||
'margin_bottom': (20, '%'),
|
||||
'margin_left': 'auto',
|
||||
}
|
||||
assert expand_to_dict('padding: 1em 0') == {
|
||||
}),
|
||||
('padding: 1em 0', {
|
||||
'padding_top': (1, 'em'),
|
||||
'padding_right': (0, None),
|
||||
'padding_bottom': (1, 'em'),
|
||||
'padding_left': (0, None),
|
||||
}
|
||||
assert expand_to_dict('padding: 1em 0 2%') == {
|
||||
}),
|
||||
('padding: 1em 0 2%', {
|
||||
'padding_top': (1, 'em'),
|
||||
'padding_right': (0, None),
|
||||
'padding_bottom': (2, '%'),
|
||||
'padding_left': (0, None),
|
||||
}
|
||||
assert expand_to_dict('padding: 1em 0 2em 5px') == {
|
||||
}),
|
||||
('padding: 1em 0 2em 5px', {
|
||||
'padding_top': (1, 'em'),
|
||||
'padding_right': (0, None),
|
||||
'padding_bottom': (2, 'em'),
|
||||
'padding_left': (5, 'px'),
|
||||
}
|
||||
assert expand_to_dict(
|
||||
'padding: 1 2 3 4 5',
|
||||
'Expected 1 to 4 token components got 5') == {}
|
||||
assert_invalid('margin: rgb(0, 0, 0)')
|
||||
assert_invalid('padding: auto')
|
||||
assert_invalid('padding: -12px')
|
||||
assert_invalid('border-width: -3em')
|
||||
assert_invalid('border-width: 12%')
|
||||
}),
|
||||
))
|
||||
def test_expand_four_sides(rule, result):
|
||||
assert expand_to_dict(rule) == result
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
def test_expand_borders():
|
||||
"""Test the ``border`` property."""
|
||||
assert expand_to_dict('border-top: 3px dotted red') == {
|
||||
def test_expand_four_sides_warning():
|
||||
assert expand_to_dict(
|
||||
'padding: 1 2 3 4 5', 'Expected 1 to 4 token components got 5') == {}
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
@pytest.mark.parametrize('rule', (
|
||||
'margin: rgb(0, 0, 0)',
|
||||
'padding: auto',
|
||||
'padding: -12px',
|
||||
'border-width: -3em',
|
||||
'border-width: 12%',
|
||||
))
|
||||
def test_expand_four_sides_invalid(rule):
|
||||
assert_invalid(rule)
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
@pytest.mark.parametrize('rule, result', (
|
||||
('border-top: 3px dotted red', {
|
||||
'border_top_width': (3, 'px'),
|
||||
'border_top_style': 'dotted',
|
||||
'border_top_color': (1, 0, 0, 1), # red
|
||||
}
|
||||
assert expand_to_dict('border-top: 3px dotted') == {
|
||||
}),
|
||||
('border-top: 3px dotted', {
|
||||
'border_top_width': (3, 'px'),
|
||||
'border_top_style': 'dotted',
|
||||
}
|
||||
assert expand_to_dict('border-top: 3px red') == {
|
||||
}),
|
||||
('border-top: 3px red', {
|
||||
'border_top_width': (3, 'px'),
|
||||
'border_top_color': (1, 0, 0, 1), # red
|
||||
}
|
||||
assert expand_to_dict('border-top: solid') == {
|
||||
'border_top_style': 'solid',
|
||||
}
|
||||
assert expand_to_dict('border: 6px dashed lime') == {
|
||||
}),
|
||||
('border-top: solid', {'border_top_style': 'solid'}),
|
||||
('border: 6px dashed lime', {
|
||||
'border_top_width': (6, 'px'),
|
||||
'border_top_style': 'dashed',
|
||||
'border_top_color': (0, 1, 0, 1), # lime
|
||||
@ -244,42 +286,63 @@ def test_expand_borders():
|
||||
'border_right_width': (6, 'px'),
|
||||
'border_right_style': 'dashed',
|
||||
'border_right_color': (0, 1, 0, 1), # lime
|
||||
}
|
||||
}),
|
||||
))
|
||||
def test_expand_borders(rule, result):
|
||||
assert expand_to_dict(rule) == result
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
def test_expand_borders_invalid():
|
||||
assert_invalid('border: 6px dashed left')
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
def test_expand_list_style():
|
||||
"""Test the ``list_style`` property."""
|
||||
assert expand_to_dict('list-style: inherit') == {
|
||||
@pytest.mark.parametrize('rule, result', (
|
||||
('list-style: inherit', {
|
||||
'list_style_position': 'inherit',
|
||||
'list_style_image': 'inherit',
|
||||
'list_style_type': 'inherit',
|
||||
}
|
||||
assert expand_to_dict('list-style: url(../bar/lipsum.png)') == {
|
||||
}),
|
||||
('list-style: url(../bar/lipsum.png)', {
|
||||
'list_style_image': ('url', 'http://weasyprint.org/bar/lipsum.png'),
|
||||
}
|
||||
assert expand_to_dict('list-style: square') == {
|
||||
}),
|
||||
('list-style: square', {
|
||||
'list_style_type': 'square',
|
||||
}
|
||||
assert expand_to_dict('list-style: circle inside') == {
|
||||
}),
|
||||
('list-style: circle inside', {
|
||||
'list_style_position': 'inside',
|
||||
'list_style_type': 'circle',
|
||||
}
|
||||
assert expand_to_dict('list-style: none circle inside') == {
|
||||
}),
|
||||
('list-style: none circle inside', {
|
||||
'list_style_position': 'inside',
|
||||
'list_style_image': ('none', None),
|
||||
'list_style_type': 'circle',
|
||||
}
|
||||
assert expand_to_dict('list-style: none inside none') == {
|
||||
}),
|
||||
('list-style: none inside none', {
|
||||
'list_style_position': 'inside',
|
||||
'list_style_image': ('none', None),
|
||||
'list_style_type': 'none',
|
||||
}
|
||||
assert_invalid('list-style: none inside none none')
|
||||
assert_invalid('list-style: red')
|
||||
assert_invalid('list-style: circle disc',
|
||||
'got multiple type values in a list-style shorthand')
|
||||
}),
|
||||
))
|
||||
def test_expand_list_style(rule, result):
|
||||
assert expand_to_dict(rule) == result
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
def test_expand_list_style_warning():
|
||||
assert_invalid(
|
||||
'list-style: circle disc',
|
||||
'got multiple type values in a list-style shorthand')
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
@pytest.mark.parametrize('rule', (
|
||||
'list-style: none inside none none',
|
||||
'list-style: red',
|
||||
))
|
||||
def test_expand_list_style_invalid(rule):
|
||||
assert_invalid(rule)
|
||||
|
||||
|
||||
def assert_background(css, **expected):
|
||||
@ -296,7 +359,6 @@ def assert_background(css, **expected):
|
||||
|
||||
@assert_no_logs
|
||||
def test_expand_background():
|
||||
"""Test the ``background`` property."""
|
||||
assert_background('red', background_color=(1, 0, 0, 1))
|
||||
assert_background(
|
||||
'url(lipsum.png)',
|
||||
|
File diff suppressed because it is too large
Load Diff
152
weasyprint/tests/test_draw/__init__.py
Normal file
152
weasyprint/tests/test_draw/__init__.py
Normal file
@ -0,0 +1,152 @@
|
||||
"""
|
||||
weasyprint.tests.test_draw
|
||||
--------------------------
|
||||
|
||||
Test the final, drawn results and compare PNG images pixel per pixel.
|
||||
|
||||
:copyright: Copyright 2011-2018 Simon Sapin and contributors, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import cairocffi as cairo
|
||||
|
||||
from ..testing_utils import FakeHTML, resource_filename
|
||||
|
||||
|
||||
# RGBA to native-endian ARGB
|
||||
as_pixel = (
|
||||
lambda x: x[:-1][::-1] + x[-1:]
|
||||
if sys.byteorder == 'little' else
|
||||
lambda x: x[-1:] + x[:-1])
|
||||
|
||||
_ = as_pixel(b'\xff\xff\xff\xff') # white
|
||||
R = as_pixel(b'\xff\x00\x00\xff') # red
|
||||
B = as_pixel(b'\x00\x00\xff\xff') # blue
|
||||
G = as_pixel(b'\x00\xff\x00\xff') # lime green
|
||||
V = as_pixel(b'\xBF\x00\x40\xff') # Average of 1*B and 3*r.
|
||||
S = as_pixel(b'\xff\x3f\x3f\xff') # r above r above #fff
|
||||
r = as_pixel(b'\xff\x00\x00\xff') # red
|
||||
g = as_pixel(b'\x00\x80\x00\xff') # half green
|
||||
b = as_pixel(b'\x00\x00\x80\xff') # half blue
|
||||
v = as_pixel(b'\x80\x00\x80\xff') # Average of B and r.
|
||||
a = as_pixel(b'\x00\x00\xfe\xff') # JPG is lossy...
|
||||
p = as_pixel(b'\xc0\x00\x3f\xff') # r above r above B above #fff.
|
||||
|
||||
|
||||
def assert_pixels(name, expected_width, expected_height, expected_pixels,
|
||||
html):
|
||||
"""Helper testing the size of the image and the pixels values."""
|
||||
assert len(expected_pixels) == expected_height
|
||||
assert len(expected_pixels[0]) == expected_width * 4
|
||||
expected_raw = b''.join(expected_pixels)
|
||||
_doc, pixels = html_to_pixels(name, expected_width, expected_height, html)
|
||||
assert_pixels_equal(
|
||||
name, expected_width, expected_height, pixels, expected_raw)
|
||||
|
||||
|
||||
def assert_same_rendering(expected_width, expected_height, documents,
|
||||
tolerance=0):
|
||||
"""Render HTML documents to PNG and check that they render the same.
|
||||
|
||||
Each document is passed as a (name, html_source) tuple.
|
||||
|
||||
"""
|
||||
pixels_list = []
|
||||
|
||||
for name, html in documents:
|
||||
_doc, pixels = html_to_pixels(
|
||||
name, expected_width, expected_height, html)
|
||||
pixels_list.append((name, pixels))
|
||||
|
||||
_name, reference = pixels_list[0]
|
||||
for name, pixels in pixels_list[1:]:
|
||||
assert_pixels_equal(name, expected_width, expected_height,
|
||||
reference, pixels, tolerance)
|
||||
|
||||
|
||||
def assert_different_renderings(expected_width, expected_height, documents):
|
||||
"""Render HTML documents to PNG and check that they don't render the same.
|
||||
|
||||
Each document is passed as a (name, html_source) tuple.
|
||||
|
||||
"""
|
||||
pixels_list = []
|
||||
|
||||
for name, html in documents:
|
||||
_doc, pixels = html_to_pixels(
|
||||
name, expected_width, expected_height, html)
|
||||
pixels_list.append((name, pixels))
|
||||
|
||||
for i, (name_1, pixels_1) in enumerate(pixels_list):
|
||||
for name_2, pixels_2 in pixels_list[i + 1:]:
|
||||
if pixels_1 == pixels_2: # pragma: no cover
|
||||
write_png(name_1, pixels_1, expected_width, expected_height)
|
||||
# Same as "assert pixels_1 != pixels_2" but the output of
|
||||
# the assert hook would be gigantic and useless.
|
||||
assert False, '%s and %s are the same' % (name_1, name_2)
|
||||
|
||||
|
||||
def write_png(basename, pixels, width, height): # pragma: no cover
|
||||
"""Take a pixel matrix and write a PNG file."""
|
||||
directory = os.path.join(os.path.dirname(__file__), 'results')
|
||||
if not os.path.isdir(directory):
|
||||
os.mkdir(directory)
|
||||
filename = os.path.join(directory, basename + '.png')
|
||||
cairo.ImageSurface(
|
||||
cairo.FORMAT_ARGB32, width, height,
|
||||
data=bytearray(pixels), stride=width * 4
|
||||
).write_to_png(filename)
|
||||
|
||||
|
||||
def html_to_pixels(name, expected_width, expected_height, html):
|
||||
"""Render an HTML document to PNG, checks its size and return pixel data.
|
||||
|
||||
Also return the document to aid debugging.
|
||||
|
||||
"""
|
||||
document = FakeHTML(
|
||||
string=html,
|
||||
# Dummy filename, but in the right directory.
|
||||
base_url=resource_filename('<test>'))
|
||||
pixels = document_to_pixels(
|
||||
document, name, expected_width, expected_height)
|
||||
return document, pixels
|
||||
|
||||
|
||||
def document_to_pixels(document, name, expected_width, expected_height):
|
||||
"""Render an HTML document to PNG, check its size and return pixel data."""
|
||||
surface = document.write_image_surface()
|
||||
return image_to_pixels(surface, expected_width, expected_height)
|
||||
|
||||
|
||||
def image_to_pixels(surface, width, height):
|
||||
assert (surface.get_width(), surface.get_height()) == (width, height)
|
||||
# RGB24 is actually the same as ARGB32, with A unused.
|
||||
assert surface.get_format() in (cairo.FORMAT_ARGB32, cairo.FORMAT_RGB24)
|
||||
pixels = surface.get_data()[:]
|
||||
assert len(pixels) == width * height * 4
|
||||
return pixels
|
||||
|
||||
|
||||
def assert_pixels_equal(name, width, height, raw, expected_raw, tolerance=0):
|
||||
"""Take 2 matrices of pixels and assert that they are the same."""
|
||||
if raw != expected_raw: # pragma: no cover
|
||||
for i, (value, expected) in enumerate(zip(raw, expected_raw)):
|
||||
if abs(value - expected) > tolerance:
|
||||
write_png(name, raw, width, height)
|
||||
write_png(name + '.expected', expected_raw,
|
||||
width, height)
|
||||
pixel_n = i // 4
|
||||
x = pixel_n // width
|
||||
y = pixel_n % width
|
||||
i % 4
|
||||
pixel = tuple(list(raw[i:i + 4]))
|
||||
expected_pixel = tuple(list(
|
||||
expected_raw[i:i + 4]))
|
||||
assert 0, (
|
||||
'Pixel (%i, %i) in %s: expected rgba%s, got rgba%s'
|
||||
% (x, y, name, expected_pixel, pixel))
|
2393
weasyprint/tests/test_draw/test_draw.py
Normal file
2393
weasyprint/tests/test_draw/test_draw.py
Normal file
File diff suppressed because it is too large
Load Diff
530
weasyprint/tests/test_draw/test_table.py
Normal file
530
weasyprint/tests/test_draw/test_table.py
Normal file
@ -0,0 +1,530 @@
|
||||
"""
|
||||
weasyprint.tests.test_draw.test_tables
|
||||
--------------------------------------
|
||||
|
||||
Test the drawn tables.
|
||||
|
||||
:copyright: Copyright 2011-2014 Simon Sapin and contributors, see AUTHORS.
|
||||
:license: BSD, see LICENSE for details.
|
||||
|
||||
"""
|
||||
|
||||
from . import B, R, S, _, as_pixel, assert_pixels, p
|
||||
from ...html import HTML_HANDLERS
|
||||
from ..testing_utils import assert_no_logs, requires
|
||||
|
||||
# rgba(255, 0, 0, 0.5) above #fff
|
||||
r = as_pixel(b'\xff\x7f\x7f\xff')
|
||||
# rgba(0, 255, 0, 0.5) above #fff
|
||||
g = as_pixel(b'\x7f\xff\x7f\xff')
|
||||
# r above B above #fff.
|
||||
b = as_pixel(b'\x80\x00\x7f\xff')
|
||||
|
||||
# TODO: refactor colspan/rowspan into CSS:
|
||||
# td, th { column-span: attr(colspan integer) }
|
||||
HTML_HANDLERS['x-td'] = HTML_HANDLERS['td']
|
||||
HTML_HANDLERS['x-th'] = HTML_HANDLERS['th']
|
||||
tables_source = '''
|
||||
<style>
|
||||
@page { size: 28px; background: #fff }
|
||||
x-table { margin: 1px; padding: 1px; border-spacing: 1px;
|
||||
border: 1px solid transparent }
|
||||
x-td { width: 2px; height: 2px; padding: 1px;
|
||||
border: 1px solid transparent }
|
||||
%(extra_css)s
|
||||
</style>
|
||||
<x-table>
|
||||
<x-colgroup>
|
||||
<x-col></x-col>
|
||||
<x-col></x-col>
|
||||
</x-colgroup>
|
||||
<x-col></x-col>
|
||||
<x-tbody>
|
||||
<x-tr>
|
||||
<x-td></x-td>
|
||||
<x-td rowspan=2></x-td>
|
||||
<x-td></x-td>
|
||||
</x-tr>
|
||||
<x-tr>
|
||||
<x-td colspan=2></x-td>
|
||||
<x-td></x-td>
|
||||
</x-tr>
|
||||
</x-tbody>
|
||||
<x-tr>
|
||||
<x-td></x-td>
|
||||
<x-td></x-td>
|
||||
</x-tr>
|
||||
</x-table>
|
||||
'''
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
@requires('cairo', (1, 12, 0))
|
||||
def test_tables_1():
|
||||
assert_pixels('table_borders', 28, 28, [
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+_+_+_+_+r+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+r+S+r+r+r+r+S+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+_+_+_+_+_+_+r+_+_+_+_+S+_+r+_+_+_+_+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+_+_+_+_+_+_+r+_+_+_+_+S+_+r+_+_+_+_+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+_+_+_+_+_+_+r+_+_+_+_+S+_+r+_+_+_+_+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+_+_+_+_+_+_+r+_+_+_+_+S+_+r+_+_+_+_+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+r+S+S+S+S+S+S+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
], tables_source % {'extra_css': '''
|
||||
x-table { border-color: #00f; table-layout: fixed }
|
||||
x-td { border-color: rgba(255, 0, 0, 0.5) }
|
||||
'''})
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
@requires('cairo', (1, 12, 0))
|
||||
def test_tables_2():
|
||||
assert_pixels('table_collapsed_borders', 28, 28, [
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+r+r+r+r+r+_+_+_+_+r+r+r+r+r+B+B+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+_+_+_+_+_+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+_+_+_+_+_+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+_+_+_+_+_+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+_+_+_+_+_+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+r+r+r+r+r+r+r+r+r+r+r+r+r+r+B+B+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
], tables_source % {'extra_css': '''
|
||||
x-table { border: 2px solid #00f; table-layout: fixed;
|
||||
border-collapse: collapse }
|
||||
x-td { border-color: #ff7f7f }
|
||||
'''})
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
@requires('cairo', (1, 12, 0))
|
||||
def test_tables_3():
|
||||
assert_pixels('table_collapsed_borders_paged', 28, 52, [
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+_, # noqa
|
||||
_+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+r+r+r+r+r+_+_+_+_+r+r+r+r+r+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+_+_+_+_+_+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+_+_+_+_+_+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+_+_+_+_+_+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+_+_+_+_+_+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+r+r+r+r+r+r+r+r+r+r+r+r+r+r+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa
|
||||
_+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+_, # noqa
|
||||
_+g+_+B+B+r+r+r+r+r+r+r+r+r+r+r+r+r+r+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa
|
||||
_+g+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+g+_, # noqa
|
||||
_+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+g+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
], tables_source % {'extra_css': '''
|
||||
x-table { border: solid #00f; border-width: 8px 2px;
|
||||
table-layout: fixed; border-collapse: collapse }
|
||||
x-td { border-color: #ff7f7f }
|
||||
@page { size: 28px 26px; margin: 1px;
|
||||
border: 1px solid rgba(0, 255, 0, 0.5); }
|
||||
'''})
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
@requires('cairo', (1, 12, 0))
|
||||
def test_tables_4():
|
||||
assert_pixels('table_td_backgrounds', 28, 28, [
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+r+S+S+S+S+S+S+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+r+S+S+S+S+S+S+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+r+S+S+S+S+S+S+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+r+S+S+S+S+S+S+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+r+S+S+S+S+S+S+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+r+S+S+S+S+S+S+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
], tables_source % {'extra_css': '''
|
||||
x-table { border-color: #00f; table-layout: fixed }
|
||||
x-td { background: rgba(255, 0, 0, 0.5) }
|
||||
'''})
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
@requires('cairo', (1, 12, 0))
|
||||
def test_tables_5():
|
||||
assert_pixels('table_row_backgrounds', 28, 28, [
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+b+b+b+b+b+b+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+b+b+b+b+b+b+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+b+b+b+b+b+b+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+b+b+b+b+b+b+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+b+b+b+b+b+b+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+b+b+b+b+b+b+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+b+b+b+b+b+b+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
], tables_source % {'extra_css': '''
|
||||
x-table { border-color: #00f; table-layout: fixed }
|
||||
x-tbody { background: rgba(0, 0, 255, 1) }
|
||||
x-tr { background: rgba(255, 0, 0, 0.5) }
|
||||
'''})
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
@requires('cairo', (1, 12, 0))
|
||||
def test_tables_6():
|
||||
assert_pixels('table_column_backgrounds', 28, 28, [
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+b+b+b+b+b+b+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
], tables_source % {'extra_css': '''
|
||||
x-table { border-color: #00f; table-layout: fixed }
|
||||
x-colgroup { background: rgba(0, 0, 255, 1) }
|
||||
x-col { background: rgba(255, 0, 0, 0.5) }
|
||||
'''})
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
@requires('cairo', (1, 12, 0))
|
||||
def test_tables_7():
|
||||
assert_pixels('table_borders_and_row_backgrounds', 28, 28, [
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+b+b+b+b+b+b+_+_+B+_, # noqa
|
||||
_+B+_+_+b+B+B+B+B+b+_+b+B+B+B+B+b+_+b+B+B+B+B+b+_+_+B+_, # noqa
|
||||
_+B+_+_+b+B+B+B+B+b+_+b+B+B+B+B+b+_+b+B+B+B+B+b+_+_+B+_, # noqa
|
||||
_+B+_+_+b+B+B+B+B+b+_+b+B+B+B+B+b+_+b+B+B+B+B+b+_+_+B+_, # noqa
|
||||
_+B+_+_+b+B+B+B+B+b+_+b+B+B+B+B+b+_+b+B+B+B+B+b+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+b+B+B+B+B+b+_+b+b+b+b+b+b+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+b+B+B+B+B+b+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+r+p+b+b+b+b+p+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+_+_+_+_+_+_+b+B+B+B+B+p+_+r+_+_+_+_+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+_+_+_+_+_+_+b+B+B+B+B+p+_+r+_+_+_+_+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+_+_+_+_+_+_+b+B+B+B+B+p+_+r+_+_+_+_+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+_+_+_+_+_+_+b+B+B+B+B+p+_+r+_+_+_+_+r+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+r+p+p+p+p+p+p+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
], tables_source % {'extra_css': '''
|
||||
x-table { border-color: #00f; table-layout: fixed }
|
||||
x-tr:first-child { background: blue }
|
||||
x-td { border-color: rgba(255, 0, 0, 0.5) }
|
||||
'''})
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
@requires('cairo', (1, 12, 0))
|
||||
def test_tables_8():
|
||||
assert_pixels('table_borders_and_column_backgrounds', 28, 28, [
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+r+r+r+r+r+r+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+b+B+B+B+B+b+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+B+_, # noqa
|
||||
_+B+_+_+b+B+B+B+B+b+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+B+_, # noqa
|
||||
_+B+_+_+b+B+B+B+B+b+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+B+_, # noqa
|
||||
_+B+_+_+b+B+B+B+B+b+_+r+_+_+_+_+r+_+r+_+_+_+_+r+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+r+_+_+_+_+r+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+b+p+b+b+b+b+p+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+b+B+B+B+B+B+B+b+B+B+B+B+p+_+r+_+_+_+_+r+_+_+B+_, # noqa
|
||||
_+B+_+_+b+B+B+B+B+B+B+b+B+B+B+B+p+_+r+_+_+_+_+r+_+_+B+_, # noqa
|
||||
_+B+_+_+b+B+B+B+B+B+B+b+B+B+B+B+p+_+r+_+_+_+_+r+_+_+B+_, # noqa
|
||||
_+B+_+_+b+B+B+B+B+B+B+b+B+B+B+B+p+_+r+_+_+_+_+r+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+b+p+p+p+p+p+p+_+r+r+r+r+r+r+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+b+B+B+B+B+b+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+b+B+B+B+B+b+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+b+B+B+B+B+b+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+b+B+B+B+B+b+_+r+_+_+_+_+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+b+b+b+b+b+b+_+r+r+r+r+r+r+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+B+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
], tables_source % {'extra_css': '''
|
||||
x-table { border-color: #00f; table-layout: fixed }
|
||||
x-col:first-child { background: blue }
|
||||
x-td { border-color: rgba(255, 0, 0, 0.5) }
|
||||
'''})
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
@requires('cairo', (1, 12, 0))
|
||||
def test_tables_9():
|
||||
r = as_pixel(b'\xff\x00\x00\xff')
|
||||
assert_pixels('collapsed_border_thead', 22, 36, [
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+B+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+B+_, # noqa
|
||||
_+B+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+B+_, # noqa
|
||||
_+B+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+B+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa
|
||||
_+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa
|
||||
_+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa
|
||||
_+_+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+_+_, # noqa
|
||||
_+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa
|
||||
_+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa
|
||||
_+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa
|
||||
_+_+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+B+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+B+_, # noqa
|
||||
_+B+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+B+_, # noqa
|
||||
_+B+B+B+_+_+_+_+r+_+_+_+_+r+_+_+_+_+B+B+B+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa
|
||||
_+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa
|
||||
_+_+r+_+_+_+_+_+r+_+_+_+_+r+_+_+_+_+_+r+_+_, # noqa
|
||||
_+_+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+r+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
], '''
|
||||
<style>
|
||||
@page { size: 22px 18px; margin: 1px; background: #fff }
|
||||
td { border: 1px red solid; width: 4px; height: 3px; }
|
||||
</style>
|
||||
<table style="table-layout: fixed; border-collapse: collapse">
|
||||
<thead style="border: blue solid; border-width: 2px 3px;
|
||||
"><td></td><td></td><td></td></thead>
|
||||
<tr><td></td><td></td><td></td></tr>
|
||||
<tr><td></td><td></td><td></td></tr>
|
||||
<tr><td></td><td></td><td></td></tr>''')
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
@requires('cairo', (1, 12, 0))
|
||||
def test_tables_10():
|
||||
assert_pixels('collapsed_border_tfoot', 22, 36, [
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+R+R+R+R+R+R+R+R+R+R+R+R+R+R+R+R+R+R+_+_, # noqa
|
||||
_+_+R+_+_+_+_+_+R+_+_+_+_+R+_+_+_+_+_+R+_+_, # noqa
|
||||
_+_+R+_+_+_+_+_+R+_+_+_+_+R+_+_+_+_+_+R+_+_, # noqa
|
||||
_+_+R+_+_+_+_+_+R+_+_+_+_+R+_+_+_+_+_+R+_+_, # noqa
|
||||
_+_+R+R+R+R+R+R+R+R+R+R+R+R+R+R+R+R+R+R+_+_, # noqa
|
||||
_+_+R+_+_+_+_+_+R+_+_+_+_+R+_+_+_+_+_+R+_+_, # noqa
|
||||
_+_+R+_+_+_+_+_+R+_+_+_+_+R+_+_+_+_+_+R+_+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+B+B+B+_+_+_+_+R+_+_+_+_+R+_+_+_+_+B+B+B+_, # noqa
|
||||
_+B+B+B+_+_+_+_+R+_+_+_+_+R+_+_+_+_+B+B+B+_, # noqa
|
||||
_+B+B+B+_+_+_+_+R+_+_+_+_+R+_+_+_+_+B+B+B+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+R+R+R+R+R+R+R+R+R+R+R+R+R+R+R+R+R+R+_+_, # noqa
|
||||
_+_+R+_+_+_+_+_+R+_+_+_+_+R+_+_+_+_+_+R+_+_, # noqa
|
||||
_+_+R+_+_+_+_+_+R+_+_+_+_+R+_+_+_+_+_+R+_+_, # noqa
|
||||
_+_+R+_+_+_+_+_+R+_+_+_+_+R+_+_+_+_+_+R+_+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+B+B+B+_+_+_+_+R+_+_+_+_+R+_+_+_+_+B+B+B+_, # noqa
|
||||
_+B+B+B+_+_+_+_+R+_+_+_+_+R+_+_+_+_+B+B+B+_, # noqa
|
||||
_+B+B+B+_+_+_+_+R+_+_+_+_+R+_+_+_+_+B+B+B+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+B+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
], '''
|
||||
<style>
|
||||
@page { size: 22px 18px; margin: 1px; background: #fff }
|
||||
td { border: 1px red solid; width: 4px; height: 3px; }
|
||||
</style>
|
||||
<table style="table-layout: fixed; margin-left: 1px;
|
||||
border-collapse: collapse">
|
||||
<tr><td></td><td></td><td></td></tr>
|
||||
<tr><td></td><td></td><td></td></tr>
|
||||
<tr><td></td><td></td><td></td></tr>
|
||||
<tfoot style="border: blue solid; border-width: 2px 3px;
|
||||
"><td></td><td></td><td></td></tfoot>''')
|
||||
|
||||
|
||||
@assert_no_logs
|
||||
@requires('cairo', (1, 12, 0))
|
||||
def test_tables_11():
|
||||
# Segression test for inline table with collapsed border and alignment
|
||||
# rendering borders incorrectly
|
||||
# https://github.com/Kozea/WeasyPrint/issues/82
|
||||
assert_pixels('inline_text_align', 20, 10, [
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+R+R+R+R+R+R+R+R+R+R+R+_, # noqa
|
||||
_+_+_+_+_+_+_+_+R+_+_+_+_+R+_+_+_+_+R+_, # noqa
|
||||
_+_+_+_+_+_+_+_+R+_+_+_+_+R+_+_+_+_+R+_, # noqa
|
||||
_+_+_+_+_+_+_+_+R+_+_+_+_+R+_+_+_+_+R+_, # noqa
|
||||
_+_+_+_+_+_+_+_+R+R+R+R+R+R+R+R+R+R+R+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_+_, # noqa
|
||||
], '''
|
||||
<style>
|
||||
@page { size: 20px 10px; margin: 1px; background: #fff }
|
||||
body { text-align: right; font-size: 0 }
|
||||
table { display: inline-table; width: 11px }
|
||||
td { border: 1px red solid; width: 4px; height: 3px }
|
||||
</style>
|
||||
<table style="table-layout: fixed; border-collapse: collapse">
|
||||
<tr><td></td><td></td></tr>''')
|
@ -10,7 +10,7 @@
|
||||
"""
|
||||
|
||||
from .test_boxes import render_pages
|
||||
from .test_draw import requires
|
||||
from .test_draw.test_draw import requires
|
||||
from .testing_utils import assert_no_logs
|
||||
|
||||
|
||||
|
@ -12,7 +12,8 @@
|
||||
import pytest
|
||||
|
||||
from ..test_boxes import render_pages
|
||||
from ..test_draw import B, _, assert_pixels, r
|
||||
from ..test_draw import assert_pixels
|
||||
from ..test_draw.test_draw import B, _, r
|
||||
from ..testing_utils import assert_no_logs, capture_logs, requires
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user