summaryrefslogtreecommitdiff
path: root/tests/docx/numbering_xml_tests.py
blob: 6f1e44759f5f61785fe1f6157ec9d5d2e9704eaf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
from mammoth.docx.xmlparser import element as xml_element
from mammoth.docx.numbering_xml import read_numbering_xml_element
from mammoth.docx.styles_xml import NumberingStyle, Styles
from ..testing import assert_equal


def test_find_level_returns_none_if_num_with_id_cannot_be_found():
    numbering = _read_numbering_xml_element(xml_element("w:numbering"))
    assert_equal(None, numbering.find_level("47", "0"))


_sample_numbering_xml = xml_element("w:numbering", {}, [
    xml_element("w:abstractNum", {"w:abstractNumId": "42"}, [
        xml_element("w:lvl", {"w:ilvl": "0"}, [
            xml_element("w:numFmt", {"w:val": "bullet"})
        ]),
        xml_element("w:lvl", {"w:ilvl": "1"}, [
            xml_element("w:numFmt", {"w:val": "decimal"})
        ])
    ]),
    xml_element("w:num", {"w:numId": "47"}, [
        xml_element("w:abstractNumId", {"w:val": "42"})
    ])
])


def test_level_includes_level_index():
    numbering = _read_numbering_xml_element(_sample_numbering_xml)
    assert_equal("0", numbering.find_level("47", "0").level_index)
    assert_equal("1", numbering.find_level("47", "1").level_index)


def test_list_is_not_ordered_if_formatted_as_bullet():
    numbering = _read_numbering_xml_element(_sample_numbering_xml)
    assert_equal(False, numbering.find_level("47", "0").is_ordered)


def test_list_is_ordered_if_formatted_as_decimal():
    numbering = _read_numbering_xml_element(_sample_numbering_xml)
    assert_equal(True, numbering.find_level("47", "1").is_ordered)


def test_list_is_ordered_if_there_is_no_explicit_format():
    element = xml_element("w:numbering", {}, [
        xml_element("w:abstractNum", {"w:abstractNumId": "42"}, [
            xml_element("w:lvl", {"w:ilvl": "0"}),
        ]),
        xml_element("w:num", {"w:numId": "47"}, [
            xml_element("w:abstractNumId", {"w:val": "42"})
        ])
    ])

    numbering = _read_numbering_xml_element(element)

    assert_equal(True, numbering.find_level("47", "0").is_ordered)


def test_find_level_returns_none_if_level_cannot_be_found():
    numbering = _read_numbering_xml_element(_sample_numbering_xml)
    assert_equal(None, numbering.find_level("47", "2"))


def test_num_referencing_non_existent_abstract_num_is_ignored():
    element = xml_element("w:numbering", {}, [
        xml_element("w:num", {"w:numId": "47"}, [
            xml_element("w:abstractNumId", {"w:val": "42"})
        ])
    ])

    numbering = _read_numbering_xml_element(element)

    assert_equal(None, numbering.find_level("47", "0"))


def test_when_abstract_num_has_num_style_link_then_style_is_used_to_find_num():
    numbering = _read_numbering_xml_element(
        xml_element("w:numbering", {}, [
            xml_element("w:abstractNum", {"w:abstractNumId": "100"}, [
                xml_element("w:lvl", {"w:ilvl": "0"}, [
                    xml_element("w:numFmt", {"w:val": "decimal"}),
                ]),
            ]),
            xml_element("w:abstractNum", {"w:abstractNumId": "101"}, [
                xml_element("w:numStyleLink", {"w:val": "List1"}),
            ]),
            xml_element("w:num", {"w:numId": "200"}, [
                xml_element("w:abstractNumId", {"w:val": "100"}),
            ]),
            xml_element("w:num", {"w:numId": "201"}, [
                xml_element("w:abstractNumId", {"w:val": "101"}),
            ])
        ]),
        styles=Styles.create(numbering_styles={
            "List1": NumberingStyle(style_id="List1", num_id="200"),
        }),
    )
    assert_equal(True, numbering.find_level("201", "0").is_ordered)


# See: 17.9.23 pStyle (Paragraph Style's Associated Numbering Level) in ECMA-376, 4th Edition
def test_numbering_level_can_be_found_by_paragraph_style_id():
    numbering = _read_numbering_xml_element(
        xml_element("w:numbering", {}, [
            xml_element("w:abstractNum", {"w:abstractNumId": "42"}, [
                xml_element("w:lvl", {"w:ilvl": "0"}, [
                    xml_element("w:numFmt", {"w:val": "bullet"}),
                ]),
            ]),
            xml_element("w:abstractNum", {"w:abstractNumId": "43"}, [
                xml_element("w:lvl", {"w:ilvl": "0"}, [
                    xml_element("w:pStyle", {"w:val": "List"}),
                    xml_element("w:numFmt", {"w:val": "decimal"}),
                ]),
            ]),
        ]),
    )

    assert_equal(True, numbering.find_level_by_paragraph_style_id("List").is_ordered)
    assert_equal(None, numbering.find_level_by_paragraph_style_id("Paragraph"))


def _read_numbering_xml_element(element, styles=None):
    if styles is None:
        styles = Styles.EMPTY

    return read_numbering_xml_element(element, styles=styles)