X Tutup
# encoding: utf-8 """ Test suite for the docx.oxml.text module. """ from __future__ import ( absolute_import, division, print_function, unicode_literals ) import pytest from docx.exceptions import InvalidSpanError from docx.oxml import parse_xml from docx.oxml.table import CT_Row, CT_Tc from ..unitutil.cxml import element, xml from ..unitutil.file import snippet_seq from ..unitutil.mock import call, instance_mock, method_mock, property_mock class DescribeCT_Row(object): def it_can_add_a_trPr(self, add_trPr_fixture): tr, expected_xml = add_trPr_fixture tr._add_trPr() assert tr.xml == expected_xml def it_raises_on_tc_at_grid_col(self, tc_raise_fixture): tr, idx = tc_raise_fixture with pytest.raises(ValueError): tr.tc_at_grid_col(idx) # fixtures ------------------------------------------------------- @pytest.fixture(params=[ ('w:tr', 'w:tr/w:trPr'), ('w:tr/w:tblPrEx', 'w:tr/(w:tblPrEx,w:trPr)'), ('w:tr/w:tc', 'w:tr/(w:trPr,w:tc)'), ('w:tr/(w:sdt,w:del,w:tc)', 'w:tr/(w:trPr,w:sdt,w:del,w:tc)'), ]) def add_trPr_fixture(self, request): tr_cxml, expected_cxml = request.param tr = element(tr_cxml) expected_xml = xml(expected_cxml) return tr, expected_xml @pytest.fixture(params=[(0, 0, 3), (1, 0, 1)]) def tc_raise_fixture(self, request): snippet_idx, row_idx, col_idx = request.param tbl = parse_xml(snippet_seq('tbl-cells')[snippet_idx]) tr = tbl.tr_lst[row_idx] return tr, col_idx class DescribeCT_Tc(object): def it_can_merge_to_another_tc(self, merge_fixture): tc, other_tc, top_tr_, top_tc_, left, height, width = merge_fixture merged_tc = tc.merge(other_tc) tc._span_dimensions.assert_called_once_with(other_tc) top_tr_.tc_at_grid_col.assert_called_once_with(left) top_tc_._grow_to.assert_called_once_with(width, height) assert merged_tc is top_tc_ def it_knows_its_extents_to_help(self, extents_fixture): tc, attr_name, expected_value = extents_fixture extent = getattr(tc, attr_name) assert extent == expected_value def it_calculates_the_dimensions_of_a_span_to_help(self, span_fixture): tc, other_tc, expected_dimensions = span_fixture dimensions = tc._span_dimensions(other_tc) assert dimensions == expected_dimensions def it_raises_on_invalid_span(self, span_raise_fixture): tc, other_tc = span_raise_fixture with pytest.raises(InvalidSpanError): tc._span_dimensions(other_tc) def it_can_grow_itself_to_help_merge(self, grow_to_fixture): tc, width, height, top_tc, expected_calls = grow_to_fixture tc._grow_to(width, height, top_tc) assert tc._span_to_width.call_args_list == expected_calls def it_can_extend_its_horz_span_to_help_merge(self, span_width_fixture): tc, grid_width, top_tc, vMerge, expected_calls = span_width_fixture tc._span_to_width(grid_width, top_tc, vMerge) tc._move_content_to.assert_called_once_with(top_tc) assert tc._swallow_next_tc.call_args_list == expected_calls assert tc.vMerge == vMerge def it_can_swallow_the_next_tc_help_merge(self, swallow_fixture): tc, grid_width, top_tc, tr, expected_xml = swallow_fixture tc._swallow_next_tc(grid_width, top_tc) assert tr.xml == expected_xml def it_adds_cell_widths_on_swallow(self, add_width_fixture): tc, grid_width, top_tc, tr, expected_xml = add_width_fixture tc._swallow_next_tc(grid_width, top_tc) assert tr.xml == expected_xml def it_raises_on_invalid_swallow(self, swallow_raise_fixture): tc, grid_width, top_tc, tr = swallow_raise_fixture with pytest.raises(InvalidSpanError): tc._swallow_next_tc(grid_width, top_tc) def it_can_move_its_content_to_help_merge(self, move_fixture): tc, tc_2, expected_tc_xml, expected_tc_2_xml = move_fixture tc._move_content_to(tc_2) assert tc.xml == expected_tc_xml assert tc_2.xml == expected_tc_2_xml def it_raises_on_tr_above(self, tr_above_raise_fixture): tc = tr_above_raise_fixture with pytest.raises(ValueError): tc._tr_above # fixtures ------------------------------------------------------- @pytest.fixture(params=[ # both cells have a width ('w:tr/(w:tc/(w:tcPr/w:tcW{w:w=1440,w:type=dxa},w:p),' 'w:tc/(w:tcPr/w:tcW{w:w=1440,w:type=dxa},w:p))', 0, 2, 'w:tr/(w:tc/(w:tcPr/(w:tcW{w:w=2880,w:type=dxa},' 'w:gridSpan{w:val=2}),w:p))'), # neither have a width ('w:tr/(w:tc/w:p,w:tc/w:p)', 0, 2, 'w:tr/(w:tc/(w:tcPr/w:gridSpan{w:val=2},w:p))'), # only second one has a width ('w:tr/(w:tc/w:p,' 'w:tc/(w:tcPr/w:tcW{w:w=1440,w:type=dxa},w:p))', 0, 2, 'w:tr/(w:tc/(w:tcPr/w:gridSpan{w:val=2},w:p))'), # only first one has a width ('w:tr/(w:tc/(w:tcPr/w:tcW{w:w=1440,w:type=dxa},w:p),' 'w:tc/w:p)', 0, 2, 'w:tr/(w:tc/(w:tcPr/(w:tcW{w:w=1440,w:type=dxa},' 'w:gridSpan{w:val=2}),w:p))'), ]) def add_width_fixture(self, request): tr_cxml, tc_idx, grid_width, expected_tr_cxml = request.param tr = element(tr_cxml) tc = top_tc = tr[tc_idx] expected_tr_xml = xml(expected_tr_cxml) return tc, grid_width, top_tc, tr, expected_tr_xml @pytest.fixture(params=[ (0, 0, 0, 'top', 0), (2, 0, 1, 'top', 0), (2, 1, 1, 'top', 0), (4, 2, 1, 'top', 1), (0, 0, 0, 'left', 0), (1, 0, 1, 'left', 2), (3, 1, 0, 'left', 0), (3, 1, 1, 'left', 2), (0, 0, 0, 'bottom', 1), (1, 0, 0, 'bottom', 1), (2, 0, 1, 'bottom', 2), (4, 1, 1, 'bottom', 3), (0, 0, 0, 'right', 1), (1, 0, 0, 'right', 2), (0, 0, 0, 'right', 1), (4, 2, 1, 'right', 3), ]) def extents_fixture(self, request): snippet_idx, row, col, attr_name, expected_value = request.param tbl = self._snippet_tbl(snippet_idx) tc = tbl.tr_lst[row].tc_lst[col] return tc, attr_name, expected_value @pytest.fixture(params=[ (0, 0, 0, 2, 1), (0, 0, 1, 1, 2), (0, 1, 1, 2, 2), (1, 0, 0, 2, 2), (2, 0, 0, 2, 2), (2, 1, 2, 1, 2), ]) def grow_to_fixture(self, request, _span_to_width_): snippet_idx, row, col, width, height = request.param tbl = self._snippet_tbl(snippet_idx) tc = tbl.tr_lst[row].tc_lst[col] start = 0 if height == 1 else 1 end = start + height expected_calls = [ call(width, tc, None), call(width, tc, 'restart'), call(width, tc, 'continue'), call(width, tc, 'continue'), ][start:end] return tc, width, height, None, expected_calls @pytest.fixture def merge_fixture( self, tr_, _span_dimensions_, _tbl_, _grow_to_, top_tc_): tc, other_tc = element('w:tc'), element('w:tc') top, left, height, width = 0, 1, 2, 3 _span_dimensions_.return_value = top, left, height, width _tbl_.return_value.tr_lst = [tr_] tr_.tc_at_grid_col.return_value = top_tc_ return tc, other_tc, tr_, top_tc_, left, height, width @pytest.fixture(params=[ ('w:tc/w:p', 'w:tc/w:p', 'w:tc/w:p', 'w:tc/w:p'), ('w:tc/w:p', 'w:tc/w:p/w:r', 'w:tc/w:p', 'w:tc/w:p/w:r'), ('w:tc/w:p/w:r', 'w:tc/w:p', 'w:tc/w:p', 'w:tc/w:p/w:r'), ('w:tc/(w:p/w:r,w:sdt)', 'w:tc/w:p', 'w:tc/w:p', 'w:tc/(w:p/w:r,w:sdt)'), ('w:tc/(w:p/w:r,w:sdt)', 'w:tc/(w:tbl,w:p)', 'w:tc/w:p', 'w:tc/(w:tbl,w:p/w:r,w:sdt)'), ]) def move_fixture(self, request): tc_cxml, tc_2_cxml, expected_tc_cxml, expected_tc_2_cxml = ( request.param ) tc, tc_2 = element(tc_cxml), element(tc_2_cxml) expected_tc_xml = xml(expected_tc_cxml) expected_tc_2_xml = xml(expected_tc_2_cxml) return tc, tc_2, expected_tc_xml, expected_tc_2_xml @pytest.fixture(params=[ (0, 0, 0, 0, 1, (0, 0, 1, 2)), (0, 0, 1, 2, 1, (0, 1, 3, 1)), (0, 2, 2, 1, 1, (1, 1, 2, 2)), (0, 1, 2, 1, 0, (1, 0, 1, 3)), (1, 0, 0, 1, 1, (0, 0, 2, 2)), (1, 0, 1, 0, 0, (0, 0, 1, 3)), (2, 0, 1, 2, 1, (0, 1, 3, 1)), (2, 0, 1, 1, 0, (0, 0, 2, 2)), (2, 1, 2, 0, 1, (0, 1, 2, 2)), (4, 0, 1, 0, 0, (0, 0, 1, 3)), ]) def span_fixture(self, request): snippet_idx, row, col, row_2, col_2, expected_value = request.param tbl = self._snippet_tbl(snippet_idx) tc = tbl.tr_lst[row].tc_lst[col] tc_2 = tbl.tr_lst[row_2].tc_lst[col_2] return tc, tc_2, expected_value @pytest.fixture(params=[ (1, 0, 0, 1, 0), # inverted-L horz (1, 1, 0, 0, 0), # same in opposite order (2, 0, 2, 0, 1), # inverted-L vert (5, 0, 1, 1, 0), # tee-shape horz bar (5, 1, 0, 2, 1), # same, opposite side (6, 1, 0, 0, 1), # tee-shape vert bar (6, 0, 1, 1, 2), # same, opposite side ]) def span_raise_fixture(self, request): snippet_idx, row, col, row_2, col_2 = request.param tbl = self._snippet_tbl(snippet_idx) tc = tbl.tr_lst[row].tc_lst[col] tc_2 = tbl.tr_lst[row_2].tc_lst[col_2] return tc, tc_2 @pytest.fixture def span_width_fixture( self, top_tc_, grid_span_, _move_content_to_, _swallow_next_tc_): tc = element('w:tc') grid_span_.side_effect = [1, 3, 4] grid_width, vMerge = 4, 'continue' expected_calls = [ call(grid_width, top_tc_), call(grid_width, top_tc_) ] return tc, grid_width, top_tc_, vMerge, expected_calls @pytest.fixture(params=[ ('w:tr/(w:tc/w:p,w:tc/w:p)', 0, 2, 'w:tr/(w:tc/(w:tcPr/w:gridSpan{w:val=2},w:p))'), ('w:tr/(w:tc/w:p,w:tc/w:p,w:tc/w:p)', 1, 2, 'w:tr/(w:tc/w:p,w:tc/(w:tcPr/w:gridSpan{w:val=2},w:p))'), ('w:tr/(w:tc/w:p/w:r/w:t"a",w:tc/w:p/w:r/w:t"b")', 0, 2, 'w:tr/(w:tc/(w:tcPr/w:gridSpan{w:val=2},w:p/w:r/w:t"a",' 'w:p/w:r/w:t"b"))'), ('w:tr/(w:tc/(w:tcPr/w:gridSpan{w:val=2},w:p),w:tc/w:p)', 0, 3, 'w:tr/(w:tc/(w:tcPr/w:gridSpan{w:val=3},w:p))'), ('w:tr/(w:tc/w:p,w:tc/(w:tcPr/w:gridSpan{w:val=2},w:p))', 0, 3, 'w:tr/(w:tc/(w:tcPr/w:gridSpan{w:val=3},w:p))'), ]) def swallow_fixture(self, request): tr_cxml, tc_idx, grid_width, expected_tr_cxml = request.param tr = element(tr_cxml) tc = top_tc = tr[tc_idx] expected_tr_xml = xml(expected_tr_cxml) return tc, grid_width, top_tc, tr, expected_tr_xml @pytest.fixture(params=[ ('w:tr/w:tc/w:p', 0, 2), ('w:tr/(w:tc/w:p,w:tc/(w:tcPr/w:gridSpan{w:val=2},w:p))', 0, 2), ]) def swallow_raise_fixture(self, request): tr_cxml, tc_idx, grid_width = request.param tr = element(tr_cxml) tc = top_tc = tr[tc_idx] return tc, grid_width, top_tc, tr @pytest.fixture(params=[(0, 0, 0), (4, 0, 0)]) def tr_above_raise_fixture(self, request): snippet_idx, row_idx, col_idx = request.param tbl = parse_xml(snippet_seq('tbl-cells')[snippet_idx]) tc = tbl.tr_lst[row_idx].tc_lst[col_idx] return tc # fixture components --------------------------------------------- @pytest.fixture def grid_span_(self, request): return property_mock(request, CT_Tc, 'grid_span') @pytest.fixture def _grow_to_(self, request): return method_mock(request, CT_Tc, '_grow_to') @pytest.fixture def _move_content_to_(self, request): return method_mock(request, CT_Tc, '_move_content_to') @pytest.fixture def _span_dimensions_(self, request): return method_mock(request, CT_Tc, '_span_dimensions') @pytest.fixture def _span_to_width_(self, request): return method_mock(request, CT_Tc, '_span_to_width') def _snippet_tbl(self, idx): """ Return a element for snippet at *idx* in 'tbl-cells' snippet file. """ return parse_xml(snippet_seq('tbl-cells')[idx]) @pytest.fixture def _swallow_next_tc_(self, request): return method_mock(request, CT_Tc, '_swallow_next_tc') @pytest.fixture def _tbl_(self, request): return property_mock(request, CT_Tc, '_tbl') @pytest.fixture def top_tc_(self, request): return instance_mock(request, CT_Tc) @pytest.fixture def tr_(self, request): return instance_mock(request, CT_Row)
X Tutup