ixbrl-viewer 1.4.68__py3-none-any.whl → 1.4.70__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of ixbrl-viewer might be problematic. Click here for more details.
- iXBRLViewerPlugin/_version.py +2 -2
- iXBRLViewerPlugin/viewer/dist/ixbrlviewer.js +1 -1
- {ixbrl_viewer-1.4.68.dist-info → ixbrl_viewer-1.4.70.dist-info}/METADATA +3 -4
- {ixbrl_viewer-1.4.68.dist-info → ixbrl_viewer-1.4.70.dist-info}/RECORD +9 -29
- {ixbrl_viewer-1.4.68.dist-info → ixbrl_viewer-1.4.70.dist-info}/top_level.txt +0 -1
- tests/__init__.py +0 -0
- tests/puppeteer/framework/core_elements.js +0 -117
- tests/puppeteer/framework/page_objects/doc_frame.js +0 -105
- tests/puppeteer/framework/page_objects/fact_details_panel.js +0 -112
- tests/puppeteer/framework/page_objects/search_panel.js +0 -73
- tests/puppeteer/framework/page_objects/toolbar.js +0 -18
- tests/puppeteer/framework/utils.js +0 -3
- tests/puppeteer/framework/viewer_page.js +0 -103
- tests/puppeteer/puppeteer_test_run_via_intellij.jpg +0 -0
- tests/puppeteer/test_filings/filing_documents_smoke_test.zip +0 -0
- tests/puppeteer/test_filings/highlights.zip +0 -0
- tests/puppeteer/tests/fact_properties.test.js +0 -84
- tests/puppeteer/tests/highlight.test.js +0 -186
- tests/puppeteer/tests/search.test.js +0 -86
- tests/puppeteer/tools/generate.sh +0 -15
- tests/unit_tests/__init__.py +0 -0
- tests/unit_tests/iXBRLViewerPlugin/__init__.py +0 -0
- tests/unit_tests/iXBRLViewerPlugin/mock_arelle.py +0 -41
- tests/unit_tests/iXBRLViewerPlugin/test_iXBRLViewer.py +0 -801
- tests/unit_tests/iXBRLViewerPlugin/test_xhtmlserialize.py +0 -310
- {ixbrl_viewer-1.4.68.dist-info → ixbrl_viewer-1.4.70.dist-info}/WHEEL +0 -0
- {ixbrl_viewer-1.4.68.dist-info → ixbrl_viewer-1.4.70.dist-info}/entry_points.txt +0 -0
- {ixbrl_viewer-1.4.68.dist-info → ixbrl_viewer-1.4.70.dist-info}/licenses/LICENSE.md +0 -0
- {ixbrl_viewer-1.4.68.dist-info → ixbrl_viewer-1.4.70.dist-info}/licenses/NOTICE +0 -0
|
@@ -1,801 +0,0 @@
|
|
|
1
|
-
import io
|
|
2
|
-
import json
|
|
3
|
-
import logging
|
|
4
|
-
import os
|
|
5
|
-
from collections import defaultdict
|
|
6
|
-
from unittest.mock import Mock, patch
|
|
7
|
-
|
|
8
|
-
import pytest
|
|
9
|
-
from arelle import XbrlConst
|
|
10
|
-
from arelle.ModelDocument import Type
|
|
11
|
-
from arelle.ModelValue import qname
|
|
12
|
-
from lxml import etree
|
|
13
|
-
|
|
14
|
-
from .mock_arelle import mock_arelle
|
|
15
|
-
|
|
16
|
-
mock_arelle()
|
|
17
|
-
|
|
18
|
-
from iXBRLViewerPlugin.iXBRLViewer import NamespaceMap, IXBRLViewerBuilder, iXBRLViewerFile
|
|
19
|
-
|
|
20
|
-
class TestNamespaceMap:
|
|
21
|
-
|
|
22
|
-
def test_getPrefix_with_none(self):
|
|
23
|
-
"""
|
|
24
|
-
Tests NamespaceMap.getPrefix with None. Should return generated prefix.
|
|
25
|
-
"""
|
|
26
|
-
ns_map = NamespaceMap()
|
|
27
|
-
result = ns_map.getPrefix(None)
|
|
28
|
-
assert result == 'ns0'
|
|
29
|
-
|
|
30
|
-
def test_getPrefix_with_none_with_prefix(self):
|
|
31
|
-
"""
|
|
32
|
-
Tests NamespaceMap.getPrefix with None. Should return specified prefix.
|
|
33
|
-
"""
|
|
34
|
-
ns_map = NamespaceMap()
|
|
35
|
-
prefix = 'prefix'
|
|
36
|
-
result = ns_map.getPrefix(None, prefix)
|
|
37
|
-
assert result == prefix
|
|
38
|
-
|
|
39
|
-
def test_getPrefix_with_namespace(self):
|
|
40
|
-
"""
|
|
41
|
-
Tests NamespaceMap.getPrefix for 'namespace'. Should return generated
|
|
42
|
-
prefix.
|
|
43
|
-
"""
|
|
44
|
-
ns_map = NamespaceMap()
|
|
45
|
-
namespace = 'namespace'
|
|
46
|
-
result = ns_map.getPrefix(namespace)
|
|
47
|
-
assert result == 'ns0'
|
|
48
|
-
|
|
49
|
-
def test_getPrefix_with_namespace_with_prefix(self):
|
|
50
|
-
"""
|
|
51
|
-
Tests NamespaceMap.getPrefix with 'namespace' with preferred prefix.
|
|
52
|
-
Should return specified prefix.
|
|
53
|
-
"""
|
|
54
|
-
ns_map = NamespaceMap()
|
|
55
|
-
namespace = 'namespace'
|
|
56
|
-
prefix = 'prefix'
|
|
57
|
-
result = ns_map.getPrefix(namespace, prefix)
|
|
58
|
-
assert result == prefix
|
|
59
|
-
|
|
60
|
-
def test_getPrefix_subsequent_call_with_namespace(self):
|
|
61
|
-
"""
|
|
62
|
-
Tests NamespaceMap.getPrefix twice with 'namespace'. Should return same
|
|
63
|
-
generated prefix.
|
|
64
|
-
"""
|
|
65
|
-
ns_map = NamespaceMap()
|
|
66
|
-
namespace = 'namespace'
|
|
67
|
-
result = ns_map.getPrefix(namespace)
|
|
68
|
-
assert result == 'ns0'
|
|
69
|
-
result_2 = ns_map.getPrefix(namespace)
|
|
70
|
-
assert result_2 == 'ns0'
|
|
71
|
-
|
|
72
|
-
def test_getPrefix_subsequent_call_with_namespace_and_prefix(self):
|
|
73
|
-
"""
|
|
74
|
-
Tests NamespaceMap.getPrefix twice with 'namespace' and specified
|
|
75
|
-
prefix. Should return same specified prefix.
|
|
76
|
-
"""
|
|
77
|
-
ns_map = NamespaceMap()
|
|
78
|
-
namespace = 'namespace'
|
|
79
|
-
prefix = 'prefix'
|
|
80
|
-
result = ns_map.getPrefix(namespace, prefix)
|
|
81
|
-
assert result == prefix
|
|
82
|
-
result_2 = ns_map.getPrefix(namespace, prefix)
|
|
83
|
-
assert result_2 == prefix
|
|
84
|
-
|
|
85
|
-
def test_getPrefix_subsequent_call_with_two_namespaces_and_prefix(self):
|
|
86
|
-
"""
|
|
87
|
-
Tests NamespaceMap.getPrefix with two namespaces. Should return
|
|
88
|
-
sequential generated prefixes.
|
|
89
|
-
"""
|
|
90
|
-
ns_map = NamespaceMap()
|
|
91
|
-
namespace_1 = 'namespace_1'
|
|
92
|
-
namespace_2 = 'namespace_2'
|
|
93
|
-
result = ns_map.getPrefix(namespace_1)
|
|
94
|
-
assert result == 'ns0'
|
|
95
|
-
result_2 = ns_map.getPrefix(namespace_2)
|
|
96
|
-
assert result_2 == 'ns1'
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
class TestIXBRLViewer:
|
|
100
|
-
|
|
101
|
-
def setup_method(self, method):
|
|
102
|
-
self.usd_qname = Mock(
|
|
103
|
-
localName='USD',
|
|
104
|
-
prefix='iso4217',
|
|
105
|
-
namespaceURI='http://www.xbrl.org/2003/iso4217'
|
|
106
|
-
)
|
|
107
|
-
|
|
108
|
-
self.monetary_type = Mock(
|
|
109
|
-
qname = Mock(
|
|
110
|
-
localName="monetaryItemType",
|
|
111
|
-
prefix="xbrli",
|
|
112
|
-
namespaceURI="http://www.xbrl.org/2003/instance"
|
|
113
|
-
)
|
|
114
|
-
)
|
|
115
|
-
|
|
116
|
-
self.string_type = Mock(
|
|
117
|
-
qname = Mock(
|
|
118
|
-
localName="stringItemType",
|
|
119
|
-
prefix="xbrli",
|
|
120
|
-
namespaceURI="http://www.xbrl.org/2003/instance"
|
|
121
|
-
)
|
|
122
|
-
)
|
|
123
|
-
|
|
124
|
-
self.integer_simple_type = Mock(
|
|
125
|
-
qname = Mock(
|
|
126
|
-
localName="integer",
|
|
127
|
-
prefix="xs",
|
|
128
|
-
namespaceURI="http://www.w3.org/2001/XMLSchema"
|
|
129
|
-
)
|
|
130
|
-
)
|
|
131
|
-
|
|
132
|
-
self.usd_unit = Mock(
|
|
133
|
-
measures = ([self.usd_qname],[])
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
self.null_units = Mock(
|
|
137
|
-
measures = ([],[])
|
|
138
|
-
)
|
|
139
|
-
|
|
140
|
-
self.cash_concept = Mock(
|
|
141
|
-
qname=Mock(
|
|
142
|
-
localName='Cash',
|
|
143
|
-
prefix='us-gaap',
|
|
144
|
-
namespaceURI='http://viewer.com'
|
|
145
|
-
),
|
|
146
|
-
balance="debit",
|
|
147
|
-
isTypedDimension=False,
|
|
148
|
-
type=self.monetary_type,
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
to_concept = Mock(
|
|
152
|
-
qname=Mock(
|
|
153
|
-
localName='to_concept',
|
|
154
|
-
prefix='us-gaap',
|
|
155
|
-
namespaceURI='http://viewer.com'
|
|
156
|
-
),
|
|
157
|
-
balance="credit",
|
|
158
|
-
isTypedDimension=False,
|
|
159
|
-
type=self.monetary_type,
|
|
160
|
-
)
|
|
161
|
-
from_concept = Mock(
|
|
162
|
-
qname=Mock(
|
|
163
|
-
localName='from_concept',
|
|
164
|
-
prefix='us-gaap',
|
|
165
|
-
namespaceURI='http://viewer.com'
|
|
166
|
-
),
|
|
167
|
-
balance=None,
|
|
168
|
-
isTypedDimension=False,
|
|
169
|
-
type=self.monetary_type,
|
|
170
|
-
)
|
|
171
|
-
|
|
172
|
-
dimension_concept = Mock(
|
|
173
|
-
qname=Mock(
|
|
174
|
-
localName='dimension',
|
|
175
|
-
prefix='us-gaap',
|
|
176
|
-
namespaceURI='http://viewer.com'
|
|
177
|
-
),
|
|
178
|
-
balance=None,
|
|
179
|
-
isTypedDimension=False,
|
|
180
|
-
type=self.string_type,
|
|
181
|
-
)
|
|
182
|
-
|
|
183
|
-
typed_dimension_domain_concept = Mock(
|
|
184
|
-
qname=Mock(
|
|
185
|
-
localName='typed_dimension_domain',
|
|
186
|
-
prefix='us-gaap',
|
|
187
|
-
namespaceURI='http://viewer.com'
|
|
188
|
-
),
|
|
189
|
-
balance=None,
|
|
190
|
-
isTypedDimension=False,
|
|
191
|
-
type=self.string_type,
|
|
192
|
-
)
|
|
193
|
-
|
|
194
|
-
typed_dimension_concept = Mock(
|
|
195
|
-
qname=Mock(
|
|
196
|
-
localName='typed_dimension',
|
|
197
|
-
prefix='us-gaap',
|
|
198
|
-
namespaceURI='http://viewer.com'
|
|
199
|
-
),
|
|
200
|
-
balance=None,
|
|
201
|
-
isTypedDimension=True,
|
|
202
|
-
typedDomainElement=typed_dimension_domain_concept,
|
|
203
|
-
type=self.integer_simple_type,
|
|
204
|
-
)
|
|
205
|
-
|
|
206
|
-
member_concept = Mock(
|
|
207
|
-
qname=Mock(
|
|
208
|
-
localName='member',
|
|
209
|
-
prefix='us-gaap',
|
|
210
|
-
namespaceURI='http://viewer.com'
|
|
211
|
-
),
|
|
212
|
-
balance=None,
|
|
213
|
-
isTypedDimension=False,
|
|
214
|
-
type=self.string_type,
|
|
215
|
-
)
|
|
216
|
-
|
|
217
|
-
rel = Mock(
|
|
218
|
-
fromModelObject=from_concept,
|
|
219
|
-
toModelObject=to_concept,
|
|
220
|
-
weight=1
|
|
221
|
-
)
|
|
222
|
-
|
|
223
|
-
dimension = Mock(
|
|
224
|
-
dimensionQname=dimension_concept.qname,
|
|
225
|
-
memberQname=member_concept.qname,
|
|
226
|
-
dimension=dimension_concept,
|
|
227
|
-
member=member_concept
|
|
228
|
-
)
|
|
229
|
-
|
|
230
|
-
typed_dimension = Mock(
|
|
231
|
-
dimensionQname=typed_dimension_concept.qname,
|
|
232
|
-
memberQname=None,
|
|
233
|
-
dimension=typed_dimension_concept,
|
|
234
|
-
typedMember=Mock(text='typedDimension')
|
|
235
|
-
)
|
|
236
|
-
|
|
237
|
-
dimension_missing_member = Mock(
|
|
238
|
-
dimensionQname=dimension_concept.qname,
|
|
239
|
-
memberQname=None,
|
|
240
|
-
dimension=dimension_concept,
|
|
241
|
-
typedMember=None
|
|
242
|
-
)
|
|
243
|
-
|
|
244
|
-
def isoformat_effect():
|
|
245
|
-
return '01-01-19T00:00:00'
|
|
246
|
-
|
|
247
|
-
context_1 = Mock(
|
|
248
|
-
entityIdentifier=('scheme', 'ident'),
|
|
249
|
-
qnameDims={'d': dimension},
|
|
250
|
-
isInstantPeriod=False,
|
|
251
|
-
isStartEndPeriod=True,
|
|
252
|
-
startDatetime=Mock(isoformat=isoformat_effect),
|
|
253
|
-
endDatetime=Mock(isoformat=isoformat_effect)
|
|
254
|
-
)
|
|
255
|
-
|
|
256
|
-
context_2 = Mock(
|
|
257
|
-
entityIdentifier=('scheme', 'ident'),
|
|
258
|
-
qnameDims={},
|
|
259
|
-
isInstantPeriod=None,
|
|
260
|
-
isStartEndPeriod=None
|
|
261
|
-
)
|
|
262
|
-
|
|
263
|
-
context_with_typed_dimension = Mock(
|
|
264
|
-
entityIdentifier=('scheme', 'ident'),
|
|
265
|
-
qnameDims={'d': typed_dimension},
|
|
266
|
-
isInstantPeriod=False,
|
|
267
|
-
isStartEndPeriod=True,
|
|
268
|
-
startDatetime=Mock(isoformat=isoformat_effect),
|
|
269
|
-
endDatetime=Mock(isoformat=isoformat_effect)
|
|
270
|
-
)
|
|
271
|
-
|
|
272
|
-
context_with_missing_member_on_dimension = Mock(
|
|
273
|
-
entityIdentifier=('scheme', 'ident'),
|
|
274
|
-
qnameDims={'d': dimension_missing_member},
|
|
275
|
-
isInstantPeriod=False,
|
|
276
|
-
isStartEndPeriod=True,
|
|
277
|
-
startDatetime=Mock(isoformat=isoformat_effect),
|
|
278
|
-
endDatetime=Mock(isoformat=isoformat_effect)
|
|
279
|
-
)
|
|
280
|
-
|
|
281
|
-
fact_1 = Mock(
|
|
282
|
-
id='fact_id1',
|
|
283
|
-
qname=self.cash_concept.qname,
|
|
284
|
-
value=100,
|
|
285
|
-
isNumeric=False,
|
|
286
|
-
isTuple=False,
|
|
287
|
-
context=context_1,
|
|
288
|
-
concept=self.cash_concept,
|
|
289
|
-
format='format'
|
|
290
|
-
)
|
|
291
|
-
|
|
292
|
-
fact_2 = Mock(
|
|
293
|
-
id='fact_id2',
|
|
294
|
-
qname=self.cash_concept.qname,
|
|
295
|
-
concept=self.cash_concept,
|
|
296
|
-
context=context_2,
|
|
297
|
-
isNumeric=True,
|
|
298
|
-
isTuple=False,
|
|
299
|
-
unit=self.usd_unit,
|
|
300
|
-
value=None,
|
|
301
|
-
decimals=None,
|
|
302
|
-
precision=None,
|
|
303
|
-
format=None
|
|
304
|
-
)
|
|
305
|
-
|
|
306
|
-
fact_3 = Mock(
|
|
307
|
-
id='fact_id3',
|
|
308
|
-
qname=self.cash_concept.qname,
|
|
309
|
-
concept=self.cash_concept,
|
|
310
|
-
context=context_2,
|
|
311
|
-
isNumeric=True,
|
|
312
|
-
isTuple=False,
|
|
313
|
-
unit=self.null_units,
|
|
314
|
-
value=None,
|
|
315
|
-
decimals=None,
|
|
316
|
-
precision=None,
|
|
317
|
-
format=None
|
|
318
|
-
)
|
|
319
|
-
|
|
320
|
-
fact_with_typed_dimension = Mock(
|
|
321
|
-
id='fact_typed_dimension',
|
|
322
|
-
qname=self.cash_concept.qname,
|
|
323
|
-
value=10,
|
|
324
|
-
isNumeric=False,
|
|
325
|
-
isTuple=False,
|
|
326
|
-
context=context_with_typed_dimension,
|
|
327
|
-
concept=self.cash_concept,
|
|
328
|
-
format='format'
|
|
329
|
-
)
|
|
330
|
-
|
|
331
|
-
fact_with_missing_member_on_dimension = Mock(
|
|
332
|
-
id='fact_dimension_missing_member',
|
|
333
|
-
qname=self.cash_concept.qname,
|
|
334
|
-
value=1000,
|
|
335
|
-
isNumeric=False,
|
|
336
|
-
isTuple=False,
|
|
337
|
-
context=context_with_missing_member_on_dimension,
|
|
338
|
-
concept=self.cash_concept,
|
|
339
|
-
format='format'
|
|
340
|
-
)
|
|
341
|
-
|
|
342
|
-
file_1 = Mock(
|
|
343
|
-
filename='something/reports/001.jpg'
|
|
344
|
-
)
|
|
345
|
-
|
|
346
|
-
file_2 = Mock(
|
|
347
|
-
filename='something/reports/002.jpg'
|
|
348
|
-
)
|
|
349
|
-
|
|
350
|
-
fs = Mock(
|
|
351
|
-
filelist = [file_1, file_2]
|
|
352
|
-
)
|
|
353
|
-
|
|
354
|
-
file_source = Mock(
|
|
355
|
-
fs = fs
|
|
356
|
-
)
|
|
357
|
-
|
|
358
|
-
def creationSoftwareMatches_effect(text):
|
|
359
|
-
return ["Example Software Name"]
|
|
360
|
-
|
|
361
|
-
def fromModelObjects_effect(concept):
|
|
362
|
-
return []
|
|
363
|
-
|
|
364
|
-
def relationshipSet_effect(self, *args):
|
|
365
|
-
return Mock(
|
|
366
|
-
fromModelObject=fromModelObjects_effect,
|
|
367
|
-
modelRelationships=[rel]
|
|
368
|
-
)
|
|
369
|
-
|
|
370
|
-
def info_effect(info, msg):
|
|
371
|
-
# This is a no op for logging
|
|
372
|
-
pass
|
|
373
|
-
|
|
374
|
-
baseSets = defaultdict(list)
|
|
375
|
-
baseSets[('http://www.xbrl.org/2003/arcrole/summation-item', 'ELR', 'linkqname', 'arcqname')] = []
|
|
376
|
-
baseSets[("http://xbrl.org/int/dim/arcrole/dimension-default", 'ELR', 'linkqname', 'arcqname')] = []
|
|
377
|
-
baseSets[("http://www.xbrl.org/2003/arcrole/parent-child", 'ELR', 'linkqname', 'arcqname')] = []
|
|
378
|
-
|
|
379
|
-
roleTypes = defaultdict(list)
|
|
380
|
-
roleTypes['ELR'] = [Mock(definition = "ELR Label")]
|
|
381
|
-
|
|
382
|
-
root = etree.Element('root')
|
|
383
|
-
etree.SubElement(root, '{http://www.w3.org/1999/xhtml}body')
|
|
384
|
-
|
|
385
|
-
self.modelDocument = Mock(
|
|
386
|
-
xmlDocument=etree.ElementTree(root),
|
|
387
|
-
filepath='a.html',
|
|
388
|
-
referencesDocument={
|
|
389
|
-
"xmlDocument":etree.ElementTree(root),
|
|
390
|
-
"filepath":'a.html',
|
|
391
|
-
"objectIndex":0,
|
|
392
|
-
"type":Type.INLINEXBRL,
|
|
393
|
-
},
|
|
394
|
-
ixdsTarget=None,
|
|
395
|
-
)
|
|
396
|
-
|
|
397
|
-
self.modelDocumentInlineSet = Mock(
|
|
398
|
-
referencesDocument={
|
|
399
|
-
Mock(
|
|
400
|
-
xmlDocument=etree.ElementTree(root),
|
|
401
|
-
filepath='a.html',
|
|
402
|
-
objectIndex=0,
|
|
403
|
-
type=Type.INLINEXBRL,
|
|
404
|
-
): [],
|
|
405
|
-
Mock(
|
|
406
|
-
xmlDocument=etree.ElementTree(root),
|
|
407
|
-
filepath='b.html',
|
|
408
|
-
objectIndex=1,
|
|
409
|
-
type=Type.INLINEXBRL,
|
|
410
|
-
): [],
|
|
411
|
-
Mock(
|
|
412
|
-
xmlDocument=etree.ElementTree(root),
|
|
413
|
-
filepath='a.xsd',
|
|
414
|
-
objectIndex=2,
|
|
415
|
-
type=Type.SCHEMA,
|
|
416
|
-
): [],
|
|
417
|
-
},
|
|
418
|
-
filepath=self.modelDocument.filepath,
|
|
419
|
-
type=Type.INLINEXBRLDOCUMENTSET,
|
|
420
|
-
ixdsTarget=None,
|
|
421
|
-
)
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
def urlDocEntry(path, docType, linkQName=None):
|
|
425
|
-
return path, Mock(
|
|
426
|
-
creationSoftwareMatches=creationSoftwareMatches_effect,
|
|
427
|
-
type=docType,
|
|
428
|
-
basename=os.path.basename(path),
|
|
429
|
-
xmlRootElement=Mock(
|
|
430
|
-
iterchildren=Mock(
|
|
431
|
-
return_value=[
|
|
432
|
-
Mock(qname=linkQName)] if linkQName else []
|
|
433
|
-
)
|
|
434
|
-
)
|
|
435
|
-
)
|
|
436
|
-
|
|
437
|
-
self.modelXbrl_1 = Mock(
|
|
438
|
-
relationshipSet=relationshipSet_effect,
|
|
439
|
-
relationshipSets={},
|
|
440
|
-
baseSets=baseSets,
|
|
441
|
-
roleTypes=roleTypes,
|
|
442
|
-
facts=[fact_1, fact_with_typed_dimension, fact_with_missing_member_on_dimension],
|
|
443
|
-
fileSource=file_source,
|
|
444
|
-
info=info_effect,
|
|
445
|
-
modelDocument=self.modelDocument,
|
|
446
|
-
ixdsTarget=None,
|
|
447
|
-
urlDocs=dict((
|
|
448
|
-
urlDocEntry('/filesystem/local-inline.htm', Type.INLINEXBRL),
|
|
449
|
-
urlDocEntry('https://example.com/remote-inline.htm', Type.INLINEXBRL),
|
|
450
|
-
urlDocEntry('/filesystem/local-docset/_IXDS', Type.INLINEXBRLDOCUMENTSET),
|
|
451
|
-
urlDocEntry('https://example.com/remote-docset/_IXDS', Type.INLINEXBRLDOCUMENTSET),
|
|
452
|
-
urlDocEntry('/filesystem/local-schema.xsd', Type.SCHEMA),
|
|
453
|
-
urlDocEntry('https://example.com/remote-schema.xsd', Type.SCHEMA),
|
|
454
|
-
urlDocEntry('/filesystem/local-label-linkbase.xml', Type.LINKBASE, XbrlConst.qnLinkLabelLink),
|
|
455
|
-
urlDocEntry('https://example.com/remote-label-linkbase.xml', Type.LINKBASE, XbrlConst.qnLinkLabelLink),
|
|
456
|
-
urlDocEntry('/filesystem/local-pres-linkbase.xml', Type.LINKBASE, XbrlConst.qnLinkPresentationLink),
|
|
457
|
-
urlDocEntry('https://example.com/remote-pres-linkbase.xml', Type.LINKBASE, XbrlConst.qnLinkPresentationLink),
|
|
458
|
-
urlDocEntry('/filesystem/local-calc-linkbase.xml', Type.LINKBASE, XbrlConst.qnLinkCalculationLink),
|
|
459
|
-
urlDocEntry('https://example.com/remote-calc-linkbase.xml', Type.LINKBASE, XbrlConst.qnLinkCalculationLink),
|
|
460
|
-
urlDocEntry('/filesystem/local-def-linkbase.xml', Type.LINKBASE, XbrlConst.qnLinkDefinitionLink),
|
|
461
|
-
urlDocEntry('https://example.com/remote-def-linkbase.xml', Type.LINKBASE, XbrlConst.qnLinkDefinitionLink),
|
|
462
|
-
urlDocEntry('/filesystem/local-ref-linkbase.xml', Type.LINKBASE, XbrlConst.qnLinkReferenceLink),
|
|
463
|
-
urlDocEntry('https://example.com/remote-ref-linkbase.xml', Type.LINKBASE, XbrlConst.qnLinkReferenceLink),
|
|
464
|
-
urlDocEntry('/filesystem/local-unrecognized-linkbase.xml', Type.LINKBASE, qname("{http://www.example.org/linkbase}link:unrecognizedLink")),
|
|
465
|
-
urlDocEntry('https://example.com/remote-unrecognized-linkbase.xml', Type.LINKBASE, qname("{http://www.example.org/linkbase}link:unrecognizedLink")),
|
|
466
|
-
))
|
|
467
|
-
)
|
|
468
|
-
self.modelXbrl_2 = Mock(
|
|
469
|
-
relationshipSet=relationshipSet_effect,
|
|
470
|
-
relationshipSets={},
|
|
471
|
-
baseSets=baseSets,
|
|
472
|
-
roleTypes=roleTypes,
|
|
473
|
-
facts=[fact_2, fact_3],
|
|
474
|
-
fileSource=file_source,
|
|
475
|
-
info=info_effect,
|
|
476
|
-
modelDocument=self.modelDocument,
|
|
477
|
-
ixdsTarget=None,
|
|
478
|
-
urlDocs={}
|
|
479
|
-
)
|
|
480
|
-
self.modelXbrlDocSet = Mock(
|
|
481
|
-
relationshipSet=relationshipSet_effect,
|
|
482
|
-
relationshipSets={},
|
|
483
|
-
baseSets=baseSets,
|
|
484
|
-
roleTypes=roleTypes,
|
|
485
|
-
facts=[fact_1, fact_with_typed_dimension, fact_with_missing_member_on_dimension],
|
|
486
|
-
fileSource=file_source,
|
|
487
|
-
info=info_effect,
|
|
488
|
-
modelDocument=self.modelDocumentInlineSet,
|
|
489
|
-
ixdsTarget=None,
|
|
490
|
-
urlDocs={}
|
|
491
|
-
)
|
|
492
|
-
|
|
493
|
-
self.cash_concept.modelXbrl = self.modelXbrl_1
|
|
494
|
-
to_concept.modelXbrl = self.modelXbrl_1
|
|
495
|
-
from_concept.modelXbrl = self.modelXbrl_1
|
|
496
|
-
dimension_concept.modelXbrl = self.modelXbrl_1
|
|
497
|
-
typed_dimension_concept.modelXbrl = self.modelXbrl_1
|
|
498
|
-
typed_dimension_domain_concept.modelXbrl = self.modelXbrl_1
|
|
499
|
-
member_concept.modelXbrl = self.modelXbrl_1
|
|
500
|
-
|
|
501
|
-
self.logRecordBuffer = []
|
|
502
|
-
self.cntlr_mock = Mock(
|
|
503
|
-
logHandler = Mock(
|
|
504
|
-
logRecordBuffer = self.logRecordBuffer
|
|
505
|
-
)
|
|
506
|
-
)
|
|
507
|
-
self.builder_1 = IXBRLViewerBuilder(self.cntlr_mock)
|
|
508
|
-
self.builder_doc_set = IXBRLViewerBuilder(self.cntlr_mock)
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
@patch('arelle.XbrlConst.conceptLabel', 'http://www.xbrl.org/2003/arcrole/concept-label')
|
|
512
|
-
@patch('arelle.XbrlConst.conceptReference', 'http://www.xbrl.org/2003/arcrole/concept-reference')
|
|
513
|
-
def test_addConcept_simple_case(self):
|
|
514
|
-
builder = IXBRLViewerBuilder(Mock())
|
|
515
|
-
builder.currentTargetReport = builder.newTargetReport(None)
|
|
516
|
-
builder.addSourceReport()["targetReports"].append(builder.currentTargetReport)
|
|
517
|
-
builder.addConcept(self.modelXbrl_1, self.cash_concept)
|
|
518
|
-
assert builder.taxonomyData["sourceReports"][0]["targetReports"][0].get('concepts').get('us-gaap:Cash')
|
|
519
|
-
|
|
520
|
-
@patch('arelle.XbrlConst.parentChild', 'http://www.xbrl.org/2003/arcrole/parent-child')
|
|
521
|
-
@patch('arelle.XbrlConst.summationItem', 'http://www.xbrl.org/2003/arcrole/summation-item')
|
|
522
|
-
def test_getRelationships_simple_case(self):
|
|
523
|
-
modelXbrl = Mock(baseSets=defaultdict(list), relationshipSets={})
|
|
524
|
-
builder = IXBRLViewerBuilder(Mock())
|
|
525
|
-
result = builder.getRelationships(modelXbrl)
|
|
526
|
-
assert result == {}
|
|
527
|
-
|
|
528
|
-
@patch('arelle.XbrlConst.parentChild', 'http://www.xbrl.org/2003/arcrole/parent-child')
|
|
529
|
-
@patch('arelle.XbrlConst.summationItem', 'http://www.xbrl.org/2003/arcrole/summation-item')
|
|
530
|
-
def test_getRelationships_returns_a_rel(self):
|
|
531
|
-
builder = IXBRLViewerBuilder(Mock())
|
|
532
|
-
builder.currentTargetReport = builder.newTargetReport(None)
|
|
533
|
-
result = builder.getRelationships(self.modelXbrl_1)
|
|
534
|
-
roleMap = builder.roleMap
|
|
535
|
-
siPrefix = roleMap.getPrefix('http://www.xbrl.org/2003/arcrole/summation-item')
|
|
536
|
-
assert result.get(siPrefix).get(roleMap.getPrefix('ELR')).get('us-gaap:from_concept')
|
|
537
|
-
|
|
538
|
-
def test_addRoleDefinition_no_definition(self):
|
|
539
|
-
"""
|
|
540
|
-
Adding an ELR with no definition should result in no entry in the roleDefs map
|
|
541
|
-
"""
|
|
542
|
-
elr = "http://example.com/unknownELR"
|
|
543
|
-
builder = IXBRLViewerBuilder(Mock())
|
|
544
|
-
builder.currentTargetReport = builder.newTargetReport(None)
|
|
545
|
-
builder.addRoleDefinition(self.modelXbrl_1, elr)
|
|
546
|
-
elrPrefix = builder.roleMap.getPrefix(elr)
|
|
547
|
-
assert builder.currentTargetReport.get('roleDefs').get(elrPrefix) is None
|
|
548
|
-
|
|
549
|
-
def test_addRoleDefinition_with_definition(self):
|
|
550
|
-
"""
|
|
551
|
-
Adding an ELR with a definition should result in an "en" label with the definition as its value.
|
|
552
|
-
"""
|
|
553
|
-
elr = "ELR"
|
|
554
|
-
builder = IXBRLViewerBuilder(Mock())
|
|
555
|
-
builder.currentTargetReport = builder.newTargetReport(None)
|
|
556
|
-
builder.addRoleDefinition(self.modelXbrl_1, elr)
|
|
557
|
-
elrPrefix = builder.roleMap.getPrefix(elr)
|
|
558
|
-
assert builder.currentTargetReport.get('roleDefs').get(elrPrefix).get("en") == "ELR Label"
|
|
559
|
-
|
|
560
|
-
@patch('arelle.XbrlConst.conceptLabel', 'http://www.xbrl.org/2003/arcrole/concept-label')
|
|
561
|
-
@patch('arelle.XbrlConst.conceptReference', 'http://www.xbrl.org/2003/arcrole/concept-reference')
|
|
562
|
-
@patch('arelle.XbrlConst.dimensionDefault', 'http://xbrl.org/int/dim/arcrole/dimension-default')
|
|
563
|
-
@patch('arelle.XbrlConst.parentChild', 'http://www.xbrl.org/2003/arcrole/parent-child')
|
|
564
|
-
@patch('arelle.XbrlConst.summationItem', 'http://www.xbrl.org/2003/arcrole/summation-item')
|
|
565
|
-
@patch('arelle.XbrlConst.standardLabel', 'http://www.xbrl.org/2003/role/label')
|
|
566
|
-
@patch('arelle.XbrlConst.documentationLabel', 'http://www.xbrl.org/2003/role/documentation')
|
|
567
|
-
def test_createViewerWithValidation(self):
|
|
568
|
-
js_uri = 'ixbrlviewer.js'
|
|
569
|
-
|
|
570
|
-
error1 = logging.LogRecord("arelle", logging.ERROR, "", 0, "Error message", {}, None)
|
|
571
|
-
error1.messageCode = "code1"
|
|
572
|
-
self.logRecordBuffer.append(error1)
|
|
573
|
-
|
|
574
|
-
builder = IXBRLViewerBuilder(self.cntlr_mock)
|
|
575
|
-
builder.processModel(self.modelXbrl_1)
|
|
576
|
-
result = builder.createViewer(js_uri)
|
|
577
|
-
assert len(result.files) == 1
|
|
578
|
-
body = result.files[0].xmlDocument.getroot()[0]
|
|
579
|
-
assert body[0].text == 'BEGIN IXBRL VIEWER EXTENSIONS'
|
|
580
|
-
assert body[1].attrib.get('src') == js_uri
|
|
581
|
-
assert body[1].attrib.get('type') == 'text/javascript'
|
|
582
|
-
assert body[2].attrib.get('type') == 'application/x.ixbrl-viewer+json'
|
|
583
|
-
assert body[3].text == 'END IXBRL VIEWER EXTENSIONS'
|
|
584
|
-
|
|
585
|
-
jsdata = json.loads(body[2].text)
|
|
586
|
-
errors = jsdata["validation"]
|
|
587
|
-
assert errors == [{"sev": "ERROR", "msg": "Error message", "code": "code1" }]
|
|
588
|
-
assert set(jsdata["sourceReports"][0]["targetReports"][0]["facts"]) == {"fact_id1", "fact_typed_dimension", "fact_dimension_missing_member"}
|
|
589
|
-
assert jsdata["sourceReports"][0]["targetReports"][0]["softwareCredits"] == ["Example Software Name"]
|
|
590
|
-
|
|
591
|
-
@patch('arelle.XbrlConst.conceptLabel', 'http://www.xbrl.org/2003/arcrole/concept-label')
|
|
592
|
-
@patch('arelle.XbrlConst.conceptReference', 'http://www.xbrl.org/2003/arcrole/concept-reference')
|
|
593
|
-
@patch('arelle.XbrlConst.parentChild', 'http://www.xbrl.org/2003/arcrole/parent-child')
|
|
594
|
-
@patch('arelle.XbrlConst.summationItem', 'http://www.xbrl.org/2003/arcrole/summation-item')
|
|
595
|
-
@patch('arelle.XbrlConst.standardLabel', 'http://www.xbrl.org/2003/role/label')
|
|
596
|
-
@patch('arelle.XbrlConst.documentationLabel', 'http://www.xbrl.org/2003/role/documentation')
|
|
597
|
-
@patch('arelle.XbrlConst.dimensionDefault', 'http://xbrl.org/int/dim/arcrole/dimension-default')
|
|
598
|
-
def test_createViewer(self):
|
|
599
|
-
js_uri = 'ixbrlviewer.js'
|
|
600
|
-
builder = IXBRLViewerBuilder(self.cntlr_mock)
|
|
601
|
-
builder.processModel(self.modelXbrl_1)
|
|
602
|
-
result = builder.createViewer(js_uri, showValidations = False)
|
|
603
|
-
assert len(result.files) == 1
|
|
604
|
-
body = result.files[0].xmlDocument.getroot()[0]
|
|
605
|
-
assert body[0].text, 'BEGIN IXBRL VIEWER EXTENSIONS'
|
|
606
|
-
assert body[1].attrib.get('src') == js_uri
|
|
607
|
-
assert body[1].attrib.get('type') == 'text/javascript'
|
|
608
|
-
assert body[2].attrib.get('type') == 'application/x.ixbrl-viewer+json'
|
|
609
|
-
assert body[3].text == 'END IXBRL VIEWER EXTENSIONS'
|
|
610
|
-
|
|
611
|
-
jsdata = json.loads(body[2].text)
|
|
612
|
-
assert "validation" not in jsdata
|
|
613
|
-
reportData = jsdata["sourceReports"][0]["targetReports"][0]
|
|
614
|
-
assert set(reportData["facts"]) == {"fact_id1", "fact_typed_dimension", "fact_dimension_missing_member"}
|
|
615
|
-
assert reportData["concepts"] == {
|
|
616
|
-
'us-gaap:Cash': {'e': True, 't': True, 'labels': {}, 'dt': 'xbrli:monetaryItemType', 'b': 'debit'},
|
|
617
|
-
'us-gaap:from_concept': {'e': True, 't': True, 'labels': {}, 'dt': 'xbrli:monetaryItemType'},
|
|
618
|
-
'us-gaap:to_concept': {'e': True, 't': True, 'labels': {}, 'dt': 'xbrli:monetaryItemType', 'b': 'credit'},
|
|
619
|
-
'us-gaap:dimension': {'d': 'e', 'e': True, 't': True, 'labels': {}, 'dt': 'xbrli:stringItemType'},
|
|
620
|
-
'us-gaap:member': {'e': True, 't': True, 'labels': {}, 'dt': 'xbrli:stringItemType'},
|
|
621
|
-
'us-gaap:typed_dimension_domain': {'e': True, 't': True, 'labels': {}, 'dt': 'xbrli:stringItemType'},
|
|
622
|
-
'us-gaap:typed_dimension': {'d': 't', 'e': True, 't': True, 'labels': {}, 'td': 'us-gaap:typed_dimension_domain', 'dt': 'xs:integer'},
|
|
623
|
-
}
|
|
624
|
-
assert reportData["localDocs"] == {
|
|
625
|
-
'local-inline.htm': ['inline'],
|
|
626
|
-
'local-schema.xsd': ['schema'],
|
|
627
|
-
'local-pres-linkbase.xml': ['presLinkbase'],
|
|
628
|
-
'local-calc-linkbase.xml': ['calcLinkbase'],
|
|
629
|
-
'local-def-linkbase.xml': ['defLinkbase'],
|
|
630
|
-
'local-label-linkbase.xml': ['labelLinkbase'],
|
|
631
|
-
'local-ref-linkbase.xml': ['refLinkbase'],
|
|
632
|
-
'local-unrecognized-linkbase.xml': ['unrecognizedLinkbase'],
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
assert jsdata["sourceReports"][0]["docSetFiles"] == ["a.html"]
|
|
636
|
-
|
|
637
|
-
@patch('arelle.XbrlConst.conceptLabel', 'http://www.xbrl.org/2003/arcrole/concept-label')
|
|
638
|
-
@patch('arelle.XbrlConst.conceptReference', 'http://www.xbrl.org/2003/arcrole/concept-reference')
|
|
639
|
-
@patch('arelle.XbrlConst.parentChild', 'http://www.xbrl.org/2003/arcrole/parent-child')
|
|
640
|
-
@patch('arelle.XbrlConst.summationItem', 'http://www.xbrl.org/2003/arcrole/summation-item')
|
|
641
|
-
@patch('arelle.XbrlConst.standardLabel', 'http://www.xbrl.org/2003/role/label')
|
|
642
|
-
@patch('arelle.XbrlConst.documentationLabel', 'http://www.xbrl.org/2003/role/documentation')
|
|
643
|
-
@patch('arelle.XbrlConst.dimensionDefault', 'http://xbrl.org/int/dim/arcrole/dimension-default')
|
|
644
|
-
def test_createStubViewer(self):
|
|
645
|
-
js_uri = 'ixbrlviewer.js'
|
|
646
|
-
builder = IXBRLViewerBuilder(self.cntlr_mock, useStubViewer = True)
|
|
647
|
-
builder.processModel(self.modelXbrl_1)
|
|
648
|
-
result = builder.createViewer(js_uri, showValidations = False)
|
|
649
|
-
assert len(result.files) == 2
|
|
650
|
-
body = result.files[0].xmlDocument.getroot().find('{http://www.w3.org/1999/xhtml}body')
|
|
651
|
-
assert body[0].text == 'BEGIN IXBRL VIEWER EXTENSIONS'
|
|
652
|
-
assert body[1].attrib.get('src') == js_uri
|
|
653
|
-
assert body[1].attrib.get('type') == 'text/javascript'
|
|
654
|
-
assert body[2].attrib.get('type') == 'application/x.ixbrl-viewer+json'
|
|
655
|
-
assert body[3].text == 'END IXBRL VIEWER EXTENSIONS'
|
|
656
|
-
|
|
657
|
-
jsdata = json.loads(body[2].text)
|
|
658
|
-
assert "validation" not in jsdata
|
|
659
|
-
reportData = jsdata["sourceReports"][0]["targetReports"][0]
|
|
660
|
-
assert set(reportData["facts"]) == {"fact_id1", "fact_typed_dimension", "fact_dimension_missing_member"}
|
|
661
|
-
assert reportData["concepts"] == {
|
|
662
|
-
'us-gaap:Cash': {'e': True, 't': True, 'labels': {}, 'dt': 'xbrli:monetaryItemType', 'b': 'debit'},
|
|
663
|
-
'us-gaap:from_concept': {'e': True, 't': True, 'labels': {}, 'dt': 'xbrli:monetaryItemType'},
|
|
664
|
-
'us-gaap:to_concept': {'e': True, 't': True, 'labels': {}, 'dt': 'xbrli:monetaryItemType', 'b': 'credit'},
|
|
665
|
-
'us-gaap:dimension': {'d': 'e', 'e': True, 't': True, 'labels': {}, 'dt': 'xbrli:stringItemType'},
|
|
666
|
-
'us-gaap:member': {'e': True, 't': True, 'labels': {}, 'dt': 'xbrli:stringItemType'},
|
|
667
|
-
'us-gaap:typed_dimension_domain': {'e': True, 't': True, 'labels': {}, 'dt': 'xbrli:stringItemType'},
|
|
668
|
-
'us-gaap:typed_dimension': {'d': 't', 'e': True, 't': True, 'labels': {}, 'td': 'us-gaap:typed_dimension_domain', 'dt': 'xs:integer'},
|
|
669
|
-
}
|
|
670
|
-
assert reportData["localDocs"] == {
|
|
671
|
-
'local-inline.htm': ['inline'],
|
|
672
|
-
'local-schema.xsd': ['schema'],
|
|
673
|
-
'local-pres-linkbase.xml': ['presLinkbase'],
|
|
674
|
-
'local-calc-linkbase.xml': ['calcLinkbase'],
|
|
675
|
-
'local-def-linkbase.xml': ['defLinkbase'],
|
|
676
|
-
'local-label-linkbase.xml': ['labelLinkbase'],
|
|
677
|
-
'local-ref-linkbase.xml': ['refLinkbase'],
|
|
678
|
-
'local-unrecognized-linkbase.xml': ['unrecognizedLinkbase'],
|
|
679
|
-
}
|
|
680
|
-
|
|
681
|
-
assert jsdata["sourceReports"][0]["docSetFiles"] == [ "a.html" ]
|
|
682
|
-
|
|
683
|
-
@patch('arelle.XbrlConst.conceptLabel', 'http://www.xbrl.org/2003/arcrole/concept-label')
|
|
684
|
-
@patch('arelle.XbrlConst.conceptReference', 'http://www.xbrl.org/2003/arcrole/concept-reference')
|
|
685
|
-
@patch('arelle.XbrlConst.parentChild', 'http://www.xbrl.org/2003/arcrole/parent-child')
|
|
686
|
-
@patch('arelle.XbrlConst.summationItem', 'http://www.xbrl.org/2003/arcrole/summation-item')
|
|
687
|
-
@patch('arelle.XbrlConst.standardLabel', 'http://www.xbrl.org/2003/role/label')
|
|
688
|
-
@patch('arelle.XbrlConst.documentationLabel', 'http://www.xbrl.org/2003/role/documentation')
|
|
689
|
-
@patch('arelle.XbrlConst.dimensionDefault', 'http://xbrl.org/int/dim/arcrole/dimension-default')
|
|
690
|
-
def test_createViewer_docset(self):
|
|
691
|
-
js_uri = 'ixbrlviewer.js'
|
|
692
|
-
self.builder_doc_set.processModel(self.modelXbrlDocSet)
|
|
693
|
-
result = self.builder_doc_set.createViewer(js_uri, showValidations=False)
|
|
694
|
-
assert len(result.files) == 2
|
|
695
|
-
body = result.files[0].xmlDocument.getroot()[0]
|
|
696
|
-
assert body[0].text == 'BEGIN IXBRL VIEWER EXTENSIONS'
|
|
697
|
-
assert body[1].attrib.get('src') == js_uri
|
|
698
|
-
assert body[1].attrib.get('type') == 'text/javascript'
|
|
699
|
-
assert body[2].attrib.get('type') == 'application/x.ixbrl-viewer+json'
|
|
700
|
-
assert body[3].text == 'END IXBRL VIEWER EXTENSIONS'
|
|
701
|
-
|
|
702
|
-
jsdata = json.loads(body[2].text)
|
|
703
|
-
assert "validation" not in jsdata
|
|
704
|
-
reportData = jsdata["sourceReports"][0]["targetReports"][0]
|
|
705
|
-
assert set(reportData["facts"]) == {"fact_id1", "fact_typed_dimension", "fact_dimension_missing_member"}
|
|
706
|
-
|
|
707
|
-
assert jsdata["sourceReports"][0]["docSetFiles"] == [
|
|
708
|
-
'a.html',
|
|
709
|
-
'b.html'
|
|
710
|
-
]
|
|
711
|
-
|
|
712
|
-
@patch('arelle.XbrlConst.conceptLabel', 'http://www.xbrl.org/2003/arcrole/concept-label')
|
|
713
|
-
@patch('arelle.XbrlConst.conceptReference', 'http://www.xbrl.org/2003/arcrole/concept-reference')
|
|
714
|
-
@patch('arelle.XbrlConst.parentChild', 'http://www.xbrl.org/2003/arcrole/parent-child')
|
|
715
|
-
@patch('arelle.XbrlConst.dimensionDefault', 'http://xbrl.org/int/dim/arcrole/dimension-default')
|
|
716
|
-
@patch('arelle.XbrlConst.summationItem', 'http://www.xbrl.org/2003/arcrole/summation-item')
|
|
717
|
-
@patch('arelle.XbrlConst.standardLabel', 'http://www.xbrl.org/2003/role/label')
|
|
718
|
-
@patch('arelle.XbrlConst.documentationLabel', 'http://www.xbrl.org/2003/role/documentation')
|
|
719
|
-
def test_createViewer_bad_path(self):
|
|
720
|
-
js_uri = 'ixbrlviewer.js'
|
|
721
|
-
builder = IXBRLViewerBuilder(self.cntlr_mock)
|
|
722
|
-
builder.processModel(self.modelXbrl_2)
|
|
723
|
-
result = builder.createViewer(js_uri)
|
|
724
|
-
assert len(result.files) == 1
|
|
725
|
-
body = result.files[0].xmlDocument.getroot()[0]
|
|
726
|
-
assert body[0].text == 'BEGIN IXBRL VIEWER EXTENSIONS'
|
|
727
|
-
assert body[1].tag == '{http://www.w3.org/1999/xhtml}script'
|
|
728
|
-
assert body[1].prefix is None
|
|
729
|
-
assert body[1].attrib.get('src') == js_uri
|
|
730
|
-
assert body[1].attrib.get('type') == 'text/javascript'
|
|
731
|
-
assert body[2].tag == '{http://www.w3.org/1999/xhtml}script'
|
|
732
|
-
assert body[2].prefix is None
|
|
733
|
-
assert body[2].attrib.get('type') == 'application/x.ixbrl-viewer+json'
|
|
734
|
-
assert body[3].text == 'END IXBRL VIEWER EXTENSIONS'
|
|
735
|
-
|
|
736
|
-
jsdata = json.loads(body[2].text)
|
|
737
|
-
facts = jsdata["sourceReports"][0]["targetReports"][0]["facts"]
|
|
738
|
-
assert facts.keys() == {"fact_id2", "fact_id3"}
|
|
739
|
-
assert facts["fact_id2"]["a"]["u"] == "iso4217:USD"
|
|
740
|
-
assert facts["fact_id3"]["a"]["u"] is None
|
|
741
|
-
|
|
742
|
-
def test_enableFeature_valid(self):
|
|
743
|
-
"""
|
|
744
|
-
Enable a defined feature
|
|
745
|
-
"""
|
|
746
|
-
builder = IXBRLViewerBuilder(Mock(), features={'review': True})
|
|
747
|
-
assert builder.taxonomyData["features"] == {'review': True}
|
|
748
|
-
|
|
749
|
-
def test_enableFeature_invalid(self):
|
|
750
|
-
"""
|
|
751
|
-
Attempt to enable an undefined feature
|
|
752
|
-
"""
|
|
753
|
-
with pytest.raises(AssertionError, match=rf'^Given feature name `unknown` does not match any defined features'):
|
|
754
|
-
IXBRLViewerBuilder(Mock(), features={'unknown': True})
|
|
755
|
-
|
|
756
|
-
def test_xhtmlNamespaceHandling(self):
|
|
757
|
-
# Check the prefix used for our inserted script tags
|
|
758
|
-
tests = (rb'''
|
|
759
|
-
<html xmlns="http://www.w3.org/1999/xhtml">
|
|
760
|
-
<body>
|
|
761
|
-
</body>
|
|
762
|
-
</html>
|
|
763
|
-
''',
|
|
764
|
-
rb'''
|
|
765
|
-
<html xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml">
|
|
766
|
-
<body>
|
|
767
|
-
</body>
|
|
768
|
-
</html>
|
|
769
|
-
''',
|
|
770
|
-
# In this case we won't fix the root element to be in the default NS,
|
|
771
|
-
# but our <script> tags will be.
|
|
772
|
-
rb'''
|
|
773
|
-
<xhtml:html xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/xhtml">
|
|
774
|
-
<body>
|
|
775
|
-
</body>
|
|
776
|
-
</xhtml:html>
|
|
777
|
-
'''
|
|
778
|
-
)
|
|
779
|
-
|
|
780
|
-
for xmls in tests:
|
|
781
|
-
xml = etree.parse(io.BytesIO(xmls))
|
|
782
|
-
|
|
783
|
-
js_uri = 'https://example.com/script-url'
|
|
784
|
-
viewer_file = iXBRLViewerFile("test.xhtml", xml)
|
|
785
|
-
result = self.builder_1.addViewerData(viewer_file, js_uri)
|
|
786
|
-
|
|
787
|
-
# addViewerData takes a copy, so original body tag should be empty
|
|
788
|
-
original_body = xml.getroot()[0]
|
|
789
|
-
assert len(original_body) == 0
|
|
790
|
-
|
|
791
|
-
body = viewer_file.xmlDocument.getroot()[0]
|
|
792
|
-
assert len(body) == 4
|
|
793
|
-
assert body[0].text == 'BEGIN IXBRL VIEWER EXTENSIONS'
|
|
794
|
-
assert body[1].tag == '{http://www.w3.org/1999/xhtml}script'
|
|
795
|
-
assert body[1].prefix is None
|
|
796
|
-
assert body[1].attrib.get('src') == js_uri
|
|
797
|
-
assert body[1].attrib.get('type') == 'text/javascript'
|
|
798
|
-
assert body[2].tag == '{http://www.w3.org/1999/xhtml}script'
|
|
799
|
-
assert body[2].prefix is None
|
|
800
|
-
assert body[2].attrib.get('type') == 'application/x.ixbrl-viewer+json'
|
|
801
|
-
assert body[3].text == 'END IXBRL VIEWER EXTENSIONS'
|