11
11
import pytest
12
12
13
13
from docx .opc .oxml import CT_Relationships
14
+ from docx .opc .package import Part
14
15
from docx .opc .packuri import PackURI
15
16
from docx .opc .rel import _Relationship , Relationships
16
17
17
- from ..unitutil .mock import call , class_mock , Mock , patch , PropertyMock
18
+ from ..unitutil .mock import (
19
+ call , class_mock , instance_mock , Mock , patch , PropertyMock
20
+ )
18
21
19
22
20
23
class Describe_Relationship (object ):
@@ -56,21 +59,6 @@ def it_should_have_relative_ref_for_internal_rel(self):
56
59
57
60
class DescribeRelationships (object ):
58
61
59
- def it_has_a_len (self ):
60
- rels = Relationships (None )
61
- assert len (rels ) == 0
62
-
63
- def it_has_dict_style_lookup_of_rel_by_rId (self ):
64
- rel = Mock (name = 'rel' , rId = 'foobar' )
65
- rels = Relationships (None )
66
- rels ['foobar' ] = rel
67
- assert rels ['foobar' ] == rel
68
-
69
- def it_should_raise_on_failed_lookup_by_rId (self ):
70
- rels = Relationships (None )
71
- with pytest .raises (KeyError ):
72
- rels ['barfoo' ]
73
-
74
62
def it_can_add_a_relationship (self , _Relationship_ ):
75
63
baseURI , rId , reltype , target , external = (
76
64
'baseURI' , 'rId9' , 'reltype' , 'target' , False
@@ -91,13 +79,43 @@ def it_can_add_an_external_relationship(self, add_ext_rel_fixture_):
91
79
assert rel .target_ref == url
92
80
assert rel .reltype == reltype
93
81
94
- def it_should_return_an_existing_one_if_it_matches (
82
+ def it_can_find_a_relationship_by_rId (self ):
83
+ rel = Mock (name = 'rel' , rId = 'foobar' )
84
+ rels = Relationships (None )
85
+ rels ['foobar' ] = rel
86
+ assert rels ['foobar' ] == rel
87
+
88
+ def it_can_find_or_add_a_relationship (
89
+ self , rels_with_matching_rel_ , rels_with_missing_rel_ ):
90
+
91
+ rels , reltype , part , matching_rel = rels_with_matching_rel_
92
+ assert rels .get_or_add (reltype , part ) == matching_rel
93
+
94
+ rels , reltype , part , new_rel = rels_with_missing_rel_
95
+ assert rels .get_or_add (reltype , part ) == new_rel
96
+
97
+ def it_can_find_or_add_an_external_relationship (
95
98
self , add_matching_ext_rel_fixture_ ):
96
99
rels , reltype , url , rId = add_matching_ext_rel_fixture_
97
100
_rId = rels .get_or_add_ext_rel (reltype , url )
98
101
assert _rId == rId
99
102
assert len (rels ) == 1
100
103
104
+ def it_can_find_a_related_part_by_rId (self , rels_with_known_target_part ):
105
+ rels , rId , known_target_part = rels_with_known_target_part
106
+ part = rels .related_parts [rId ]
107
+ assert part is known_target_part
108
+
109
+ def it_raises_on_related_part_not_found (self , rels ):
110
+ with pytest .raises (KeyError ):
111
+ rels .related_parts ['rId666' ]
112
+
113
+ def it_can_find_a_related_part_by_reltype (
114
+ self , rels_with_target_known_by_reltype ):
115
+ rels , reltype , known_target_part = rels_with_target_known_by_reltype
116
+ part = rels .part_with_reltype (reltype )
117
+ assert part is known_target_part
118
+
101
119
def it_can_compose_rels_xml (self , rels , rels_elm ):
102
120
# exercise ---------------------
103
121
rels .xml
@@ -115,6 +133,11 @@ def it_can_compose_rels_xml(self, rels, rels_elm):
115
133
any_order = True
116
134
)
117
135
136
+ def it_knows_the_next_available_rId_to_help (self , rels_with_rId_gap ):
137
+ rels , expected_next_rId = rels_with_rId_gap
138
+ next_rId = rels ._next_rId
139
+ assert next_rId == expected_next_rId
140
+
118
141
# fixtures ---------------------------------------------
119
142
120
143
@pytest .fixture
@@ -129,10 +152,22 @@ def add_matching_ext_rel_fixture_(self, request, reltype, url):
129
152
rels .add_relationship (reltype , url , rId , is_external = True )
130
153
return rels , reltype , url , rId
131
154
155
+ # fixture components -----------------------------------
156
+
157
+ @pytest .fixture
158
+ def _baseURI (self ):
159
+ return '/baseURI'
160
+
132
161
@pytest .fixture
133
162
def _Relationship_ (self , request ):
134
163
return class_mock (request , 'docx.opc.rel._Relationship' )
135
164
165
+ @pytest .fixture
166
+ def _rel_with_target_known_by_reltype (
167
+ self , _rId , reltype , _target_part , _baseURI ):
168
+ rel = _Relationship (_rId , reltype , _target_part , _baseURI )
169
+ return rel , reltype , _target_part
170
+
136
171
@pytest .fixture
137
172
def rels (self ):
138
173
"""
@@ -168,10 +203,82 @@ def rels_elm(self, request):
168
203
request .addfinalizer (patch_ .stop )
169
204
return rels_elm
170
205
206
+ @pytest .fixture
207
+ def _rel_with_known_target_part (
208
+ self , _rId , reltype , _target_part , _baseURI ):
209
+ rel = _Relationship (_rId , reltype , _target_part , _baseURI )
210
+ return rel , _rId , _target_part
211
+
212
+ @pytest .fixture
213
+ def rels_with_known_target_part (self , rels , _rel_with_known_target_part ):
214
+ rel , rId , target_part = _rel_with_known_target_part
215
+ rels .add_relationship (None , target_part , rId )
216
+ return rels , rId , target_part
217
+
218
+ @pytest .fixture
219
+ def rels_with_matching_rel_ (self , request , rels ):
220
+ matching_reltype_ = instance_mock (
221
+ request , str , name = 'matching_reltype_'
222
+ )
223
+ matching_part_ = instance_mock (
224
+ request , Part , name = 'matching_part_'
225
+ )
226
+ matching_rel_ = instance_mock (
227
+ request , _Relationship , name = 'matching_rel_' ,
228
+ reltype = matching_reltype_ , target_part = matching_part_ ,
229
+ is_external = False
230
+ )
231
+ rels [1 ] = matching_rel_
232
+ return rels , matching_reltype_ , matching_part_ , matching_rel_
233
+
234
+ @pytest .fixture
235
+ def rels_with_missing_rel_ (self , request , rels , _Relationship_ ):
236
+ missing_reltype_ = instance_mock (
237
+ request , str , name = 'missing_reltype_'
238
+ )
239
+ missing_part_ = instance_mock (
240
+ request , Part , name = 'missing_part_'
241
+ )
242
+ new_rel_ = instance_mock (
243
+ request , _Relationship , name = 'new_rel_' ,
244
+ reltype = missing_reltype_ , target_part = missing_part_ ,
245
+ is_external = False
246
+ )
247
+ _Relationship_ .return_value = new_rel_
248
+ return rels , missing_reltype_ , missing_part_ , new_rel_
249
+
250
+ @pytest .fixture
251
+ def rels_with_rId_gap (self , request ):
252
+ rels = Relationships (None )
253
+ rel_with_rId1 = instance_mock (
254
+ request , _Relationship , name = 'rel_with_rId1' , rId = 'rId1'
255
+ )
256
+ rel_with_rId3 = instance_mock (
257
+ request , _Relationship , name = 'rel_with_rId3' , rId = 'rId3'
258
+ )
259
+ rels ['rId1' ] = rel_with_rId1
260
+ rels ['rId3' ] = rel_with_rId3
261
+ return rels , 'rId2'
262
+
263
+ @pytest .fixture
264
+ def rels_with_target_known_by_reltype (
265
+ self , rels , _rel_with_target_known_by_reltype ):
266
+ rel , reltype , target_part = _rel_with_target_known_by_reltype
267
+ rels [1 ] = rel
268
+ return rels , reltype , target_part
269
+
171
270
@pytest .fixture
172
271
def reltype (self ):
173
272
return 'http://rel/type'
174
273
274
+ @pytest .fixture
275
+ def _rId (self ):
276
+ return 'rId6'
277
+
278
+ @pytest .fixture
279
+ def _target_part (self , request ):
280
+ return instance_mock (request , Part )
281
+
175
282
@pytest .fixture
176
283
def url (self ):
177
284
return 'https://github.com/scanny/python-docx'
0 commit comments