ixbrl-viewer 1.4.1__py3-none-any.whl → 1.4.86__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.
Files changed (190) hide show
  1. iXBRLViewerPlugin/__init__.py +231 -127
  2. iXBRLViewerPlugin/_version.py +33 -3
  3. iXBRLViewerPlugin/constants.py +96 -2
  4. iXBRLViewerPlugin/featureConfig.py +8 -1
  5. iXBRLViewerPlugin/iXBRLViewer.py +356 -214
  6. iXBRLViewerPlugin/plugin.py +12 -0
  7. iXBRLViewerPlugin/ui.py +81 -50
  8. iXBRLViewerPlugin/viewer/dist/ixbrlviewer.js +1 -1
  9. iXBRLViewerPlugin/viewer/dist/ixbrlviewer.js.LICENSE.txt +12 -5
  10. iXBRLViewerPlugin/viewer/i18next-parser.config.js +1 -1
  11. iXBRLViewerPlugin/viewer/src/data/utr.json +1244 -0
  12. iXBRLViewerPlugin/viewer/src/html/fact-details.html +69 -38
  13. iXBRLViewerPlugin/viewer/src/html/footer-logo.html +4 -0
  14. iXBRLViewerPlugin/viewer/src/html/footnote-details.html +2 -2
  15. iXBRLViewerPlugin/viewer/src/html/inspector.html +352 -197
  16. iXBRLViewerPlugin/viewer/src/i18n/cy/balancetypes.json +1 -0
  17. iXBRLViewerPlugin/viewer/src/i18n/cy/currencies.json +13 -0
  18. iXBRLViewerPlugin/viewer/src/i18n/cy/datatypes.json +9 -0
  19. iXBRLViewerPlugin/viewer/src/i18n/cy/labelroles.json +24 -0
  20. iXBRLViewerPlugin/viewer/src/i18n/cy/referenceparts.json +10 -0
  21. iXBRLViewerPlugin/viewer/src/i18n/cy/scale.json +16 -0
  22. iXBRLViewerPlugin/viewer/src/i18n/cy/tooltips.json +17 -0
  23. iXBRLViewerPlugin/viewer/src/i18n/cy/translation.json +179 -0
  24. iXBRLViewerPlugin/viewer/src/i18n/da/balancetypes.json +4 -0
  25. iXBRLViewerPlugin/viewer/src/i18n/da/currencies.json +13 -0
  26. iXBRLViewerPlugin/viewer/src/i18n/da/datatypes.json +9 -0
  27. iXBRLViewerPlugin/viewer/src/i18n/da/labelroles.json +24 -0
  28. iXBRLViewerPlugin/viewer/src/i18n/da/referenceparts.json +10 -0
  29. iXBRLViewerPlugin/viewer/src/i18n/da/scale.json +15 -0
  30. iXBRLViewerPlugin/viewer/src/i18n/da/tooltips.json +17 -0
  31. iXBRLViewerPlugin/viewer/src/i18n/da/translation.json +179 -0
  32. iXBRLViewerPlugin/viewer/src/i18n/de/balancetypes.json +4 -0
  33. iXBRLViewerPlugin/viewer/src/i18n/de/currencies.json +13 -0
  34. iXBRLViewerPlugin/viewer/src/i18n/de/datatypes.json +9 -0
  35. iXBRLViewerPlugin/viewer/src/i18n/de/labelroles.json +24 -0
  36. iXBRLViewerPlugin/viewer/src/i18n/de/referenceparts.json +10 -0
  37. iXBRLViewerPlugin/viewer/src/i18n/de/scale.json +15 -0
  38. iXBRLViewerPlugin/viewer/src/i18n/de/tooltips.json +17 -0
  39. iXBRLViewerPlugin/viewer/src/i18n/de/translation.json +179 -0
  40. iXBRLViewerPlugin/viewer/src/i18n/en/balancetypes.json +4 -0
  41. iXBRLViewerPlugin/viewer/src/i18n/en/datatypes.json +10 -0
  42. iXBRLViewerPlugin/viewer/src/i18n/en/labelroles.json +4 -0
  43. iXBRLViewerPlugin/viewer/src/i18n/en/scale.json +16 -0
  44. iXBRLViewerPlugin/viewer/src/i18n/en/tooltips.json +17 -0
  45. iXBRLViewerPlugin/viewer/src/i18n/en/translation.json +73 -23
  46. iXBRLViewerPlugin/viewer/src/i18n/es/balancetypes.json +4 -0
  47. iXBRLViewerPlugin/viewer/src/i18n/es/datatypes.json +10 -0
  48. iXBRLViewerPlugin/viewer/src/i18n/es/labelroles.json +24 -0
  49. iXBRLViewerPlugin/viewer/src/i18n/es/scale.json +16 -0
  50. iXBRLViewerPlugin/viewer/src/i18n/es/tooltips.json +17 -0
  51. iXBRLViewerPlugin/viewer/src/i18n/es/translation.json +87 -37
  52. iXBRLViewerPlugin/viewer/src/i18n/fr/balancetypes.json +4 -0
  53. iXBRLViewerPlugin/viewer/src/i18n/fr/currencies.json +13 -0
  54. iXBRLViewerPlugin/viewer/src/i18n/fr/datatypes.json +9 -0
  55. iXBRLViewerPlugin/viewer/src/i18n/fr/labelroles.json +24 -0
  56. iXBRLViewerPlugin/viewer/src/i18n/fr/referenceparts.json +10 -0
  57. iXBRLViewerPlugin/viewer/src/i18n/fr/scale.json +15 -0
  58. iXBRLViewerPlugin/viewer/src/i18n/fr/tooltips.json +17 -0
  59. iXBRLViewerPlugin/viewer/src/i18n/fr/translation.json +179 -0
  60. iXBRLViewerPlugin/viewer/src/i18n/nl/balancetypes.json +4 -0
  61. iXBRLViewerPlugin/viewer/src/i18n/nl/currencies.json +13 -0
  62. iXBRLViewerPlugin/viewer/src/i18n/nl/datatypes.json +9 -0
  63. iXBRLViewerPlugin/viewer/src/i18n/nl/labelroles.json +24 -0
  64. iXBRLViewerPlugin/viewer/src/i18n/nl/referenceparts.json +10 -0
  65. iXBRLViewerPlugin/viewer/src/i18n/nl/scale.json +15 -0
  66. iXBRLViewerPlugin/viewer/src/i18n/nl/tooltips.json +17 -0
  67. iXBRLViewerPlugin/viewer/src/i18n/nl/translation.json +179 -0
  68. iXBRLViewerPlugin/viewer/src/i18n/uk/balancetypes.json +4 -0
  69. iXBRLViewerPlugin/viewer/src/i18n/uk/currencies.json +13 -0
  70. iXBRLViewerPlugin/viewer/src/i18n/uk/datatypes.json +9 -0
  71. iXBRLViewerPlugin/viewer/src/i18n/uk/labelroles.json +24 -0
  72. iXBRLViewerPlugin/viewer/src/i18n/uk/referenceparts.json +10 -0
  73. iXBRLViewerPlugin/viewer/src/i18n/uk/scale.json +15 -0
  74. iXBRLViewerPlugin/viewer/src/i18n/uk/tooltips.json +17 -0
  75. iXBRLViewerPlugin/viewer/src/i18n/uk/translation.json +179 -0
  76. iXBRLViewerPlugin/viewer/src/icons/calculator.svg +13 -0
  77. iXBRLViewerPlugin/viewer/src/icons/circle-cross.svg +11 -0
  78. iXBRLViewerPlugin/viewer/src/icons/circle-tick.svg +11 -0
  79. iXBRLViewerPlugin/viewer/src/icons/dark-mode.svg +4 -0
  80. iXBRLViewerPlugin/viewer/src/icons/dimension.svg +1 -5
  81. iXBRLViewerPlugin/viewer/src/icons/member.svg +2 -5
  82. iXBRLViewerPlugin/viewer/src/icons/multi-tag.svg +10 -0
  83. iXBRLViewerPlugin/viewer/src/img/arelle-dark.svg +179 -0
  84. iXBRLViewerPlugin/viewer/src/img/inline-viewer-dark.svg +59 -0
  85. iXBRLViewerPlugin/viewer/src/js/accordian.js +5 -4
  86. iXBRLViewerPlugin/viewer/src/js/aspect.js +29 -10
  87. iXBRLViewerPlugin/viewer/src/js/aspect.test.js +40 -31
  88. iXBRLViewerPlugin/viewer/src/js/balance.js +14 -0
  89. iXBRLViewerPlugin/viewer/src/js/calculation.js +213 -0
  90. iXBRLViewerPlugin/viewer/src/js/calculation.test.js +306 -0
  91. iXBRLViewerPlugin/viewer/src/js/calculationInspector.js +187 -0
  92. iXBRLViewerPlugin/viewer/src/js/chart.js +26 -24
  93. iXBRLViewerPlugin/viewer/src/js/chart.test.js +10 -9
  94. iXBRLViewerPlugin/viewer/src/js/concept.js +37 -4
  95. iXBRLViewerPlugin/viewer/src/js/concept.test.js +30 -6
  96. iXBRLViewerPlugin/viewer/src/js/datatype.js +20 -0
  97. iXBRLViewerPlugin/viewer/src/js/datatype.test.js +62 -0
  98. iXBRLViewerPlugin/viewer/src/js/dialog.js +6 -4
  99. iXBRLViewerPlugin/viewer/src/js/docOrderIndex.js +7 -7
  100. iXBRLViewerPlugin/viewer/src/js/fact.js +156 -59
  101. iXBRLViewerPlugin/viewer/src/js/fact.test.js +160 -29
  102. iXBRLViewerPlugin/viewer/src/js/factset.js +64 -15
  103. iXBRLViewerPlugin/viewer/src/js/factset.test.js +102 -31
  104. iXBRLViewerPlugin/viewer/src/js/footnote.js +8 -2
  105. iXBRLViewerPlugin/viewer/src/js/index.js +11 -3
  106. iXBRLViewerPlugin/viewer/src/js/inspector.js +747 -221
  107. iXBRLViewerPlugin/viewer/src/js/inspector.test.js +143 -25
  108. iXBRLViewerPlugin/viewer/src/js/interval.js +70 -0
  109. iXBRLViewerPlugin/viewer/src/js/interval.test.js +153 -0
  110. iXBRLViewerPlugin/viewer/src/js/ixbrlviewer.js +391 -262
  111. iXBRLViewerPlugin/viewer/src/js/ixbrlviewer.test.js +134 -20
  112. iXBRLViewerPlugin/viewer/src/js/ixnode.js +1 -1
  113. iXBRLViewerPlugin/viewer/src/js/menu.js +25 -7
  114. iXBRLViewerPlugin/viewer/src/js/number-matcher.js +7 -3
  115. iXBRLViewerPlugin/viewer/src/js/number-matcher.test.js +4 -0
  116. iXBRLViewerPlugin/viewer/src/js/outline.js +34 -13
  117. iXBRLViewerPlugin/viewer/src/js/outline.test.js +97 -91
  118. iXBRLViewerPlugin/viewer/src/js/period.js +0 -1
  119. iXBRLViewerPlugin/viewer/src/js/report.js +260 -351
  120. iXBRLViewerPlugin/viewer/src/js/report.test.js +95 -27
  121. iXBRLViewerPlugin/viewer/src/js/reportset.js +264 -0
  122. iXBRLViewerPlugin/viewer/src/js/reportset.test.js +357 -0
  123. iXBRLViewerPlugin/viewer/src/js/search.js +72 -38
  124. iXBRLViewerPlugin/viewer/src/js/search.test.js +184 -84
  125. iXBRLViewerPlugin/viewer/src/js/summary.js +34 -8
  126. iXBRLViewerPlugin/viewer/src/js/summary.test.js +69 -25
  127. iXBRLViewerPlugin/viewer/src/js/tableExport.js +9 -9
  128. iXBRLViewerPlugin/viewer/src/js/taxonomynamer.js +34 -0
  129. iXBRLViewerPlugin/viewer/src/js/taxonomynamer.test.js +32 -0
  130. iXBRLViewerPlugin/viewer/src/js/test-utils.js +46 -0
  131. iXBRLViewerPlugin/viewer/src/js/theme.js +50 -0
  132. iXBRLViewerPlugin/viewer/src/js/unit.js +90 -32
  133. iXBRLViewerPlugin/viewer/src/js/unit.test.js +62 -25
  134. iXBRLViewerPlugin/viewer/src/js/util.js +94 -0
  135. iXBRLViewerPlugin/viewer/src/js/util.test.js +33 -1
  136. iXBRLViewerPlugin/viewer/src/js/utr.js +27 -0
  137. iXBRLViewerPlugin/viewer/src/js/viewer.js +205 -181
  138. iXBRLViewerPlugin/viewer/src/js/viewerOptions.js +0 -2
  139. iXBRLViewerPlugin/viewer/src/less/accordian.less +10 -6
  140. iXBRLViewerPlugin/viewer/src/less/block-list.less +16 -5
  141. iXBRLViewerPlugin/viewer/src/less/calculation-inspector.less +83 -0
  142. iXBRLViewerPlugin/viewer/src/less/chart.less +8 -5
  143. iXBRLViewerPlugin/viewer/src/less/colours-dark-mode.less +40 -0
  144. iXBRLViewerPlugin/viewer/src/less/colours.less +32 -20
  145. iXBRLViewerPlugin/viewer/src/less/common.less +3 -3
  146. iXBRLViewerPlugin/viewer/src/less/components.less +6 -4
  147. iXBRLViewerPlugin/viewer/src/less/core.less +2 -0
  148. iXBRLViewerPlugin/viewer/src/less/dialog.less +21 -14
  149. iXBRLViewerPlugin/viewer/src/less/form-controls.less +33 -11
  150. iXBRLViewerPlugin/viewer/src/less/inspector.less +1045 -726
  151. iXBRLViewerPlugin/viewer/src/less/loader.less +2 -2
  152. iXBRLViewerPlugin/viewer/src/less/menu.less +33 -15
  153. iXBRLViewerPlugin/viewer/src/less/summary.less +16 -6
  154. iXBRLViewerPlugin/viewer/src/less/tabs.less +9 -9
  155. iXBRLViewerPlugin/viewer/src/less/text-block-viewer.less +2 -0
  156. iXBRLViewerPlugin/viewer/src/less/text-mixins.less +2 -1
  157. iXBRLViewerPlugin/viewer/src/less/validation-report.less +2 -3
  158. iXBRLViewerPlugin/viewer/src/less/viewer.less +105 -74
  159. iXBRLViewerPlugin/viewer/webpack.common.js +19 -9
  160. iXBRLViewerPlugin/xhtmlserialize.py +59 -45
  161. {ixbrl_viewer-1.4.1.dist-info → ixbrl_viewer-1.4.86.dist-info}/METADATA +181 -50
  162. ixbrl_viewer-1.4.86.dist-info/RECORD +217 -0
  163. {ixbrl_viewer-1.4.1.dist-info → ixbrl_viewer-1.4.86.dist-info}/WHEEL +1 -1
  164. ixbrl_viewer-1.4.1.dist-info/LICENSE → ixbrl_viewer-1.4.86.dist-info/licenses/LICENSE.md +8 -14
  165. {ixbrl_viewer-1.4.1.dist-info → ixbrl_viewer-1.4.86.dist-info}/top_level.txt +0 -1
  166. iXBRLViewerPlugin/viewer/src/js/calculations.js +0 -111
  167. iXBRLViewerPlugin/viewer/src/js/interact.min.js +0 -6
  168. ixbrl_viewer-1.4.1.dist-info/RECORD +0 -155
  169. tests/__init__.py +0 -0
  170. tests/puppeteer/framework/core_elements.js +0 -117
  171. tests/puppeteer/framework/page_objects/doc_frame.js +0 -105
  172. tests/puppeteer/framework/page_objects/fact_details_panel.js +0 -80
  173. tests/puppeteer/framework/page_objects/search_panel.js +0 -76
  174. tests/puppeteer/framework/page_objects/toolbar.js +0 -18
  175. tests/puppeteer/framework/utils.js +0 -3
  176. tests/puppeteer/framework/viewer_page.js +0 -103
  177. tests/puppeteer/puppeteer_test_run_via_intellij.jpg +0 -0
  178. tests/puppeteer/test_filings/filing_documents_smoke_test.zip +0 -0
  179. tests/puppeteer/test_filings/highlights.zip +0 -0
  180. tests/puppeteer/tests/fact_properties.test.js +0 -78
  181. tests/puppeteer/tests/highlight.test.js +0 -186
  182. tests/puppeteer/tests/search.test.js +0 -86
  183. tests/puppeteer/tools/generate.sh +0 -15
  184. tests/unit_tests/__init__.py +0 -0
  185. tests/unit_tests/iXBRLViewerPlugin/__init__.py +0 -0
  186. tests/unit_tests/iXBRLViewerPlugin/mock_arelle.py +0 -39
  187. tests/unit_tests/iXBRLViewerPlugin/test_iXBRLViewer.py +0 -641
  188. tests/unit_tests/iXBRLViewerPlugin/test_xhtmlserialize.py +0 -310
  189. {ixbrl_viewer-1.4.1.dist-info → ixbrl_viewer-1.4.86.dist-info}/entry_points.txt +0 -0
  190. {ixbrl_viewer-1.4.1.dist-info → ixbrl_viewer-1.4.86.dist-info/licenses}/NOTICE +0 -0
