1
1
mirror of https://github.com/Kozea/WeasyPrint.git synced 2024-10-04 07:57:52 +03:00
WeasyPrint/tests/layout/test_column.py
2021-11-10 21:20:30 +01:00

455 lines
14 KiB
Python

"""
weasyprint.tests.layout.column
------------------------------
Tests for multicolumn layout.
"""
import pytest
from ..testing_utils import assert_no_logs, render_pages
@assert_no_logs
@pytest.mark.parametrize('css', (
'columns: 4',
'columns: 100px',
'columns: 4 100px',
'columns: 100px 4',
'column-width: 100px',
'column-count: 4',
))
def test_columns(css):
page, = render_pages('''
<style>
@font-face { src: url(weasyprint.otf); font-family: weasyprint }
div { %s; column-gap: 0 }
body { margin: 0; font-family: weasyprint }
@page { margin: 0; size: 400px 1000px }
</style>
<div>
Ipsum dolor sit amet,
consectetur adipiscing elit.
Sed sollicitudin nibh
et turpis molestie tristique.
</div>
''' % css)
html, = page.children
body, = html.children
div, = body.children
columns = div.children
assert len(columns) == 4
assert [column.width for column in columns] == [100, 100, 100, 100]
assert [column.position_x for column in columns] == [0, 100, 200, 300]
assert [column.position_y for column in columns] == [0, 0, 0, 0]
@pytest.mark.parametrize('value, width', (
('normal', 16), # "normal" is 1em = 16px
('unknown', 16), # default value is normal
('15px', 15),
('40%', 16), # percentages are not allowed
('-1em', 16), # negative values are not allowed
))
def test_column_gap(value, width):
page, = render_pages('''
<style>
@font-face { src: url(weasyprint.otf); font-family: weasyprint }
div { columns: 3; column-gap: %s }
body { margin: 0; font-family: weasyprint }
@page { margin: 0; size: 300px 1000px }
</style>
<div>
Ipsum dolor sit amet,
consectetur adipiscing elit.
Sed sollicitudin nibh
et turpis molestie tristique.
</div>
''' % value)
html, = page.children
body, = html.children
div, = body.children
columns = div.children
assert len(columns) == 3
assert [column.width for column in columns] == (
3 * [100 - 2 * width / 3])
assert [column.position_x for column in columns] == (
[0, 100 + width / 3, 200 + 2 * width / 3])
assert [column.position_y for column in columns] == [0, 0, 0]
@assert_no_logs
def test_column_span_1():
page, = render_pages('''
<style>
@font-face { src: url(weasyprint.otf); font-family: weasyprint }
body { margin: 0; font-family: weasyprint; line-height: 1 }
div { columns: 2; width: 10em; column-gap: 0 }
section { column-span: all; margin: 1em 0 }
</style>
<div>
abc def
<section>test</section>
<section>test</section>
ghi jkl
</div>
''')
html, = page.children
body, = html.children
div, = body.children
column1, column2, section1, section2, column3, column4 = div.children
assert (column1.position_x, column1.position_y) == (0, 0)
assert (column2.position_x, column2.position_y) == (5 * 16, 0)
assert (section1.content_box_x(), section1.content_box_y()) == (0, 32)
assert (section2.content_box_x(), section2.content_box_y()) == (0, 64)
assert (column3.position_x, column3.position_y) == (0, 96)
assert (column4.position_x, column4.position_y) == (5 * 16, 96)
assert column1.height == 16
@assert_no_logs
def test_column_span_2():
page, = render_pages('''
<style>
@font-face { src: url(weasyprint.otf); font-family: weasyprint }
body { margin: 0; font-family: weasyprint; line-height: 1 }
div { columns: 2; width: 10em; column-gap: 0 }
section { column-span: all; margin: 1em 0 }
</style>
<div>
<section>test</section>
abc def
ghi jkl
mno pqr
stu vwx
</div>
''')
html, = page.children
body, = html.children
div, = body.children
section1, column1, column2 = div.children
assert (section1.content_box_x(), section1.content_box_y()) == (0, 16)
assert (column1.position_x, column1.position_y) == (0, 3 * 16)
assert (column2.position_x, column2.position_y) == (5 * 16, 3 * 16)
assert column1.height == column2.height == 16 * 4
@assert_no_logs
def test_columns_multipage():
page1, page2 = render_pages('''
<style>
@font-face { src: url(weasyprint.otf); font-family: weasyprint }
div { columns: 2; column-gap: 1px }
body { margin: 0; font-family: weasyprint;
font-size: 1px; line-height: 1px }
@page { margin: 0; size: 3px 2px }
</style>
<div>a b c d e f g</div>
''')
html, = page1.children
body, = html.children
div, = body.children
columns = div.children
assert len(columns) == 2
assert len(columns[0].children) == 2
assert len(columns[1].children) == 2
columns[0].children[0].children[0].text == 'a'
columns[0].children[1].children[0].text == 'b'
columns[1].children[0].children[0].text == 'c'
columns[1].children[1].children[0].text == 'd'
html, = page2.children
body, = html.children
div, = body.children
columns = div.children
assert len(columns) == 2
assert len(columns[0].children) == 2
assert len(columns[1].children) == 1
columns[0].children[0].children[0].text == 'e'
columns[0].children[1].children[0].text == 'f'
columns[1].children[0].children[0].text == 'g'
@assert_no_logs
def test_columns_not_enough_content():
page, = render_pages('''
<style>
@font-face { src: url(weasyprint.otf); font-family: weasyprint }
div { columns: 5; column-gap: 0 }
body { margin: 0; font-family: weasyprint }
@page { margin: 0; size: 5px; font-size: 1px }
</style>
<div>a b c</div>
''')
html, = page.children
body, = html.children
div, = body.children
assert div.width == 5
columns = div.children
assert len(columns) == 3
assert [column.width for column in columns] == [1, 1, 1]
assert [column.position_x for column in columns] == [0, 1, 2]
assert [column.position_y for column in columns] == [0, 0, 0]
@assert_no_logs
def test_columns_empty():
page, = render_pages('''
<style>
@font-face { src: url(weasyprint.otf); font-family: weasyprint }
div { columns: 3 }
body { margin: 0; font-family: weasyprint }
@page { margin: 0; size: 3px; font-size: 1px }
</style>
<div></div>
''')
html, = page.children
body, = html.children
div, = body.children
assert div.width == 3
assert div.height == 0
columns = div.children
assert len(columns) == 0
@assert_no_logs
@pytest.mark.parametrize('prop', ('height', 'min-height'))
def test_columns_fixed_height(prop):
# TODO: we should test when the height is too small
page, = render_pages('''
<style>
@font-face { src: url(weasyprint.otf); font-family: weasyprint }
div { columns: 4; column-gap: 0; %s: 10px }
body { margin: 0; font-family: weasyprint; line-height: 1px }
@page { margin: 0; size: 4px 50px; font-size: 1px }
</style>
<div>a b c</div>
''' % prop)
html, = page.children
body, = html.children
div, = body.children
assert div.width == 4
columns = div.children
assert len(columns) == 3
assert [column.width for column in columns] == [1, 1, 1]
assert [column.height for column in columns] == [10, 10, 10]
assert [column.position_x for column in columns] == [0, 1, 2]
assert [column.position_y for column in columns] == [0, 0, 0]
@assert_no_logs
def test_columns_padding():
page, = render_pages('''
<style>
@font-face { src: url(weasyprint.otf); font-family: weasyprint }
div { columns: 4; column-gap: 0; padding: 1px }
body { margin: 0; font-family: weasyprint; line-height: 1px }
@page { margin: 0; size: 6px 50px; font-size: 1px }
</style>
<div>a b c</div>
''')
html, = page.children
body, = html.children
div, = body.children
assert div.width == 4
assert div.height == 1
assert div.padding_width() == 6
assert div.padding_height() == 3
columns = div.children
assert len(columns) == 3
assert [column.width for column in columns] == [1, 1, 1]
assert [column.height for column in columns] == [1, 1, 1]
assert [column.position_x for column in columns] == [1, 2, 3]
assert [column.position_y for column in columns] == [1, 1, 1]
@assert_no_logs
def test_columns_relative():
page, = render_pages('''
<style>
@font-face { src: url(weasyprint.otf); font-family: weasyprint }
article { position: absolute; top: 3px }
div { columns: 4; column-gap: 0; position: relative;
top: 1px; left: 2px }
body { margin: 0; font-family: weasyprint; line-height: 1px }
@page { margin: 0; size: 4px 50px; font-size: 1px }
</style>
<div>a b c d<article>e</article></div>
''')
html, = page.children
body, = html.children
div, = body.children
assert div.width == 4
columns = div.children
assert [column.width for column in columns] == [1, 1, 1, 1]
assert [column.position_x for column in columns] == [2, 3, 4, 5]
assert [column.position_y for column in columns] == [1, 1, 1, 1]
column4 = columns[-1]
column_line, = column4.children
_, absolute_article = column_line.children
absolute_line, = absolute_article.children
span, = absolute_line.children
assert span.position_x == 5 # Default position of the 4th column
assert span.position_y == 4 # div's 1px + span's 3px
@assert_no_logs
def test_columns_regression_1():
# Regression test #1 for https://github.com/Kozea/WeasyPrint/issues/659
page1, page2, page3 = render_pages('''
<style>
@page {margin: 0; width: 100px; height: 100px}
body {margin: 0; font-size: 1px}
</style>
<div style="height:95px">A</div>
<div style="column-count:2">
<div style="height:20px">B1</div>
<div style="height:20px">B2</div>
<div style="height:20px">B3</div>
</div>
<div style="height:95px">C</div>
''')
html, = page1.children
body, = html.children
div, = body.children
assert div.position_y == 0
assert div.children[0].children[0].text == 'A'
html, = page2.children
body, = html.children
div, = body.children
assert div.position_y == 0
column1, column2 = div.children
assert column1.position_y == column2.position_y == 0
div1, div2 = column1.children
div3, = column2.children
assert div1.position_y == div3.position_y == 0
assert div2.position_y == 20
assert div1.children[0].children[0].text == 'B1'
assert div2.children[0].children[0].text == 'B2'
assert div3.children[0].children[0].text == 'B3'
html, = page3.children
body, = html.children
div, = body.children
assert div.position_y == 0
assert div.children[0].children[0].text == 'C'
@assert_no_logs
def test_columns_regression_2():
# Regression test #2 for https://github.com/Kozea/WeasyPrint/issues/659
page1, page2 = render_pages('''
<style>
@page {margin: 0; width: 100px; height: 100px}
body {margin: 0; font-size: 1px}
</style>
<div style="column-count:2">
<div style="height:20px">B1</div>
<div style="height:60px">B2</div>
<div style="height:60px">B3</div>
<div style="height:60px">B4</div>
</div>
''')
html, = page1.children
body, = html.children
div, = body.children
assert div.position_y == 0
column1, column2 = div.children
assert column1.position_y == column2.position_y == 0
div1, div2 = column1.children
div3, = column2.children
assert div1.position_y == div3.position_y == 0
assert div2.position_y == 20
assert div1.children[0].children[0].text == 'B1'
assert div2.children[0].children[0].text == 'B2'
assert div3.children[0].children[0].text == 'B3'
html, = page2.children
body, = html.children
div, = body.children
assert div.position_y == 0
column1, = div.children
assert column1.position_y == 0
div1, = column1.children
assert div1.position_y == div3.position_y == 0
assert div1.children[0].children[0].text == 'B4'
@assert_no_logs
def test_columns_regression_3():
# Regression test #3 for https://github.com/Kozea/WeasyPrint/issues/659
page, = render_pages('''
<style>
@page {margin: 0; width: 100px; height: 100px}
body {margin: 0; font-size: 10px}
</style>
<div style="column-count:2">
<div style="height:20px; margin:5px">B1</div>
<div style="height:60px">B2</div>
<div style="height:60px">B3</div>
</div>
''')
html, = page.children
body, = html.children
div, = body.children
assert div.position_y == 0
column1, column2 = div.children
assert column1.position_y == column2.position_y == 0
div1, div2 = column1.children
div3, = column2.children
assert div1.position_y == div3.position_y == 0
assert div2.position_y == 30
assert div.height == 5 + 20 + 5 + 60
assert div1.children[0].children[0].text == 'B1'
assert div2.children[0].children[0].text == 'B2'
assert div3.children[0].children[0].text == 'B3'
@assert_no_logs
def test_columns_regression_4():
# Regression test for https://github.com/Kozea/WeasyPrint/issues/897
page, = render_pages('''
<div style="position:absolute">
<div style="column-count:2">
<div>a</div>
</div>
</div>
''')
html, = page.children
body, = html.children
div, = body.children
assert div.position_y == 0
column1, = div.children
assert column1.position_y == 0
div1, = column1.children
assert div1.position_y == 0
@assert_no_logs
def test_columns_regression_5():
# Regression test for https://github.com/Kozea/WeasyPrint/issues/1191
render_pages('''
<style>
@page {width: 100px; height: 100px}
</style>
<div style="height: 1px"></div>
<div style="columns: 2">
<div style="break-after: avoid">
<div style="height: 50px"></div>
</div>
<div style="break-after: avoid">
<div style="height: 50px"></div>
<p>a</p>
</div>
</div>
<div style="height: 50px"></div>
''')