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.
- iXBRLViewerPlugin/__init__.py +231 -127
- iXBRLViewerPlugin/_version.py +33 -3
- iXBRLViewerPlugin/constants.py +96 -2
- iXBRLViewerPlugin/featureConfig.py +8 -1
- iXBRLViewerPlugin/iXBRLViewer.py +356 -214
- iXBRLViewerPlugin/plugin.py +12 -0
- iXBRLViewerPlugin/ui.py +81 -50
- iXBRLViewerPlugin/viewer/dist/ixbrlviewer.js +1 -1
- iXBRLViewerPlugin/viewer/dist/ixbrlviewer.js.LICENSE.txt +12 -5
- iXBRLViewerPlugin/viewer/i18next-parser.config.js +1 -1
- iXBRLViewerPlugin/viewer/src/data/utr.json +1244 -0
- iXBRLViewerPlugin/viewer/src/html/fact-details.html +69 -38
- iXBRLViewerPlugin/viewer/src/html/footer-logo.html +4 -0
- iXBRLViewerPlugin/viewer/src/html/footnote-details.html +2 -2
- iXBRLViewerPlugin/viewer/src/html/inspector.html +352 -197
- iXBRLViewerPlugin/viewer/src/i18n/cy/balancetypes.json +1 -0
- iXBRLViewerPlugin/viewer/src/i18n/cy/currencies.json +13 -0
- iXBRLViewerPlugin/viewer/src/i18n/cy/datatypes.json +9 -0
- iXBRLViewerPlugin/viewer/src/i18n/cy/labelroles.json +24 -0
- iXBRLViewerPlugin/viewer/src/i18n/cy/referenceparts.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/cy/scale.json +16 -0
- iXBRLViewerPlugin/viewer/src/i18n/cy/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/cy/translation.json +179 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/balancetypes.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/currencies.json +13 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/datatypes.json +9 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/labelroles.json +24 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/referenceparts.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/scale.json +15 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/da/translation.json +179 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/balancetypes.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/currencies.json +13 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/datatypes.json +9 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/labelroles.json +24 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/referenceparts.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/scale.json +15 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/de/translation.json +179 -0
- iXBRLViewerPlugin/viewer/src/i18n/en/balancetypes.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/en/datatypes.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/en/labelroles.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/en/scale.json +16 -0
- iXBRLViewerPlugin/viewer/src/i18n/en/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/en/translation.json +73 -23
- iXBRLViewerPlugin/viewer/src/i18n/es/balancetypes.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/es/datatypes.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/es/labelroles.json +24 -0
- iXBRLViewerPlugin/viewer/src/i18n/es/scale.json +16 -0
- iXBRLViewerPlugin/viewer/src/i18n/es/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/es/translation.json +87 -37
- iXBRLViewerPlugin/viewer/src/i18n/fr/balancetypes.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/fr/currencies.json +13 -0
- iXBRLViewerPlugin/viewer/src/i18n/fr/datatypes.json +9 -0
- iXBRLViewerPlugin/viewer/src/i18n/fr/labelroles.json +24 -0
- iXBRLViewerPlugin/viewer/src/i18n/fr/referenceparts.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/fr/scale.json +15 -0
- iXBRLViewerPlugin/viewer/src/i18n/fr/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/fr/translation.json +179 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/balancetypes.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/currencies.json +13 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/datatypes.json +9 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/labelroles.json +24 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/referenceparts.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/scale.json +15 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/nl/translation.json +179 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/balancetypes.json +4 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/currencies.json +13 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/datatypes.json +9 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/labelroles.json +24 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/referenceparts.json +10 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/scale.json +15 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/tooltips.json +17 -0
- iXBRLViewerPlugin/viewer/src/i18n/uk/translation.json +179 -0
- iXBRLViewerPlugin/viewer/src/icons/calculator.svg +13 -0
- iXBRLViewerPlugin/viewer/src/icons/circle-cross.svg +11 -0
- iXBRLViewerPlugin/viewer/src/icons/circle-tick.svg +11 -0
- iXBRLViewerPlugin/viewer/src/icons/dark-mode.svg +4 -0
- iXBRLViewerPlugin/viewer/src/icons/dimension.svg +1 -5
- iXBRLViewerPlugin/viewer/src/icons/member.svg +2 -5
- iXBRLViewerPlugin/viewer/src/icons/multi-tag.svg +10 -0
- iXBRLViewerPlugin/viewer/src/img/arelle-dark.svg +179 -0
- iXBRLViewerPlugin/viewer/src/img/inline-viewer-dark.svg +59 -0
- iXBRLViewerPlugin/viewer/src/js/accordian.js +5 -4
- iXBRLViewerPlugin/viewer/src/js/aspect.js +29 -10
- iXBRLViewerPlugin/viewer/src/js/aspect.test.js +40 -31
- iXBRLViewerPlugin/viewer/src/js/balance.js +14 -0
- iXBRLViewerPlugin/viewer/src/js/calculation.js +213 -0
- iXBRLViewerPlugin/viewer/src/js/calculation.test.js +306 -0
- iXBRLViewerPlugin/viewer/src/js/calculationInspector.js +187 -0
- iXBRLViewerPlugin/viewer/src/js/chart.js +26 -24
- iXBRLViewerPlugin/viewer/src/js/chart.test.js +10 -9
- iXBRLViewerPlugin/viewer/src/js/concept.js +37 -4
- iXBRLViewerPlugin/viewer/src/js/concept.test.js +30 -6
- iXBRLViewerPlugin/viewer/src/js/datatype.js +20 -0
- iXBRLViewerPlugin/viewer/src/js/datatype.test.js +62 -0
- iXBRLViewerPlugin/viewer/src/js/dialog.js +6 -4
- iXBRLViewerPlugin/viewer/src/js/docOrderIndex.js +7 -7
- iXBRLViewerPlugin/viewer/src/js/fact.js +156 -59
- iXBRLViewerPlugin/viewer/src/js/fact.test.js +160 -29
- iXBRLViewerPlugin/viewer/src/js/factset.js +64 -15
- iXBRLViewerPlugin/viewer/src/js/factset.test.js +102 -31
- iXBRLViewerPlugin/viewer/src/js/footnote.js +8 -2
- iXBRLViewerPlugin/viewer/src/js/index.js +11 -3
- iXBRLViewerPlugin/viewer/src/js/inspector.js +747 -221
- iXBRLViewerPlugin/viewer/src/js/inspector.test.js +143 -25
- iXBRLViewerPlugin/viewer/src/js/interval.js +70 -0
- iXBRLViewerPlugin/viewer/src/js/interval.test.js +153 -0
- iXBRLViewerPlugin/viewer/src/js/ixbrlviewer.js +391 -262
- iXBRLViewerPlugin/viewer/src/js/ixbrlviewer.test.js +134 -20
- iXBRLViewerPlugin/viewer/src/js/ixnode.js +1 -1
- iXBRLViewerPlugin/viewer/src/js/menu.js +25 -7
- iXBRLViewerPlugin/viewer/src/js/number-matcher.js +7 -3
- iXBRLViewerPlugin/viewer/src/js/number-matcher.test.js +4 -0
- iXBRLViewerPlugin/viewer/src/js/outline.js +34 -13
- iXBRLViewerPlugin/viewer/src/js/outline.test.js +97 -91
- iXBRLViewerPlugin/viewer/src/js/period.js +0 -1
- iXBRLViewerPlugin/viewer/src/js/report.js +260 -351
- iXBRLViewerPlugin/viewer/src/js/report.test.js +95 -27
- iXBRLViewerPlugin/viewer/src/js/reportset.js +264 -0
- iXBRLViewerPlugin/viewer/src/js/reportset.test.js +357 -0
- iXBRLViewerPlugin/viewer/src/js/search.js +72 -38
- iXBRLViewerPlugin/viewer/src/js/search.test.js +184 -84
- iXBRLViewerPlugin/viewer/src/js/summary.js +34 -8
- iXBRLViewerPlugin/viewer/src/js/summary.test.js +69 -25
- iXBRLViewerPlugin/viewer/src/js/tableExport.js +9 -9
- iXBRLViewerPlugin/viewer/src/js/taxonomynamer.js +34 -0
- iXBRLViewerPlugin/viewer/src/js/taxonomynamer.test.js +32 -0
- iXBRLViewerPlugin/viewer/src/js/test-utils.js +46 -0
- iXBRLViewerPlugin/viewer/src/js/theme.js +50 -0
- iXBRLViewerPlugin/viewer/src/js/unit.js +90 -32
- iXBRLViewerPlugin/viewer/src/js/unit.test.js +62 -25
- iXBRLViewerPlugin/viewer/src/js/util.js +94 -0
- iXBRLViewerPlugin/viewer/src/js/util.test.js +33 -1
- iXBRLViewerPlugin/viewer/src/js/utr.js +27 -0
- iXBRLViewerPlugin/viewer/src/js/viewer.js +205 -181
- iXBRLViewerPlugin/viewer/src/js/viewerOptions.js +0 -2
- iXBRLViewerPlugin/viewer/src/less/accordian.less +10 -6
- iXBRLViewerPlugin/viewer/src/less/block-list.less +16 -5
- iXBRLViewerPlugin/viewer/src/less/calculation-inspector.less +83 -0
- iXBRLViewerPlugin/viewer/src/less/chart.less +8 -5
- iXBRLViewerPlugin/viewer/src/less/colours-dark-mode.less +40 -0
- iXBRLViewerPlugin/viewer/src/less/colours.less +32 -20
- iXBRLViewerPlugin/viewer/src/less/common.less +3 -3
- iXBRLViewerPlugin/viewer/src/less/components.less +6 -4
- iXBRLViewerPlugin/viewer/src/less/core.less +2 -0
- iXBRLViewerPlugin/viewer/src/less/dialog.less +21 -14
- iXBRLViewerPlugin/viewer/src/less/form-controls.less +33 -11
- iXBRLViewerPlugin/viewer/src/less/inspector.less +1045 -726
- iXBRLViewerPlugin/viewer/src/less/loader.less +2 -2
- iXBRLViewerPlugin/viewer/src/less/menu.less +33 -15
- iXBRLViewerPlugin/viewer/src/less/summary.less +16 -6
- iXBRLViewerPlugin/viewer/src/less/tabs.less +9 -9
- iXBRLViewerPlugin/viewer/src/less/text-block-viewer.less +2 -0
- iXBRLViewerPlugin/viewer/src/less/text-mixins.less +2 -1
- iXBRLViewerPlugin/viewer/src/less/validation-report.less +2 -3
- iXBRLViewerPlugin/viewer/src/less/viewer.less +105 -74
- iXBRLViewerPlugin/viewer/webpack.common.js +19 -9
- iXBRLViewerPlugin/xhtmlserialize.py +59 -45
- {ixbrl_viewer-1.4.1.dist-info → ixbrl_viewer-1.4.86.dist-info}/METADATA +181 -50
- ixbrl_viewer-1.4.86.dist-info/RECORD +217 -0
- {ixbrl_viewer-1.4.1.dist-info → ixbrl_viewer-1.4.86.dist-info}/WHEEL +1 -1
- ixbrl_viewer-1.4.1.dist-info/LICENSE → ixbrl_viewer-1.4.86.dist-info/licenses/LICENSE.md +8 -14
- {ixbrl_viewer-1.4.1.dist-info → ixbrl_viewer-1.4.86.dist-info}/top_level.txt +0 -1
- iXBRLViewerPlugin/viewer/src/js/calculations.js +0 -111
- iXBRLViewerPlugin/viewer/src/js/interact.min.js +0 -6
- ixbrl_viewer-1.4.1.dist-info/RECORD +0 -155
- 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 -80
- tests/puppeteer/framework/page_objects/search_panel.js +0 -76
- 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 -78
- 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 -39
- tests/unit_tests/iXBRLViewerPlugin/test_iXBRLViewer.py +0 -641
- tests/unit_tests/iXBRLViewerPlugin/test_xhtmlserialize.py +0 -310
- {ixbrl_viewer-1.4.1.dist-info → ixbrl_viewer-1.4.86.dist-info}/entry_points.txt +0 -0
- {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 {
|
|
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
|
-
|
|
8
|
+
const testReportData = {
|
|
9
9
|
"prefixes": {
|
|
10
10
|
"eg": "http://www.example.com",
|
|
11
|
-
"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
|
-
|
|
46
|
+
const data = JSON.parse(JSON.stringify(testReportData));
|
|
48
47
|
data.facts = facts;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
return
|
|
48
|
+
const reportSet = new ReportSet(data);
|
|
49
|
+
reportSet.setIXNodeMap(ixData);
|
|
50
|
+
return reportSet;
|
|
52
51
|
}
|
|
53
52
|
|
|
54
53
|
function fromFact(value) {
|
|
55
|
-
|
|
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
|
|
61
|
+
return testReport({"f1": factData}, {"f1": {} }).getItemById("0-f1");
|
|
63
62
|
}
|
|
64
63
|
|
|
65
64
|
function toFact(value) {
|
|
66
|
-
|
|
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
|
-
|
|
72
|
+
|
|
73
|
+
return testReport({"f1": factData}, {"f1": {} }).getItemById("0-f1");
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
describe("Describe changes", () => {
|
|
77
|
-
|
|
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
|
-
|
|
135
|
-
const
|
|
134
|
+
const insp = new TestInspector();
|
|
135
|
+
const reportSet = testReport({
|
|
136
136
|
...monetaryFactData,
|
|
137
137
|
...nonMonetaryFactData,
|
|
138
138
|
}, ixData);
|
|
139
|
-
insp.initialize(
|
|
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
|
-
|
|
162
|
-
const
|
|
161
|
+
const insp = new TestInspector();
|
|
162
|
+
const reportSet = testReport({
|
|
163
163
|
...monetaryFactData,
|
|
164
164
|
}, ixData);
|
|
165
|
-
insp.initialize(
|
|
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
|
-
|
|
188
|
-
const
|
|
187
|
+
const insp = new TestInspector();
|
|
188
|
+
const reportSet = testReport({
|
|
189
189
|
...nonMonetaryFactData,
|
|
190
190
|
}, ixData);
|
|
191
|
-
insp.initialize(
|
|
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
|
+
|