@@ -1,14 +1,14 @@
1
1
  // See COPYRIGHT.md for copyright information
2
2
 
3
- import { Fact } from "./fact.js";
4
- import { iXBRLReport } from "./report.js";
3
+ import { ReportSet } from "./reportset.js";
5
4
  import { TestInspector } from "./test-utils.js";
5
+ import { NAMESPACE_ISO4217, SHOW_FACT, viewerUniqueId } from "./util.js";
6
6
 
7
7
 
8
- var testReportData = {
8
+ const testReportData = {
9
9
  "prefixes": {
10
10
  "eg": "http://www.example.com",
11
- "iso4217": "http://www.xbrl.org/2003/iso4217",
11
+ "iso4217": NAMESPACE_ISO4217,
12
12
  "e": "http://example.com/entity",
13
13
  },
14
14
  "concepts": {
@@ -39,42 +39,42 @@ var testReportData = {
39
39
  "roles": {},
40
40
  "roleDefs": {},
41
41
  "rels": {},
42
- "units": {},
43
42
  };
44
43
 
45
44
  function testReport(facts, ixData) {
46
45
  // Deep copy of standing data
47
- var data = JSON.parse(JSON.stringify(testReportData));
46
+ const data = JSON.parse(JSON.stringify(testReportData));
48
47
  data.facts = facts;
49
- var report = new iXBRLReport(data);
50
- report.setIXNodeMap(ixData);
51
- return report;
48
+ const reportSet = new ReportSet(data);
49
+ reportSet.setIXNodeMap(ixData);
50
+ return reportSet;
52
51
  }
53
52
 
54
53
  function fromFact(value) {
55
- var factData = {
54
+ const factData = {
56
55
  "v": value,
57
56
  "a": {
58
57
  "c": "eg:Concept1",
59
58
  "u": "iso4217:USD",
60
59
  "p": "2017-01-01/2018-01-01",
61
60
  }};
62
- return new Fact(testReport({"f1": factData}, {"f1": {} }), "f1");
61
+ return testReport({"f1": factData}, {"f1": {} }).getItemById("0-f1");
63
62
  }
64
63
 
65
64
  function toFact(value) {
66
- var factData = {
65
+ const factData = {
67
66
  "v": value,
68
67
  "a": {
69
68
  "c": "eg:Concept1",
70
69
  "u": "iso4217:USD",
71
70
  "p": "2018-01-01/2019-01-01",
72
71
  }};
73
- return new Fact(testReport({"f1": factData}, {"f1": {} }), "f1");
72
+
73
+ return testReport({"f1": factData}, {"f1": {} }).getItemById("0-f1");
74
74
  }
75
75
 
76
76
  describe("Describe changes", () => {
77
- var insp = new TestInspector();
77
+ const insp = new TestInspector();
78
78
  beforeAll(() => {
79
79
  return insp.i18nInit();
80
80
  });
@@ -117,7 +117,7 @@ describe("Scales filter options", () => {
117
117
  if (scale !== 0) {
118
118
  ixNode["scale"] = scale;
119
119
  }
120
- ixData[id] = ixNode;
120
+ ixData[viewerUniqueId(0, id)] = ixNode;
121
121
  }
122
122
  const nonMonetaryFactData = {};
123
123
  for (let scale = -4; scale < 11; scale++) {
@@ -127,16 +127,16 @@ describe("Scales filter options", () => {
127
127
  if (scale !== 0) {
128
128
  ixNode["scale"] = scale;
129
129
  }
130
- ixData[id] = ixNode;
130
+ ixData[viewerUniqueId(0, id)] = ixNode;
131
131
  }
132
132
 
133
133
  test("Scales filter options with monetary and non-monetary facts", () => {
134
- var insp = new TestInspector();
135
- const report = testReport({
134
+ const insp = new TestInspector();
135
+ const reportSet = testReport({
136
136
  ...monetaryFactData,
137
137
  ...nonMonetaryFactData,
138
138
  }, ixData);
139
- insp.initialize(report)
139
+ insp.initialize(reportSet)
140
140
  insp.i18nInit();
141
141
  const scalesOptions = insp._getScalesOptions();
142
142
  expect(scalesOptions).toEqual({
@@ -158,11 +158,11 @@ describe("Scales filter options", () => {
158
158
  })
159
159
 
160
160
  test("Scales filter options with only monetary facts", () => {
161
- var insp = new TestInspector();
162
- const report = testReport({
161
+ const insp = new TestInspector();
162
+ const reportSet = testReport({
163
163
  ...monetaryFactData,
164
164
  }, ixData);
165
- insp.initialize(report)
165
+ insp.initialize(reportSet)
166
166
  insp.i18nInit();
167
167
  const scalesOptions = insp._getScalesOptions();
168
168
  expect(scalesOptions).toEqual({
@@ -184,11 +184,11 @@ describe("Scales filter options", () => {
184
184
  })
185
185
 
186
186
  test("Scales filter options with only non-monetary facts", () => {
187
- var insp = new TestInspector();
188
- const report = testReport({
187
+ const insp = new TestInspector();
188
+ const reportSet = testReport({
189
189
  ...nonMonetaryFactData,
190
190
  }, ixData);
191
- insp.initialize(report)
191
+ insp.initialize(reportSet)
192
192
  insp.i18nInit();
193
193
  const scalesOptions = insp._getScalesOptions();
194
194
  expect(scalesOptions).toEqual({
@@ -209,3 +209,121 @@ describe("Scales filter options", () => {
209
209
  });
210
210
  })
211
211
  });
212
+
213
+ describe("Fact deep link", () => {
214
+ const insp = new TestInspector();
215
+ insp._reportSet = {
216
+ getItemById: jest.fn(id => ["0-123", "1-abc"].includes(id) ? true : undefined),
217
+ };
218
+ const mockSelect = jest.fn(id => true);
219
+ insp.selectItem = mockSelect;
220
+ test("Old style fact deep link", () => {
221
+ mockSelect.mockClear();
222
+ location.hash = "#f-123";
223
+ insp.handleFactDeepLink();
224
+ expect(mockSelect).toHaveBeenCalledWith("0-123");
225
+ })
226
+ test("Old style fact deep link (non-existent)", () => {
227
+ mockSelect.mockClear();
228
+ location.hash = "#f-1234";
229
+ insp.handleFactDeepLink();
230
+ expect(mockSelect).not.toHaveBeenCalled();
231
+ })
232
+ test("New style fact deep link", () => {
233
+ mockSelect.mockClear();
234
+ location.hash = "#f0-123";
235
+ insp.handleFactDeepLink();
236
+ expect(mockSelect).toHaveBeenCalledWith("0-123");
237
+ })
238
+ test("New style fact deep link", () => {
239
+ mockSelect.mockClear();
240
+ location.hash = "#f1-abc";
241
+ insp.handleFactDeepLink();
242
+ expect(mockSelect).toHaveBeenCalledWith("1-abc");
243
+ })
244
+ test("New style fact deep link (non-existent)", () => {
245
+ mockSelect.mockClear();
246
+ location.hash = "#f0-1234";
247
+ insp.handleFactDeepLink();
248
+ expect(mockSelect).not.toHaveBeenCalled();
249
+ })
250
+ });
251
+
252
+ describe("Handle message", () => {
253
+ const generateEvent = (data) => {
254
+ return {
255
+ originalEvent: {
256
+ data: JSON.stringify(data)
257
+ }
258
+ };
259
+ }
260
+ const insp = new TestInspector();
261
+ insp._reportSet = {
262
+ getItemById: jest.fn(id => ["0-123", "1-abc"].includes(id) ? true : undefined),
263
+ };
264
+ const mockSelect = jest.fn(id => true);
265
+ insp.selectItem = mockSelect;
266
+ it.each([
267
+ ["0", "0-123"],
268
+ [0, "0-123"],
269
+ [undefined, "0-123"],
270
+ ["1", "1-123"],
271
+ [1, "1-123"],
272
+ ["X", "0-123"],
273
+ ])("SHOW_FACT task with valid factID and %p docSetId selects VUID %p", (docSetId, result) => {
274
+ mockSelect.mockClear();
275
+ const data = {
276
+ task: SHOW_FACT,
277
+ factId: "123",
278
+ }
279
+ if (docSetId !== undefined) {
280
+ data["docSetId"] = docSetId
281
+ }
282
+ const event = generateEvent({
283
+ task: SHOW_FACT,
284
+ factId: "123",
285
+ docSetId: docSetId
286
+ });
287
+ insp.handleMessage(event);
288
+ expect(mockSelect).toHaveBeenCalledWith(result);
289
+ });
290
+ test("SHOW_FACT with no factId", () => {
291
+ mockSelect.mockClear();
292
+ const event = generateEvent({
293
+ task: SHOW_FACT,
294
+ docSetId: "0",
295
+ });
296
+ insp.handleMessage(event);
297
+ expect(mockSelect).toHaveBeenCalledWith(null);
298
+ })
299
+ test("SHOW_FACT with empty factId", () => {
300
+ mockSelect.mockClear();
301
+ const event = generateEvent({
302
+ task: SHOW_FACT,
303
+ factId: "",
304
+ });
305
+ insp.handleMessage(event);
306
+ expect(mockSelect).toHaveBeenCalledWith("0-");
307
+ })
308
+ test("Invalid task", () => {
309
+ mockSelect.mockClear();
310
+ const event = generateEvent({
311
+ task: "INVALID_TASK",
312
+ });
313
+ insp.handleMessage(event);
314
+ expect(mockSelect).not.toHaveBeenCalled();
315
+ })
316
+ test("Invalid JSON", () => {
317
+ mockSelect.mockClear();
318
+ const event = {
319
+ originalEvent: {
320
+ data: `{
321
+ task: "SHOW_TASK"
322
+ factId: "f1-abc"
323
+ }`
324
+ }
325
+ };
326
+ insp.handleMessage(event);
327
+ expect(mockSelect).not.toHaveBeenCalled();
328
+ })
329
+ });
@@ -0,0 +1,70 @@
1
+ // See COPYRIGHT.md for copyright information
2
+
3
+ import Decimal from 'decimal.js';
4
+
5
+ /*
6
+ * Class for working with numeric intervals, of the form: [a, b]
7
+ *
8
+ * Interval is closed (includes both bounds)
9
+ * a must be <= b
10
+ */
11
+ export class Interval {
12
+
13
+ constructor(a, b) {
14
+ this.a = typeof a == 'object' ? a : new Decimal(a);
15
+ this.b = typeof b == 'object' ? b : new Decimal(b);
16
+ }
17
+
18
+ static fromFact(fact) {
19
+ if (!fact.isNumeric()) {
20
+ return undefined;
21
+ }
22
+ const decimals = fact.decimals();
23
+ let width = 0;
24
+ if (decimals !== undefined) {
25
+ const x = new Decimal(10);
26
+ width = x.pow(0-decimals).times(0.5);
27
+ }
28
+ let value;
29
+ const factValue = fact.value();
30
+ try {
31
+ value = new Decimal(factValue);
32
+ } catch (e) {
33
+ if (e instanceof Error && /DecimalError/.test(e.message)) {
34
+ return undefined;
35
+ }
36
+ throw e;
37
+ }
38
+ return new Interval(value.minus(width), value.plus(width));
39
+ }
40
+
41
+ intersection(other) {
42
+ return Interval.intersection(this, other);
43
+ }
44
+
45
+ static intersection(...intervals) {
46
+ if (intervals.includes(undefined) || intervals.length == 0) {
47
+ return undefined;
48
+ }
49
+ const aa = intervals.map(x => x.a);
50
+ const bb = intervals.map(x => x.b);
51
+ const a = Decimal.max(...aa);
52
+ const b = Decimal.min(...bb);
53
+ if (b.lessThan(a)) {
54
+ return undefined;
55
+ }
56
+ return new Interval(a, b);
57
+ }
58
+
59
+ plus(other) {
60
+ return new Interval(this.a.plus(other.a), this.b.plus(other.b));
61
+ }
62
+
63
+ times(x) {
64
+ return x > 0 ? new Interval(this.a.times(x), this.b.times(x)) : new Interval(this.b.times(x), this.a.times(x));
65
+ }
66
+
67
+ midpoint() {
68
+ return Decimal.add(this.a, this.b).div(2);
69
+ }
70
+ }
@@ -0,0 +1,153 @@
1
+ // Copyright 2019 Workiva Inc.
2
+ //
3
+ // Licensed under the Apache License, Version 2.0 (the "License");
4
+ // you may not use this file except in compliance with the License.
5
+ // You may obtain a copy of the License at
6
+ //
7
+ // http://www.apache.org/licenses/LICENSE-2.0
8
+ //
9
+ // Unless required by applicable law or agreed to in writing, software
10
+ // distributed under the License is distributed on an "AS IS" BASIS,
11
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ // See the License for the specific language governing permissions and
13
+ // limitations under the License.
14
+
15
+ import { Fact } from "./fact.js";
16
+ import { Interval } from "./interval.js";
17
+ import { ReportSet } from "./reportset.js";
18
+ import Decimal from 'decimal.js';
19
+ import { viewerUniqueId } from "./util.js";
20
+ import './test-utils.js';
21
+
22
+ function testReportSet(facts) {
23
+ const reportset = new ReportSet({
24
+ prefixes: {},
25
+ concepts: {},
26
+ facts: facts
27
+ });
28
+ reportset._initialize();
29
+ return reportset;
30
+ }
31
+
32
+ function testFact(factData) {
33
+ factData.a = factData.a || {};
34
+ factData.a.c = factData.a.c || 'eg:Concept1';
35
+ if (!('u' in factData.a)) {
36
+ factData.a.u = 'eg:pure';
37
+ }
38
+ else if (factData.a.u === undefined) {
39
+ delete factData.a.u;
40
+ }
41
+ return testReportSet({"f1": factData}).getItemById(viewerUniqueId(0, "f1"));
42
+ }
43
+
44
+ describe("From facts", () => {
45
+ test("Infinite precision", () => {
46
+ var i = Interval.fromFact(testFact({v: 20}));
47
+ expect(i.a).toEqualDecimal(20);
48
+ expect(i.b).toEqualDecimal(20);
49
+
50
+ i = Interval.fromFact(testFact({v: -20}));
51
+ expect(i.a).toEqualDecimal(-20);
52
+ expect(i.b).toEqualDecimal(-20);
53
+ });
54
+
55
+ test("Finite precision", () => {
56
+ var i = Interval.fromFact(testFact({v: 20, d: 0}));
57
+ expect(i.a).toEqualDecimal(19.5);
58
+ expect(i.b).toEqualDecimal(20.5);
59
+
60
+ i = Interval.fromFact(testFact({v: -20.123, d: 3}));
61
+ expect(i.a).toEqualDecimal(-20.1235);
62
+ expect(i.b).toEqualDecimal(-20.1225);
63
+
64
+ i = Interval.fromFact(testFact({v: -20.123, d: -1}));
65
+ expect(i.a).toEqualDecimal(-25.123);
66
+ expect(i.b).toEqualDecimal(-15.123);
67
+ });
68
+
69
+ test("Non numeric", () => {
70
+ var i = Interval.fromFact(testFact({v: 20, a: {u: undefined}}));
71
+ expect(i).toBeUndefined();
72
+
73
+ // This would be invalid XBRL
74
+ i = Interval.fromFact(testFact({v: "abc" }));
75
+ expect(i).toBeUndefined();
76
+ });
77
+ });
78
+
79
+
80
+ describe("Intersect", () => {
81
+ test("Intersecting", () => {
82
+ var x = new Interval(5, 15);
83
+ var y = new Interval(10, 25);
84
+ var ii = x.intersection(y);
85
+ expect(ii.a).toEqualDecimal(10);
86
+ expect(ii.b).toEqualDecimal(15);
87
+
88
+ ii = Interval.intersection(x, y);
89
+ expect(ii.a).toEqualDecimal(10);
90
+ expect(ii.b).toEqualDecimal(15);
91
+
92
+ ii = y.intersection(x);
93
+ expect(ii.a).toEqualDecimal(10);
94
+ expect(ii.b).toEqualDecimal(15);
95
+
96
+ y = new Interval(15, 25);
97
+ ii = x.intersection(y);
98
+ expect(ii.a).toEqualDecimal(15);
99
+ expect(ii.b).toEqualDecimal(15);
100
+
101
+ x = new Interval(10, 20);
102
+ y = new Interval(15, 25);
103
+ var z = new Interval(18, 30);
104
+ ii = Interval.intersection(x, y, z);
105
+ expect(ii.a).toEqualDecimal(18);
106
+ expect(ii.b).toEqualDecimal(20);
107
+
108
+ });
109
+
110
+ test("No intersection", () => {
111
+ var x = new Interval(5, 15);
112
+ expect(x.intersection(new Interval(20, 25))).toBeUndefined();
113
+ expect(x.intersection(new Interval(1, 4.99))).toBeUndefined();
114
+
115
+ x = new Interval(10, 20);
116
+ var y = new Interval(15, 25);
117
+ var z = new Interval(21, 30);
118
+ expect(Interval.intersection(x, y, z)).toBeUndefined();
119
+ });
120
+ })
121
+
122
+ describe("Arithmetic", () => {
123
+ test("Add", () => {
124
+ var i = new Interval(5, 15);
125
+ var ii = i.plus(new Interval(10, 20));
126
+ expect(ii.a).toEqualDecimal(15);
127
+ expect(ii.b).toEqualDecimal(35);
128
+ });
129
+
130
+ test("Multiply", () => {
131
+ var i = new Interval(5, 15);
132
+ var ii = i.times(2);
133
+ expect(ii.a).toEqualDecimal(10);
134
+ expect(ii.b).toEqualDecimal(30);
135
+
136
+ ii = i.times(-2);
137
+ expect(ii.a).toEqualDecimal(-30);
138
+ expect(ii.b).toEqualDecimal(-10);
139
+
140
+ i = new Interval(-10, -5);
141
+ ii = i.times(2);
142
+ expect(ii.a).toEqualDecimal(-20);
143
+ expect(ii.b).toEqualDecimal(-10);
144
+
145
+ ii = i.times(-2);
146
+ expect(ii.a).toEqualDecimal(10);
147
+ expect(ii.b).toEqualDecimal(20);
148
+
149
+ });
150
+
151
+ });
152
+
153
+