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,80 +0,0 @@
1
- import { Button, Text } from '../core_elements.js';
2
- import { getTextContent } from '../utils.js';
3
-
4
- export class FactDetailsPanel {
5
- #viewerPage;
6
-
7
- constructor(viewerPage) {
8
- this.#viewerPage = viewerPage;
9
-
10
- this.accuracy = new Text(
11
- this.#viewerPage,
12
- '//*[@data-i18n="factDetails.accuracy"]//ancestor::tr//td',
13
- 'Fact Accuracy');
14
- this.concept = new Text(
15
- this.#viewerPage,
16
- '//*[contains(@class, "fact-details")]//*[contains(@class,"std-label")]',
17
- 'Fact Concept');
18
- this.date = new Text(
19
- this.#viewerPage,
20
- '//*[@data-i18n="factDetails.date"]//ancestor::tr//td',
21
- 'Fact Date');
22
- this.duplicateNext = new Button(
23
- this.#viewerPage,
24
- '//*[contains(@class,"duplicates")]//*[contains(@class,"next")]',
25
- 'Duplicate next');
26
- this.duplicateText = new Text(
27
- this.#viewerPage,
28
- '//*[contains(@class,"duplicates")]//*[contains(@class,"text")]',
29
- 'Duplicate Count');
30
- this.factValue = new Text(
31
- this.#viewerPage,
32
- '//*[@data-i18n="factDetails.factValue"]//ancestor::tr//*[contains(@class, "value")]',
33
- 'Fact Value');
34
- this.entity = new Text(
35
- this.#viewerPage,
36
- '//*[@data-i18n="factDetails.entity"]//ancestor::tr//td',
37
- 'Fact Entity');
38
- this.nextFact = new Button(this.#viewerPage,
39
- '//*[contains(@class, "ixbrl-next-tag")]', 'Next Fact');
40
- this.previousFact = new Button(this.#viewerPage,
41
- '//*[contains(@class, "ixbrl-prev-tag")]', 'Previous Fact');
42
- }
43
-
44
- // Asserts the calculation contributors listed in the fact details panel
45
- // under the [sectionTitle]. [expectedCalculation] is a map of concept to
46
- // weight ex: {'cash':'+ '}
47
- async assertCalculation(sectionTitle, expectedCalculations) {
48
- this.#viewerPage.log(`Asserting Calculations for section ${sectionTitle}`);
49
-
50
- // Pull the title elements and assert the section exists
51
- const titleElems = await this.#viewerPage.page.$x('//*[contains(@class,"calculations")]//*[contains(@class,"title")]');
52
-
53
- const titles = await Promise.all(titleElems.map(async (e) => await getTextContent(e)));
54
- expect(titles).toContain(sectionTitle)
55
-
56
- // Pull the concepts from the expected section
57
- const conceptElems = await this.#viewerPage.page.$x(`
58
- //*[contains(@class,"calculations")]//*[text()="${sectionTitle}"]
59
- //ancestor::*[contains(@class,"card")]//*[contains(@class,"item")]
60
- `);
61
-
62
- let calc = {};
63
- for(const elem of conceptElems){
64
- const nameElem = await elem.waitForSelector('xpath/' + '*[contains(@class,"concept-name")]');
65
- const name = await getTextContent(nameElem)
66
- const weightElem = await elem.waitForSelector('xpath/' + '*[contains(@class,"weight")]');
67
- const weight = await getTextContent(weightElem);
68
- calc[name] = weight;
69
- }
70
- expect(calc).toEqual(expectedCalculations);
71
- }
72
-
73
- async assertFootnotes(expectedFootnotes) {
74
- this.#viewerPage.log('Asserting footnotes');
75
- const conceptElems = await this.#viewerPage.page.$x(
76
- '//*[contains(@class,"footnotes")]//*[contains(@class,"block-list-item")]');
77
- const footnotes = await Promise.all(conceptElems.map(async (e) => await getTextContent(e)));
78
- expect(footnotes).toEqual(expectedFootnotes);
79
- }
80
- }
@@ -1,76 +0,0 @@
1
- import { Button, TextInput } from '../core_elements.js';
2
- import { getTextContent } from '../utils.js';
3
-
4
- export class Search {
5
- #viewerPage;
6
-
7
- constructor(viewerPage) {
8
- this.#viewerPage = viewerPage;
9
- this.filterToggle = new Button(this.#viewerPage,
10
- '//*[contains(@class,"filter-toggle")]', 'Filter Toggle');
11
- this.reset = new Button(this.#viewerPage,
12
- '//*[contains(@data-i18n,"inspector.reset")]', 'Reset');
13
- this.searchButton = new Button(this.#viewerPage,
14
- '//*[contains(@class,"search-button")]', 'Search');
15
- this.searchInput = new TextInput(this.#viewerPage,
16
- '//*[@id="ixbrl-search"]', 'Search Input');
17
- }
18
-
19
- async getSearchResults() {
20
- const elements = await this.#viewerPage.page.$x(
21
- '//*[contains(@class,"search-results")]' +
22
- '//*[contains(@class,"fact-list-item")]' +
23
- '//*[contains(@class,"title")]');
24
- return Promise.all(elements.map(async (e) => {
25
- return getTextContent(e);
26
- }));
27
- }
28
-
29
- async assertSearchResultsContain(concepts) {
30
- this.#viewerPage.log(`Asserting search results contain ${concepts}`);
31
- const results = await this.getSearchResults();
32
- for (const concept of concepts) {
33
- expect(results).toContain(concept);
34
- }
35
- }
36
-
37
- async assertSearchResultsDoNotContain(concepts) {
38
- this.#viewerPage.log(
39
- `Asserting search results do not contain ${concepts}`);
40
- const results = await this.getSearchResults();
41
- for (const concept of concepts) {
42
- expect(results).not.toContain(concept);
43
- }
44
- }
45
-
46
- async filterConceptType(option) {
47
- const dropdown = await this.#viewerPage.page
48
- .waitForSelector('#search-filter-concept-type');
49
- await dropdown.select(option);
50
- }
51
-
52
- async filterPeriod(option) {
53
- const dropdown = await this.#viewerPage.page
54
- .waitForSelector('#search-filter-period select');
55
- await dropdown.select(option);
56
- }
57
-
58
- getSearchResultCard(conceptName) {
59
- return new SearchResultCard(this.#viewerPage, conceptName);
60
- }
61
- }
62
-
63
- export class SearchResultCard {
64
- #viewerPage;
65
-
66
- constructor(viewerPage, conceptName) {
67
- this.conceptName = conceptName;
68
- this.#viewerPage = viewerPage;
69
- this.locator = `//*[contains(@class,"title")
70
- and contains(text(),"${this.conceptName}")]
71
- //ancestor::*[contains(@class,"fact-list-item")]`;
72
- this.selectButton = new Button(this.#viewerPage,
73
- `${this.locator}//*[contains(@class,"select-icon")]`,
74
- 'Select Button');
75
- }
76
- }
@@ -1,18 +0,0 @@
1
- import { Checkbox } from '../core_elements.js';
2
-
3
- export class Toolbar {
4
- #viewerPage;
5
-
6
- constructor(viewerPage) {
7
- this.#viewerPage = viewerPage;
8
- this.xbrlElementHighlight = new Checkbox(this.#viewerPage,
9
- '//*[contains(@class,"top-bar-controls")]//*[contains(text(),"XBRL Elements")]//input',
10
- 'XBRL Element Highlight');
11
- this.unTaggedDateHighlight = new Checkbox(this.#viewerPage,
12
- '//*[contains(@class,"top-bar-controls")]//*[contains(text(),"Untagged Dates")]//input',
13
- 'Untagged Dates');
14
- this.unTaggedNumberHighlight = new Checkbox(this.#viewerPage,
15
- '//*[contains(@class,"top-bar-controls")]//*[contains(text(),"Untagged Numbers")]//input',
16
- 'Untagged Numbers');
17
- }
18
- }
@@ -1,3 +0,0 @@
1
- export async function getTextContent(elementHandle) {
2
- return (await elementHandle.getProperty('textContent')).jsonValue();
3
- }
@@ -1,103 +0,0 @@
1
- import fs from 'fs';
2
- import puppeteer from 'puppeteer';
3
- import { DocFrame } from './page_objects/doc_frame.js';
4
- import { FactDetailsPanel } from './page_objects/fact_details_panel.js';
5
- import { PuppeteerScreenRecorder } from 'puppeteer-screen-recorder';
6
- import { Search } from './page_objects/search_panel.js';
7
- import { Toolbar } from './page_objects/toolbar.js';
8
-
9
- export class ViewerPage {
10
- browser;
11
- page;
12
- docFrame;
13
- factDetailsPanel;
14
- search;
15
- toolbar;
16
-
17
- #artifactDirectory = './tests/puppeteer/artifacts';
18
- #cleanedTestName = expect.getState()
19
- .currentTestName
20
- .replaceAll(/[^a-zA-Z0-9-]/g, '_');
21
- #isCi = process.env.CI === 'true';
22
- #logMsgs = [];
23
- #recorder;
24
-
25
- async buildPage() {
26
- // Launch the browser
27
- this.browser = await puppeteer.launch({
28
- headless: this.#isCi ? 'new' : false,
29
- args: [`--window-size=1440,900`],
30
- defaultViewport: { width: 1440, height: 821 },
31
- });
32
- this.page = await this.browser.newPage();
33
- this.docFrame = new DocFrame(this);
34
- this.factDetailsPanel = new FactDetailsPanel(this);
35
- this.search = new Search(this);
36
- this.toolbar = new Toolbar(this);
37
- this.#recorder = new PuppeteerScreenRecorder(this.page);
38
-
39
- // Set up the video recording
40
- const videoDir = `${this.#artifactDirectory}/video`;
41
- const videoPath = `${videoDir}/${this.#cleanedTestName}.mp4`;
42
- await this.#createDirectory(videoDir);
43
- await this.#recorder.start(videoPath);
44
-
45
- this.streamLogsToFile(
46
- `${this.#artifactDirectory}/${this.#cleanedTestName}_chrome_debug.log`);
47
- }
48
-
49
- log(message) {
50
- this.#logMsgs.push(message);
51
- }
52
-
53
- async navigateToViewer(filingZipName, args = '') {
54
-
55
- const filingName = filingZipName.replace('.zip', '');
56
- const url = `http://localhost:8080/tests/puppeteer/artifacts/generated_output/${filingName}.htm${args}`;
57
- this.log(`Navigating to ${url}`);
58
- await this.page.goto(url, { waitUntil: 'networkidle0' });
59
- await this.page.waitForSelector(
60
- 'xpath/' + '//*[contains(@class, "loading")]',
61
- { visible: false, hidden: true });
62
- }
63
-
64
- async tearDown() {
65
- console.log(this.#logMsgs.join('\n'));
66
- await this.#recorder.stop();
67
- await this.browser.close();
68
- }
69
-
70
- async #createDirectory(path) {
71
- if (!fs.existsSync(path)) {
72
- fs.mkdirSync(path, { recursive: true });
73
- }
74
- }
75
-
76
- streamLogsToFile(filename) {
77
- const append = (content) => fs.appendFile(filename, `${content}\n`,
78
- function(err) {
79
- if (err) throw err;
80
- });
81
-
82
- // Delete the file if it already exists
83
- fs.rmSync(filename, { force: true });
84
-
85
- // Pipe the log messages to the file
86
- this.page.on('console', msg => append(
87
- `${msg.type().substr(0, 3).toUpperCase()} ${msg.text()}`))
88
- .on('pageerror', function(err) {
89
- let value = err.toString();
90
- append(value);
91
- })
92
- .on('response', response => append(
93
- `${response.status()} ${response.url()}`))
94
- .on('requestfailed', request => append(
95
- `${request.failure().errorText} ${request.url()}`));
96
- }
97
-
98
- async waitMilliseconds(milliseconds) {
99
- return new Promise(function(resolve) {
100
- setTimeout(resolve, milliseconds);
101
- });
102
- }
103
- }
Binary file
@@ -1,78 +0,0 @@
1
- import { ViewerPage } from '../framework/viewer_page.js';
2
- import { getTextContent } from '../framework/utils.js';
3
-
4
- jest.setTimeout(60000);
5
-
6
- describe('ixbrl-viewer',() => {
7
- let viewerPage;
8
-
9
- beforeEach(async () => {
10
- viewerPage = new ViewerPage();
11
- await viewerPage.buildPage();
12
- })
13
-
14
- afterEach(async () => {
15
- await viewerPage.tearDown();
16
- });
17
-
18
- test('Fact Properties', async () => {
19
- const detailsPanel = viewerPage.factDetailsPanel;
20
- const documentType = '10-K';
21
-
22
- await viewerPage.navigateToViewer('filing_documents_smoke_test.zip');
23
-
24
- await expect(await viewerPage.page.title()).toContain('Inline Viewer');
25
-
26
- // Click on the Document Type fact
27
- await viewerPage.docFrame.selectFact('dei:DocumentType');
28
-
29
- // Assert the fact details
30
- await detailsPanel.concept.assertText('(dei) Document Type');
31
- await detailsPanel.date.assertText('1 Jan 2020 to 30 Sep 2020');
32
- await detailsPanel.factValue.assertText(documentType);
33
- await detailsPanel.accuracy.assertText('n/a');
34
- await detailsPanel.entity.assertText('[CIK] 0000990763');
35
-
36
- // Navigate to the previous fact (last fact in document)
37
- await detailsPanel.previousFact.select();
38
-
39
- // Assert the previous fact was selected
40
- await detailsPanel.concept.assertText('(us-gaap) Revenues');
41
- await detailsPanel.date.assertText('1 Jan 2011 to 31 Mar 2011');
42
- await detailsPanel.factValue.assertText('US $ 5,117,000,000');
43
- await detailsPanel.accuracy.assertText('millions');
44
- await detailsPanel.entity.assertText('[CIK] 0000990763');
45
-
46
- // Assert Calculations
47
- await detailsPanel.assertCalculation('1001002 - Statement - Statement', {
48
- 'Gain (Loss) on Investments': '+ ',
49
- 'Other Income': '+ ',
50
- 'Net Investment Income': '+ ',
51
- 'Premiums Earned, Net': '+ ',
52
- 'Revenues': ''
53
- });
54
-
55
- // Assert footnotes applied
56
- await detailsPanel.assertFootnotes(['This is a footnote']);
57
-
58
- // Navigate to next fact and assert it takes us back to the first one
59
- await detailsPanel.nextFact.select();
60
- await detailsPanel.concept.assertText('(dei) Document Type');
61
-
62
- // Duplicate Facts - Verify we're looking at fact 1 of 2
63
- await detailsPanel.duplicateText.assertText('1 of 2');
64
- const oldFact = await viewerPage.docFrame.getSelectedFact();
65
- const oldFactBox = await oldFact.boundingBox();
66
- const oldFactText = await getTextContent(oldFact);
67
- expect(oldFactText).toEqual(documentType);
68
-
69
- // Duplicate Facts - Test navigation to fact 2
70
- await detailsPanel.duplicateNext.select();
71
- await detailsPanel.duplicateText.assertText('2 of 2');
72
- const newFact = await viewerPage.docFrame.getSelectedFact();
73
- const newFactBox = await newFact.boundingBox();
74
- const newFactText = await getTextContent(newFact);
75
- expect(newFactText).toEqual(documentType);
76
- expect(newFactBox).not.toEqual(oldFactBox);
77
- });
78
- });
@@ -1,186 +0,0 @@
1
- import { ViewerPage } from '../framework/viewer_page.js';
2
- import { Highlight } from '../framework/page_objects/doc_frame.js';
3
-
4
- jest.setTimeout(60000);
5
-
6
- describe('ixbrl-viewer:', () => {
7
- let viewerPage;
8
-
9
- const gaapFactValues = [
10
- 'Feb 2023',
11
- 'March 2023',
12
- 'Apr 15, 2023',
13
- 'zero',
14
- 'one hundred',
15
- 'none',
16
- 'two trillion three hundred thirty-four billion five hundred sixty-seven million eight hundred ninety thousand',
17
- '5', // 5 Months
18
- '26', // 26 Months
19
- '123,000', // $123,000
20
- '12', // ¢12
21
- '22,213', // US$22,213
22
- '123,456', // €123,456
23
- '332,234', // £332,234
24
- '312,321', // ¥312,321
25
- '77,986', // C$77,986
26
- '12,134', // A$12,134
27
- '123,421', // NT$123,421
28
- '565,928', // S$565,928
29
- '13,123', // ₩13,123
30
- '33,445', // ₱33,445
31
- '88,123', // ₨88,123
32
- '99,192', // kr99,192
33
- '123,234', // Fr.123,234
34
- '84,234', // RM84,234
35
- '11,234', // R$11,234
36
- '93,383', // R93,383
37
- ];
38
-
39
- const untaggedDates = [
40
- 'Jan 22',
41
- 'Feb 2022',
42
- 'March 2022',
43
- 'Apr 15, 2022',
44
- 'Aug 1st',
45
- '2022'
46
- ];
47
-
48
- const untaggedNumbers = [
49
- 'zero',
50
- 'two hundred',
51
- 'no',
52
- 'none',
53
- 'three trillion four hundred thirty-four billion five hundred sixty-seven million eight hundred ninety thousand',
54
- '4 months',
55
- '25 months',
56
- '$123,001',
57
- '¢13',
58
- 'US$22,214',
59
- '€123,457',
60
- '£332,235',
61
- '¥312,322',
62
- 'C$77,987',
63
- 'A$12,135',
64
- 'NT$123,422',
65
- 'S$565,929',
66
- '₩13,124',
67
- '₱33,446',
68
- '₨88,124',
69
- 'kr99,193',
70
- 'Fr.123,235',
71
- 'RM84,235',
72
- 'R$11,235',
73
- 'R93,384'
74
- ];
75
-
76
- const deiFactValues = ['Jan 23', 'Aug 1st 2023'];
77
-
78
- const activeDeiFactHighlights = deiFactValues
79
- .map((entry) => Highlight.factNamespace2(entry));
80
-
81
- const activeGaapFactHighlights = gaapFactValues
82
- .map((entry) => Highlight.fact(entry));
83
-
84
- const activeReviewFactHighlights = [...deiFactValues, ...gaapFactValues]
85
- .map((entry) => Highlight.fact(entry));
86
-
87
- const activeUntaggedDateHighlights = untaggedDates
88
- .map((entry) => Highlight.untaggedDate(entry))
89
-
90
- const activeUntaggedNumberHighlights = untaggedNumbers
91
- .map((entry) => Highlight.untaggedNumber(entry))
92
-
93
- const inactiveGaapFactHighlights = gaapFactValues
94
- .map((entry) => Highlight.fact(entry, false));
95
-
96
- const inactiveDeiFactHighlights = deiFactValues
97
- .map((entry) => Highlight.factNamespace2(entry, false));
98
-
99
- const inactiveReviewFactHighlights = [...deiFactValues, ...gaapFactValues]
100
- .map((entry) => Highlight.fact(entry, false));
101
-
102
- const inactiveUntaggedDateHighlights = untaggedDates
103
- .map((entry) => Highlight.untaggedDate(entry, false));
104
-
105
- const inactiveUntaggedNumberHighlights = untaggedNumbers
106
- .map((entry) => Highlight.untaggedNumber(entry, false));
107
-
108
- beforeEach(async () => {
109
- viewerPage = new ViewerPage();
110
- await viewerPage.buildPage();
111
- });
112
-
113
- afterEach(async () => {
114
- await viewerPage.tearDown();
115
- });
116
-
117
- test('Highlight Test', async () => {
118
- await viewerPage.navigateToViewer('highlights.zip');
119
-
120
- // Assert on load values are not highlighted
121
- await viewerPage.docFrame.assertHighlights([
122
- ...inactiveGaapFactHighlights, ...inactiveDeiFactHighlights]);
123
-
124
- // Enable fact highlights and assert values
125
- await viewerPage.toolbar.xbrlElementHighlight.toggleOn();
126
- await viewerPage.docFrame.assertHighlights([
127
- ...activeGaapFactHighlights, ...activeDeiFactHighlights]);
128
-
129
- // Disable highlights
130
- await viewerPage.toolbar.xbrlElementHighlight.toggleOff();
131
-
132
- // Assert values are no longer highlighted
133
- await viewerPage.docFrame.assertHighlights([
134
- ...inactiveGaapFactHighlights, ...inactiveDeiFactHighlights]);
135
- });
136
-
137
- test('Highlight Test - Review', async () => {
138
- await viewerPage.navigateToViewer('highlights.zip', '?review=true');
139
-
140
- // Assert on load values are not highlighted
141
- await viewerPage.docFrame.assertHighlights([
142
- ...inactiveReviewFactHighlights,
143
- ...inactiveUntaggedDateHighlights,
144
- ...inactiveUntaggedNumberHighlights
145
- ]);
146
-
147
- // Enable untagged date highlighting and assert values
148
- await viewerPage.toolbar.unTaggedDateHighlight.toggleOn();
149
- await viewerPage.docFrame.assertHighlights([
150
- ...activeUntaggedDateHighlights,
151
- ...inactiveUntaggedNumberHighlights,
152
- ...inactiveReviewFactHighlights
153
- ]);
154
-
155
- // Enable untagged number highlighting and assert values
156
- await viewerPage.toolbar.unTaggedNumberHighlight.toggleOn();
157
- await viewerPage.docFrame.assertHighlights([
158
- ...activeUntaggedNumberHighlights,
159
- ...activeUntaggedDateHighlights,
160
- ...inactiveGaapFactHighlights,
161
- ...inactiveDeiFactHighlights
162
- ]);
163
-
164
- // Enable fact highlights and assert values
165
- await viewerPage.toolbar.xbrlElementHighlight.toggleOn();
166
- await viewerPage.docFrame.assertHighlights([
167
- ...activeReviewFactHighlights,
168
- ...activeUntaggedNumberHighlights,
169
- ...activeUntaggedDateHighlights,
170
- ]);
171
-
172
- // Disable highlights
173
- await viewerPage.toolbar.unTaggedDateHighlight.toggleOff();
174
- await viewerPage.waitMilliseconds(100);
175
- await viewerPage.toolbar.unTaggedNumberHighlight.toggleOff();
176
- await viewerPage.waitMilliseconds(100);
177
- await viewerPage.toolbar.xbrlElementHighlight.toggleOff();
178
-
179
- // Assert values are no longer highlighted
180
- await viewerPage.docFrame.assertHighlights([
181
- ...inactiveReviewFactHighlights,
182
- ...inactiveUntaggedDateHighlights,
183
- ...inactiveUntaggedNumberHighlights
184
- ]);
185
- });
186
- });
@@ -1,86 +0,0 @@
1
- import { ViewerPage } from '../framework/viewer_page.js';
2
- import { Highlight } from '../framework/page_objects/doc_frame.js';
3
-
4
- jest.setTimeout(60000);
5
-
6
- describe('ixbrl-viewer:', () => {
7
- let viewerPage;
8
-
9
- beforeEach(async () => {
10
- viewerPage = new ViewerPage();
11
- await viewerPage.buildPage();
12
- });
13
-
14
- afterEach(async () => {
15
- await viewerPage.tearDown();
16
- });
17
-
18
- test('Search Test', async () => {
19
- const concept1 = 'Entity Address, City or Town';
20
- const concept2 = 'Entity Address, State or Province';
21
- const concept3 = 'Contact Personnel Name';
22
- const concept4 = 'Entity Public Float';
23
-
24
- const docFrame = viewerPage.docFrame;
25
- const search = viewerPage.search;
26
-
27
- await viewerPage.navigateToViewer('filing_documents_smoke_test.zip');
28
- await viewerPage.waitMilliseconds('3000'); // Give search time to index
29
-
30
- // // Open search and assert all concepts are shown
31
- await search.searchButton.select();
32
- await search.assertSearchResultsContain(
33
- [concept1, concept2, concept3, concept4]);
34
-
35
- // Search for Entity Address and assert results update
36
- await search.searchInput.enterText('Entity Address', true);
37
- await search.assertSearchResultsDoNotContain([concept3]);
38
- await search.assertSearchResultsContain([concept1, concept2, concept4]);
39
-
40
- // Navigate to the fact details for concept1
41
- await search.getSearchResultCard(concept1).selectButton.select();
42
- await viewerPage.factDetailsPanel.concept
43
- .assertText('(dei) Entity Address, City or Town');
44
-
45
- // Assert the fact was highlighted in the document
46
- await docFrame.assertHighlights([Highlight.selectedFact('Ames')]);
47
-
48
- // Go back to search and assert it still contains our results
49
- await search.searchButton.select();
50
- await search.assertSearchResultsDoNotContain([concept3]);
51
- await search.assertSearchResultsContain([concept1, concept2, concept4]);
52
-
53
- // Select concept2 fact and assert selection changes
54
- await search.getSearchResultCard(concept2).selectButton.select();
55
- await docFrame.assertHighlights(
56
- [Highlight.selectedFact('Ames', false)]);
57
- await docFrame.assertHighlights([Highlight.selectedFact('IA')]);
58
- await viewerPage.factDetailsPanel.concept.assertText(
59
- '(dei) Entity Address, State or Province');
60
-
61
- // Return to search and test hover highlight
62
- await search.searchButton.select();
63
- await search.getSearchResultCard(concept1).selectButton.hover();
64
- await docFrame.assertHighlights([Highlight.searchHover('Ames')]);
65
-
66
- // Mouse off and assert hover is removed
67
- await search.searchButton.hover();
68
- await docFrame
69
- .assertHighlights([Highlight.searchHover('Ames', false)]);
70
-
71
- // Filter by concept type and assert values have been filtered
72
- await search.filterToggle.select();
73
- await search.filterConceptType('numeric');
74
- await search.assertSearchResultsContain([concept4]);
75
- await search.assertSearchResultsDoNotContain([concept1, concept2]);
76
-
77
- // Reset concept type filter
78
- await search.reset.select();
79
- await search.assertSearchResultsContain([concept4, concept1, concept2]);
80
-
81
- // Filter by period
82
- await search.filterPeriod('2020-10-01');
83
- await search.assertSearchResultsContain([concept4]);
84
- await search.assertSearchResultsDoNotContain([concept1, concept2]);
85
- });
86
- });
@@ -1,15 +0,0 @@
1
- #!/bin/bash
2
-
3
- set -e
4
-
5
- testFilingDir=tests/puppeteer/test_filings
6
- genDir=tests/puppeteer/artifacts/generated_output
7
- mkdir -p $genDir
8
-
9
- for file in "$testFilingDir"/*.zip; do
10
- echo "Generating ixbrl-viewer for: $file"
11
- outputFilename=$(basename -- "$file")
12
- viewerName=${outputFilename%.zip}.htm
13
- arelleCmdLine --plugins ixbrl-viewer -f $file --save-viewer $genDir/$viewerName --viewer-url ../../../../iXBRLViewerPlugin/viewer/dist/ixbrlviewer.js
14
- done
15
- echo "iXBRL-Viewer Generation Complete"
File without changes
File without changes