@afixt/test-utils 1.1.2 → 1.1.4

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 (132) hide show
  1. package/.claude/settings.local.json +6 -2
  2. package/.github/workflows/test.yml +26 -0
  3. package/BROWSER_TESTING.md +109 -0
  4. package/CLAUDE.md +22 -0
  5. package/package.json +6 -8
  6. package/playwright.config.js +27 -0
  7. package/src/domUtils.js +1 -1
  8. package/src/getAccessibleName.js +8 -4
  9. package/src/getCSSGeneratedContent.js +9 -5
  10. package/src/getFocusableElements.js +13 -4
  11. package/src/getImageText.js +4 -1
  12. package/src/testContrast.js +5 -1
  13. package/test/__screenshots__/getImageText.test.js/getImageText-should-be-an-async-function-1.png +0 -0
  14. package/test/__screenshots__/getImageText.test.js/getImageText-should-be-defined-and-exported-from-the-module-1.png +0 -0
  15. package/test/__screenshots__/getImageText.test.js/getImageText-should-handle-empty-string-input-gracefully-1.png +0 -0
  16. package/test/__screenshots__/getImageText.test.js/getImageText-should-handle-invalid-image-paths-gracefully-1.png +0 -0
  17. package/test/__screenshots__/getImageText.test.js/getImageText-should-handle-null-or-undefined-input-gracefully-1.png +0 -0
  18. package/test/__screenshots__/getImageText.test.js/getImageText-should-log-errors-in-non-test-environments-1.png +0 -0
  19. package/test/__screenshots__/listEventListeners.test.js/listEventListeners-addEventListener-override-should-call-original-addEventListener-1.png +0 -0
  20. package/test/__screenshots__/listEventListeners.test.js/listEventListeners-addEventListener-override-should-track-added-event-listeners-1.png +0 -0
  21. package/test/__screenshots__/listEventListeners.test.js/listEventListeners-addEventListener-override-should-track-listeners-for-different-event-types-1.png +0 -0
  22. package/test/__screenshots__/listEventListeners.test.js/listEventListeners-addEventListener-override-should-track-multiple-listeners-for-the-same-event-1.png +0 -0
  23. package/test/__screenshots__/listEventListeners.test.js/listEventListeners-addEventListener-override-should-track-options-parameter-1.png +0 -0
  24. package/test/__screenshots__/listEventListeners.test.js/listEventListeners-getEventListeners-should-return-all-event-listeners-for-an-element-1.png +0 -0
  25. package/test/__screenshots__/listEventListeners.test.js/listEventListeners-getEventListeners-should-return-empty-object-for-elements-without-listeners-1.png +0 -0
  26. package/test/__screenshots__/listEventListeners.test.js/listEventListeners-getXPath-should-generate-XPath-for-elements-without-id-1.png +0 -0
  27. package/test/__screenshots__/listEventListeners.test.js/listEventListeners-getXPath-should-handle-multiple-siblings-correctly-1.png +0 -0
  28. package/test/__screenshots__/listEventListeners.test.js/listEventListeners-getXPath-should-return-XPath-for-element-with-id-1.png +0 -0
  29. package/test/__screenshots__/listEventListeners.test.js/listEventListeners-listEventListeners-should-list-event-listeners-on-child-elements-1.png +0 -0
  30. package/test/__screenshots__/listEventListeners.test.js/listEventListeners-listEventListeners-should-list-event-listeners-on-root-element-1.png +0 -0
  31. package/test/__screenshots__/listEventListeners.test.js/listEventListeners-listEventListeners-should-list-listeners-from-multiple-elements-1.png +0 -0
  32. package/test/__screenshots__/listEventListeners.test.js/listEventListeners-listEventListeners-should-list-multiple-event-types-on-same-element-1.png +0 -0
  33. package/test/__screenshots__/listEventListeners.test.js/listEventListeners-listEventListeners-should-return-empty-array-when-no-event-listeners-exist-1.png +0 -0
  34. package/test/__screenshots__/listEventListeners.test.js/listEventListeners-listEventListeners-should-use-document-as-default-root-element-1.png +0 -0
  35. package/test/__screenshots__/listEventListeners.test.js/listEventListeners-listEventListeners-should-work-with-custom-root-element-1.png +0 -0
  36. package/test/__screenshots__/listEventListeners.test.js/listEventListeners-removeEventListener-override-should-call-original-removeEventListener-1.png +0 -0
  37. package/test/__screenshots__/listEventListeners.test.js/listEventListeners-removeEventListener-override-should-handle-removing-non-existent-listeners-gracefully-1.png +0 -0
  38. package/test/__screenshots__/listEventListeners.test.js/listEventListeners-removeEventListener-override-should-only-remove-the-specified-listener-1.png +0 -0
  39. package/test/__screenshots__/listEventListeners.test.js/listEventListeners-removeEventListener-override-should-remove-tracked-event-listeners-1.png +0 -0
  40. package/test/arrayUtils.test.js +22 -0
  41. package/test/domUtils.test.js +241 -0
  42. package/test/getAccessibleName.test.js +182 -0
  43. package/test/getAccessibleText.test.js +350 -79
  44. package/test/getCSSGeneratedContent.test.js +175 -1
  45. package/test/getFocusableElements.test.js +106 -35
  46. package/test/getImageText.test.js +95 -12
  47. package/test/getStyleObject.test.js +19 -1
  48. package/test/hasCSSGeneratedContent.test.js +7 -2
  49. package/test/hasParent.test.js +116 -0
  50. package/test/hasValidAriaRole.test.js +64 -2
  51. package/test/index.test.js +165 -0
  52. package/test/interactiveRoles.test.js +60 -0
  53. package/test/isAriaAttributesValid.test.js +36 -0
  54. package/test/isDataTable.test.js +492 -0
  55. package/test/isFocusable.test.js +94 -1
  56. package/test/isValidUrl.test.js +31 -19
  57. package/test/isVisible.test.js +121 -3
  58. package/test/playwright/css-pseudo-elements.spec.js +155 -0
  59. package/test/playwright/fixtures/css-pseudo-elements.html +77 -0
  60. package/test/setup.js +9 -1
  61. package/test/stringUtils.test.js +277 -1
  62. package/test/testContrast.test.js +614 -9
  63. package/test/testLang.test.js +152 -11
  64. package/test/testOrder.integration.test.js +369 -0
  65. package/test/testOrder.test.js +756 -21
  66. package/todo.md +11 -1
  67. package/vitest.config.js +8 -1
  68. package/coverage/base.css +0 -224
  69. package/coverage/block-navigation.js +0 -87
  70. package/coverage/coverage-final.json +0 -51
  71. package/coverage/favicon.png +0 -0
  72. package/coverage/index.html +0 -161
  73. package/coverage/prettify.css +0 -1
  74. package/coverage/prettify.js +0 -2
  75. package/coverage/sort-arrow-sprite.png +0 -0
  76. package/coverage/sorter.js +0 -196
  77. package/coverage/test-utils/docs/scripts/core.js.html +0 -2263
  78. package/coverage/test-utils/docs/scripts/core.min.js.html +0 -151
  79. package/coverage/test-utils/docs/scripts/index.html +0 -176
  80. package/coverage/test-utils/docs/scripts/resize.js.html +0 -355
  81. package/coverage/test-utils/docs/scripts/search.js.html +0 -880
  82. package/coverage/test-utils/docs/scripts/search.min.js.html +0 -100
  83. package/coverage/test-utils/docs/scripts/third-party/fuse.js.html +0 -109
  84. package/coverage/test-utils/docs/scripts/third-party/hljs-line-num-original.js.html +0 -1192
  85. package/coverage/test-utils/docs/scripts/third-party/hljs-line-num.js.html +0 -85
  86. package/coverage/test-utils/docs/scripts/third-party/hljs-original.js.html +0 -15598
  87. package/coverage/test-utils/docs/scripts/third-party/hljs.js.html +0 -85
  88. package/coverage/test-utils/docs/scripts/third-party/index.html +0 -236
  89. package/coverage/test-utils/docs/scripts/third-party/popper.js.html +0 -100
  90. package/coverage/test-utils/docs/scripts/third-party/tippy.js.html +0 -88
  91. package/coverage/test-utils/docs/scripts/third-party/tocbot.js.html +0 -2098
  92. package/coverage/test-utils/docs/scripts/third-party/tocbot.min.js.html +0 -85
  93. package/coverage/test-utils/index.html +0 -131
  94. package/coverage/test-utils/src/arrayUtils.js.html +0 -283
  95. package/coverage/test-utils/src/domUtils.js.html +0 -622
  96. package/coverage/test-utils/src/getAccessibleName.js.html +0 -1444
  97. package/coverage/test-utils/src/getAccessibleText.js.html +0 -271
  98. package/coverage/test-utils/src/getAriaAttributesByElement.js.html +0 -142
  99. package/coverage/test-utils/src/getCSSGeneratedContent.js.html +0 -265
  100. package/coverage/test-utils/src/getComputedRole.js.html +0 -592
  101. package/coverage/test-utils/src/getFocusableElements.js.html +0 -163
  102. package/coverage/test-utils/src/getGeneratedContent.js.html +0 -130
  103. package/coverage/test-utils/src/getImageText.js.html +0 -160
  104. package/coverage/test-utils/src/getStyleObject.js.html +0 -220
  105. package/coverage/test-utils/src/hasAccessibleName.js.html +0 -166
  106. package/coverage/test-utils/src/hasAttribute.js.html +0 -130
  107. package/coverage/test-utils/src/hasCSSGeneratedContent.js.html +0 -145
  108. package/coverage/test-utils/src/hasHiddenParent.js.html +0 -172
  109. package/coverage/test-utils/src/hasParent.js.html +0 -247
  110. package/coverage/test-utils/src/hasValidAriaAttributes.js.html +0 -175
  111. package/coverage/test-utils/src/hasValidAriaRole.js.html +0 -172
  112. package/coverage/test-utils/src/index.html +0 -611
  113. package/coverage/test-utils/src/index.js.html +0 -274
  114. package/coverage/test-utils/src/interactiveRoles.js.html +0 -145
  115. package/coverage/test-utils/src/isAriaAttributesValid.js.html +0 -304
  116. package/coverage/test-utils/src/isComplexTable.js.html +0 -412
  117. package/coverage/test-utils/src/isDataTable.js.html +0 -799
  118. package/coverage/test-utils/src/isFocusable.js.html +0 -187
  119. package/coverage/test-utils/src/isHidden.js.html +0 -136
  120. package/coverage/test-utils/src/isOffScreen.js.html +0 -133
  121. package/coverage/test-utils/src/isValidUrl.js.html +0 -124
  122. package/coverage/test-utils/src/isVisible.js.html +0 -271
  123. package/coverage/test-utils/src/listEventListeners.js.html +0 -370
  124. package/coverage/test-utils/src/queryCache.js.html +0 -1156
  125. package/coverage/test-utils/src/stringUtils.js.html +0 -535
  126. package/coverage/test-utils/src/testContrast.js.html +0 -784
  127. package/coverage/test-utils/src/testLang.js.html +0 -1810
  128. package/coverage/test-utils/src/testOrder.js.html +0 -355
  129. package/coverage/test-utils/vitest.config.browser.js.html +0 -133
  130. package/coverage/test-utils/vitest.config.js.html +0 -157
  131. package/test/browser-setup.js +0 -68
  132. package/vitest.config.browser.js +0 -17
@@ -1,799 +0,0 @@
1
-
2
- <!doctype html>
3
- <html lang="en">
4
-
5
- <head>
6
- <title>Code coverage report for test-utils/src/isDataTable.js</title>
7
- <meta charset="utf-8" />
8
- <link rel="stylesheet" href="../../prettify.css" />
9
- <link rel="stylesheet" href="../../base.css" />
10
- <link rel="shortcut icon" type="image/x-icon" href="../../favicon.png" />
11
- <meta name="viewport" content="width=device-width, initial-scale=1" />
12
- <style type='text/css'>
13
- .coverage-summary .sorter {
14
- background-image: url(../../sort-arrow-sprite.png);
15
- }
16
- </style>
17
- </head>
18
-
19
- <body>
20
- <div class='wrapper'>
21
- <div class='pad1'>
22
- <h1><a href="../../index.html">All files</a> / <a href="index.html">test-utils/src</a> isDataTable.js</h1>
23
- <div class='clearfix'>
24
-
25
- <div class='fl pad1y space-right2'>
26
- <span class="strong">0% </span>
27
- <span class="quiet">Statements</span>
28
- <span class='fraction'>0/200</span>
29
- </div>
30
-
31
-
32
- <div class='fl pad1y space-right2'>
33
- <span class="strong">0% </span>
34
- <span class="quiet">Branches</span>
35
- <span class='fraction'>0/1</span>
36
- </div>
37
-
38
-
39
- <div class='fl pad1y space-right2'>
40
- <span class="strong">0% </span>
41
- <span class="quiet">Functions</span>
42
- <span class='fraction'>0/1</span>
43
- </div>
44
-
45
-
46
- <div class='fl pad1y space-right2'>
47
- <span class="strong">0% </span>
48
- <span class="quiet">Lines</span>
49
- <span class='fraction'>0/200</span>
50
- </div>
51
-
52
-
53
- </div>
54
- <p class="quiet">
55
- Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
56
- </p>
57
- <template id="filterTemplate">
58
- <div class="quiet">
59
- Filter:
60
- <input type="search" id="fileSearch">
61
- </div>
62
- </template>
63
- </div>
64
- <div class='status-line low'></div>
65
- <pre><table class="coverage">
66
- <tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
67
- <a name='L2'></a><a href='#L2'>2</a>
68
- <a name='L3'></a><a href='#L3'>3</a>
69
- <a name='L4'></a><a href='#L4'>4</a>
70
- <a name='L5'></a><a href='#L5'>5</a>
71
- <a name='L6'></a><a href='#L6'>6</a>
72
- <a name='L7'></a><a href='#L7'>7</a>
73
- <a name='L8'></a><a href='#L8'>8</a>
74
- <a name='L9'></a><a href='#L9'>9</a>
75
- <a name='L10'></a><a href='#L10'>10</a>
76
- <a name='L11'></a><a href='#L11'>11</a>
77
- <a name='L12'></a><a href='#L12'>12</a>
78
- <a name='L13'></a><a href='#L13'>13</a>
79
- <a name='L14'></a><a href='#L14'>14</a>
80
- <a name='L15'></a><a href='#L15'>15</a>
81
- <a name='L16'></a><a href='#L16'>16</a>
82
- <a name='L17'></a><a href='#L17'>17</a>
83
- <a name='L18'></a><a href='#L18'>18</a>
84
- <a name='L19'></a><a href='#L19'>19</a>
85
- <a name='L20'></a><a href='#L20'>20</a>
86
- <a name='L21'></a><a href='#L21'>21</a>
87
- <a name='L22'></a><a href='#L22'>22</a>
88
- <a name='L23'></a><a href='#L23'>23</a>
89
- <a name='L24'></a><a href='#L24'>24</a>
90
- <a name='L25'></a><a href='#L25'>25</a>
91
- <a name='L26'></a><a href='#L26'>26</a>
92
- <a name='L27'></a><a href='#L27'>27</a>
93
- <a name='L28'></a><a href='#L28'>28</a>
94
- <a name='L29'></a><a href='#L29'>29</a>
95
- <a name='L30'></a><a href='#L30'>30</a>
96
- <a name='L31'></a><a href='#L31'>31</a>
97
- <a name='L32'></a><a href='#L32'>32</a>
98
- <a name='L33'></a><a href='#L33'>33</a>
99
- <a name='L34'></a><a href='#L34'>34</a>
100
- <a name='L35'></a><a href='#L35'>35</a>
101
- <a name='L36'></a><a href='#L36'>36</a>
102
- <a name='L37'></a><a href='#L37'>37</a>
103
- <a name='L38'></a><a href='#L38'>38</a>
104
- <a name='L39'></a><a href='#L39'>39</a>
105
- <a name='L40'></a><a href='#L40'>40</a>
106
- <a name='L41'></a><a href='#L41'>41</a>
107
- <a name='L42'></a><a href='#L42'>42</a>
108
- <a name='L43'></a><a href='#L43'>43</a>
109
- <a name='L44'></a><a href='#L44'>44</a>
110
- <a name='L45'></a><a href='#L45'>45</a>
111
- <a name='L46'></a><a href='#L46'>46</a>
112
- <a name='L47'></a><a href='#L47'>47</a>
113
- <a name='L48'></a><a href='#L48'>48</a>
114
- <a name='L49'></a><a href='#L49'>49</a>
115
- <a name='L50'></a><a href='#L50'>50</a>
116
- <a name='L51'></a><a href='#L51'>51</a>
117
- <a name='L52'></a><a href='#L52'>52</a>
118
- <a name='L53'></a><a href='#L53'>53</a>
119
- <a name='L54'></a><a href='#L54'>54</a>
120
- <a name='L55'></a><a href='#L55'>55</a>
121
- <a name='L56'></a><a href='#L56'>56</a>
122
- <a name='L57'></a><a href='#L57'>57</a>
123
- <a name='L58'></a><a href='#L58'>58</a>
124
- <a name='L59'></a><a href='#L59'>59</a>
125
- <a name='L60'></a><a href='#L60'>60</a>
126
- <a name='L61'></a><a href='#L61'>61</a>
127
- <a name='L62'></a><a href='#L62'>62</a>
128
- <a name='L63'></a><a href='#L63'>63</a>
129
- <a name='L64'></a><a href='#L64'>64</a>
130
- <a name='L65'></a><a href='#L65'>65</a>
131
- <a name='L66'></a><a href='#L66'>66</a>
132
- <a name='L67'></a><a href='#L67'>67</a>
133
- <a name='L68'></a><a href='#L68'>68</a>
134
- <a name='L69'></a><a href='#L69'>69</a>
135
- <a name='L70'></a><a href='#L70'>70</a>
136
- <a name='L71'></a><a href='#L71'>71</a>
137
- <a name='L72'></a><a href='#L72'>72</a>
138
- <a name='L73'></a><a href='#L73'>73</a>
139
- <a name='L74'></a><a href='#L74'>74</a>
140
- <a name='L75'></a><a href='#L75'>75</a>
141
- <a name='L76'></a><a href='#L76'>76</a>
142
- <a name='L77'></a><a href='#L77'>77</a>
143
- <a name='L78'></a><a href='#L78'>78</a>
144
- <a name='L79'></a><a href='#L79'>79</a>
145
- <a name='L80'></a><a href='#L80'>80</a>
146
- <a name='L81'></a><a href='#L81'>81</a>
147
- <a name='L82'></a><a href='#L82'>82</a>
148
- <a name='L83'></a><a href='#L83'>83</a>
149
- <a name='L84'></a><a href='#L84'>84</a>
150
- <a name='L85'></a><a href='#L85'>85</a>
151
- <a name='L86'></a><a href='#L86'>86</a>
152
- <a name='L87'></a><a href='#L87'>87</a>
153
- <a name='L88'></a><a href='#L88'>88</a>
154
- <a name='L89'></a><a href='#L89'>89</a>
155
- <a name='L90'></a><a href='#L90'>90</a>
156
- <a name='L91'></a><a href='#L91'>91</a>
157
- <a name='L92'></a><a href='#L92'>92</a>
158
- <a name='L93'></a><a href='#L93'>93</a>
159
- <a name='L94'></a><a href='#L94'>94</a>
160
- <a name='L95'></a><a href='#L95'>95</a>
161
- <a name='L96'></a><a href='#L96'>96</a>
162
- <a name='L97'></a><a href='#L97'>97</a>
163
- <a name='L98'></a><a href='#L98'>98</a>
164
- <a name='L99'></a><a href='#L99'>99</a>
165
- <a name='L100'></a><a href='#L100'>100</a>
166
- <a name='L101'></a><a href='#L101'>101</a>
167
- <a name='L102'></a><a href='#L102'>102</a>
168
- <a name='L103'></a><a href='#L103'>103</a>
169
- <a name='L104'></a><a href='#L104'>104</a>
170
- <a name='L105'></a><a href='#L105'>105</a>
171
- <a name='L106'></a><a href='#L106'>106</a>
172
- <a name='L107'></a><a href='#L107'>107</a>
173
- <a name='L108'></a><a href='#L108'>108</a>
174
- <a name='L109'></a><a href='#L109'>109</a>
175
- <a name='L110'></a><a href='#L110'>110</a>
176
- <a name='L111'></a><a href='#L111'>111</a>
177
- <a name='L112'></a><a href='#L112'>112</a>
178
- <a name='L113'></a><a href='#L113'>113</a>
179
- <a name='L114'></a><a href='#L114'>114</a>
180
- <a name='L115'></a><a href='#L115'>115</a>
181
- <a name='L116'></a><a href='#L116'>116</a>
182
- <a name='L117'></a><a href='#L117'>117</a>
183
- <a name='L118'></a><a href='#L118'>118</a>
184
- <a name='L119'></a><a href='#L119'>119</a>
185
- <a name='L120'></a><a href='#L120'>120</a>
186
- <a name='L121'></a><a href='#L121'>121</a>
187
- <a name='L122'></a><a href='#L122'>122</a>
188
- <a name='L123'></a><a href='#L123'>123</a>
189
- <a name='L124'></a><a href='#L124'>124</a>
190
- <a name='L125'></a><a href='#L125'>125</a>
191
- <a name='L126'></a><a href='#L126'>126</a>
192
- <a name='L127'></a><a href='#L127'>127</a>
193
- <a name='L128'></a><a href='#L128'>128</a>
194
- <a name='L129'></a><a href='#L129'>129</a>
195
- <a name='L130'></a><a href='#L130'>130</a>
196
- <a name='L131'></a><a href='#L131'>131</a>
197
- <a name='L132'></a><a href='#L132'>132</a>
198
- <a name='L133'></a><a href='#L133'>133</a>
199
- <a name='L134'></a><a href='#L134'>134</a>
200
- <a name='L135'></a><a href='#L135'>135</a>
201
- <a name='L136'></a><a href='#L136'>136</a>
202
- <a name='L137'></a><a href='#L137'>137</a>
203
- <a name='L138'></a><a href='#L138'>138</a>
204
- <a name='L139'></a><a href='#L139'>139</a>
205
- <a name='L140'></a><a href='#L140'>140</a>
206
- <a name='L141'></a><a href='#L141'>141</a>
207
- <a name='L142'></a><a href='#L142'>142</a>
208
- <a name='L143'></a><a href='#L143'>143</a>
209
- <a name='L144'></a><a href='#L144'>144</a>
210
- <a name='L145'></a><a href='#L145'>145</a>
211
- <a name='L146'></a><a href='#L146'>146</a>
212
- <a name='L147'></a><a href='#L147'>147</a>
213
- <a name='L148'></a><a href='#L148'>148</a>
214
- <a name='L149'></a><a href='#L149'>149</a>
215
- <a name='L150'></a><a href='#L150'>150</a>
216
- <a name='L151'></a><a href='#L151'>151</a>
217
- <a name='L152'></a><a href='#L152'>152</a>
218
- <a name='L153'></a><a href='#L153'>153</a>
219
- <a name='L154'></a><a href='#L154'>154</a>
220
- <a name='L155'></a><a href='#L155'>155</a>
221
- <a name='L156'></a><a href='#L156'>156</a>
222
- <a name='L157'></a><a href='#L157'>157</a>
223
- <a name='L158'></a><a href='#L158'>158</a>
224
- <a name='L159'></a><a href='#L159'>159</a>
225
- <a name='L160'></a><a href='#L160'>160</a>
226
- <a name='L161'></a><a href='#L161'>161</a>
227
- <a name='L162'></a><a href='#L162'>162</a>
228
- <a name='L163'></a><a href='#L163'>163</a>
229
- <a name='L164'></a><a href='#L164'>164</a>
230
- <a name='L165'></a><a href='#L165'>165</a>
231
- <a name='L166'></a><a href='#L166'>166</a>
232
- <a name='L167'></a><a href='#L167'>167</a>
233
- <a name='L168'></a><a href='#L168'>168</a>
234
- <a name='L169'></a><a href='#L169'>169</a>
235
- <a name='L170'></a><a href='#L170'>170</a>
236
- <a name='L171'></a><a href='#L171'>171</a>
237
- <a name='L172'></a><a href='#L172'>172</a>
238
- <a name='L173'></a><a href='#L173'>173</a>
239
- <a name='L174'></a><a href='#L174'>174</a>
240
- <a name='L175'></a><a href='#L175'>175</a>
241
- <a name='L176'></a><a href='#L176'>176</a>
242
- <a name='L177'></a><a href='#L177'>177</a>
243
- <a name='L178'></a><a href='#L178'>178</a>
244
- <a name='L179'></a><a href='#L179'>179</a>
245
- <a name='L180'></a><a href='#L180'>180</a>
246
- <a name='L181'></a><a href='#L181'>181</a>
247
- <a name='L182'></a><a href='#L182'>182</a>
248
- <a name='L183'></a><a href='#L183'>183</a>
249
- <a name='L184'></a><a href='#L184'>184</a>
250
- <a name='L185'></a><a href='#L185'>185</a>
251
- <a name='L186'></a><a href='#L186'>186</a>
252
- <a name='L187'></a><a href='#L187'>187</a>
253
- <a name='L188'></a><a href='#L188'>188</a>
254
- <a name='L189'></a><a href='#L189'>189</a>
255
- <a name='L190'></a><a href='#L190'>190</a>
256
- <a name='L191'></a><a href='#L191'>191</a>
257
- <a name='L192'></a><a href='#L192'>192</a>
258
- <a name='L193'></a><a href='#L193'>193</a>
259
- <a name='L194'></a><a href='#L194'>194</a>
260
- <a name='L195'></a><a href='#L195'>195</a>
261
- <a name='L196'></a><a href='#L196'>196</a>
262
- <a name='L197'></a><a href='#L197'>197</a>
263
- <a name='L198'></a><a href='#L198'>198</a>
264
- <a name='L199'></a><a href='#L199'>199</a>
265
- <a name='L200'></a><a href='#L200'>200</a>
266
- <a name='L201'></a><a href='#L201'>201</a>
267
- <a name='L202'></a><a href='#L202'>202</a>
268
- <a name='L203'></a><a href='#L203'>203</a>
269
- <a name='L204'></a><a href='#L204'>204</a>
270
- <a name='L205'></a><a href='#L205'>205</a>
271
- <a name='L206'></a><a href='#L206'>206</a>
272
- <a name='L207'></a><a href='#L207'>207</a>
273
- <a name='L208'></a><a href='#L208'>208</a>
274
- <a name='L209'></a><a href='#L209'>209</a>
275
- <a name='L210'></a><a href='#L210'>210</a>
276
- <a name='L211'></a><a href='#L211'>211</a>
277
- <a name='L212'></a><a href='#L212'>212</a>
278
- <a name='L213'></a><a href='#L213'>213</a>
279
- <a name='L214'></a><a href='#L214'>214</a>
280
- <a name='L215'></a><a href='#L215'>215</a>
281
- <a name='L216'></a><a href='#L216'>216</a>
282
- <a name='L217'></a><a href='#L217'>217</a>
283
- <a name='L218'></a><a href='#L218'>218</a>
284
- <a name='L219'></a><a href='#L219'>219</a>
285
- <a name='L220'></a><a href='#L220'>220</a>
286
- <a name='L221'></a><a href='#L221'>221</a>
287
- <a name='L222'></a><a href='#L222'>222</a>
288
- <a name='L223'></a><a href='#L223'>223</a>
289
- <a name='L224'></a><a href='#L224'>224</a>
290
- <a name='L225'></a><a href='#L225'>225</a>
291
- <a name='L226'></a><a href='#L226'>226</a>
292
- <a name='L227'></a><a href='#L227'>227</a>
293
- <a name='L228'></a><a href='#L228'>228</a>
294
- <a name='L229'></a><a href='#L229'>229</a>
295
- <a name='L230'></a><a href='#L230'>230</a>
296
- <a name='L231'></a><a href='#L231'>231</a>
297
- <a name='L232'></a><a href='#L232'>232</a>
298
- <a name='L233'></a><a href='#L233'>233</a>
299
- <a name='L234'></a><a href='#L234'>234</a>
300
- <a name='L235'></a><a href='#L235'>235</a>
301
- <a name='L236'></a><a href='#L236'>236</a>
302
- <a name='L237'></a><a href='#L237'>237</a>
303
- <a name='L238'></a><a href='#L238'>238</a>
304
- <a name='L239'></a><a href='#L239'>239</a></td><td class="line-coverage quiet"><span class="cline-any cline-no">&nbsp;</span>
305
- <span class="cline-any cline-no">&nbsp;</span>
306
- <span class="cline-any cline-neutral">&nbsp;</span>
307
- <span class="cline-any cline-no">&nbsp;</span>
308
- <span class="cline-any cline-no">&nbsp;</span>
309
- <span class="cline-any cline-no">&nbsp;</span>
310
- <span class="cline-any cline-no">&nbsp;</span>
311
- <span class="cline-any cline-no">&nbsp;</span>
312
- <span class="cline-any cline-no">&nbsp;</span>
313
- <span class="cline-any cline-no">&nbsp;</span>
314
- <span class="cline-any cline-no">&nbsp;</span>
315
- <span class="cline-any cline-no">&nbsp;</span>
316
- <span class="cline-any cline-neutral">&nbsp;</span>
317
- <span class="cline-any cline-no">&nbsp;</span>
318
- <span class="cline-any cline-no">&nbsp;</span>
319
- <span class="cline-any cline-no">&nbsp;</span>
320
- <span class="cline-any cline-no">&nbsp;</span>
321
- <span class="cline-any cline-no">&nbsp;</span>
322
- <span class="cline-any cline-no">&nbsp;</span>
323
- <span class="cline-any cline-no">&nbsp;</span>
324
- <span class="cline-any cline-no">&nbsp;</span>
325
- <span class="cline-any cline-no">&nbsp;</span>
326
- <span class="cline-any cline-neutral">&nbsp;</span>
327
- <span class="cline-any cline-no">&nbsp;</span>
328
- <span class="cline-any cline-no">&nbsp;</span>
329
- <span class="cline-any cline-no">&nbsp;</span>
330
- <span class="cline-any cline-no">&nbsp;</span>
331
- <span class="cline-any cline-no">&nbsp;</span>
332
- <span class="cline-any cline-no">&nbsp;</span>
333
- <span class="cline-any cline-no">&nbsp;</span>
334
- <span class="cline-any cline-no">&nbsp;</span>
335
- <span class="cline-any cline-no">&nbsp;</span>
336
- <span class="cline-any cline-no">&nbsp;</span>
337
- <span class="cline-any cline-no">&nbsp;</span>
338
- <span class="cline-any cline-no">&nbsp;</span>
339
- <span class="cline-any cline-neutral">&nbsp;</span>
340
- <span class="cline-any cline-no">&nbsp;</span>
341
- <span class="cline-any cline-no">&nbsp;</span>
342
- <span class="cline-any cline-no">&nbsp;</span>
343
- <span class="cline-any cline-no">&nbsp;</span>
344
- <span class="cline-any cline-no">&nbsp;</span>
345
- <span class="cline-any cline-neutral">&nbsp;</span>
346
- <span class="cline-any cline-no">&nbsp;</span>
347
- <span class="cline-any cline-no">&nbsp;</span>
348
- <span class="cline-any cline-neutral">&nbsp;</span>
349
- <span class="cline-any cline-no">&nbsp;</span>
350
- <span class="cline-any cline-no">&nbsp;</span>
351
- <span class="cline-any cline-no">&nbsp;</span>
352
- <span class="cline-any cline-no">&nbsp;</span>
353
- <span class="cline-any cline-no">&nbsp;</span>
354
- <span class="cline-any cline-no">&nbsp;</span>
355
- <span class="cline-any cline-no">&nbsp;</span>
356
- <span class="cline-any cline-no">&nbsp;</span>
357
- <span class="cline-any cline-no">&nbsp;</span>
358
- <span class="cline-any cline-no">&nbsp;</span>
359
- <span class="cline-any cline-no">&nbsp;</span>
360
- <span class="cline-any cline-no">&nbsp;</span>
361
- <span class="cline-any cline-neutral">&nbsp;</span>
362
- <span class="cline-any cline-no">&nbsp;</span>
363
- <span class="cline-any cline-no">&nbsp;</span>
364
- <span class="cline-any cline-no">&nbsp;</span>
365
- <span class="cline-any cline-neutral">&nbsp;</span>
366
- <span class="cline-any cline-no">&nbsp;</span>
367
- <span class="cline-any cline-no">&nbsp;</span>
368
- <span class="cline-any cline-neutral">&nbsp;</span>
369
- <span class="cline-any cline-no">&nbsp;</span>
370
- <span class="cline-any cline-no">&nbsp;</span>
371
- <span class="cline-any cline-no">&nbsp;</span>
372
- <span class="cline-any cline-no">&nbsp;</span>
373
- <span class="cline-any cline-no">&nbsp;</span>
374
- <span class="cline-any cline-no">&nbsp;</span>
375
- <span class="cline-any cline-no">&nbsp;</span>
376
- <span class="cline-any cline-no">&nbsp;</span>
377
- <span class="cline-any cline-no">&nbsp;</span>
378
- <span class="cline-any cline-no">&nbsp;</span>
379
- <span class="cline-any cline-no">&nbsp;</span>
380
- <span class="cline-any cline-no">&nbsp;</span>
381
- <span class="cline-any cline-no">&nbsp;</span>
382
- <span class="cline-any cline-neutral">&nbsp;</span>
383
- <span class="cline-any cline-no">&nbsp;</span>
384
- <span class="cline-any cline-no">&nbsp;</span>
385
- <span class="cline-any cline-no">&nbsp;</span>
386
- <span class="cline-any cline-neutral">&nbsp;</span>
387
- <span class="cline-any cline-no">&nbsp;</span>
388
- <span class="cline-any cline-no">&nbsp;</span>
389
- <span class="cline-any cline-no">&nbsp;</span>
390
- <span class="cline-any cline-no">&nbsp;</span>
391
- <span class="cline-any cline-no">&nbsp;</span>
392
- <span class="cline-any cline-neutral">&nbsp;</span>
393
- <span class="cline-any cline-no">&nbsp;</span>
394
- <span class="cline-any cline-no">&nbsp;</span>
395
- <span class="cline-any cline-no">&nbsp;</span>
396
- <span class="cline-any cline-no">&nbsp;</span>
397
- <span class="cline-any cline-no">&nbsp;</span>
398
- <span class="cline-any cline-no">&nbsp;</span>
399
- <span class="cline-any cline-no">&nbsp;</span>
400
- <span class="cline-any cline-no">&nbsp;</span>
401
- <span class="cline-any cline-no">&nbsp;</span>
402
- <span class="cline-any cline-no">&nbsp;</span>
403
- <span class="cline-any cline-neutral">&nbsp;</span>
404
- <span class="cline-any cline-no">&nbsp;</span>
405
- <span class="cline-any cline-neutral">&nbsp;</span>
406
- <span class="cline-any cline-neutral">&nbsp;</span>
407
- <span class="cline-any cline-no">&nbsp;</span>
408
- <span class="cline-any cline-no">&nbsp;</span>
409
- <span class="cline-any cline-no">&nbsp;</span>
410
- <span class="cline-any cline-no">&nbsp;</span>
411
- <span class="cline-any cline-no">&nbsp;</span>
412
- <span class="cline-any cline-no">&nbsp;</span>
413
- <span class="cline-any cline-no">&nbsp;</span>
414
- <span class="cline-any cline-no">&nbsp;</span>
415
- <span class="cline-any cline-no">&nbsp;</span>
416
- <span class="cline-any cline-no">&nbsp;</span>
417
- <span class="cline-any cline-no">&nbsp;</span>
418
- <span class="cline-any cline-no">&nbsp;</span>
419
- <span class="cline-any cline-no">&nbsp;</span>
420
- <span class="cline-any cline-no">&nbsp;</span>
421
- <span class="cline-any cline-no">&nbsp;</span>
422
- <span class="cline-any cline-no">&nbsp;</span>
423
- <span class="cline-any cline-no">&nbsp;</span>
424
- <span class="cline-any cline-no">&nbsp;</span>
425
- <span class="cline-any cline-no">&nbsp;</span>
426
- <span class="cline-any cline-no">&nbsp;</span>
427
- <span class="cline-any cline-no">&nbsp;</span>
428
- <span class="cline-any cline-no">&nbsp;</span>
429
- <span class="cline-any cline-no">&nbsp;</span>
430
- <span class="cline-any cline-no">&nbsp;</span>
431
- <span class="cline-any cline-neutral">&nbsp;</span>
432
- <span class="cline-any cline-no">&nbsp;</span>
433
- <span class="cline-any cline-neutral">&nbsp;</span>
434
- <span class="cline-any cline-no">&nbsp;</span>
435
- <span class="cline-any cline-no">&nbsp;</span>
436
- <span class="cline-any cline-no">&nbsp;</span>
437
- <span class="cline-any cline-neutral">&nbsp;</span>
438
- <span class="cline-any cline-neutral">&nbsp;</span>
439
- <span class="cline-any cline-no">&nbsp;</span>
440
- <span class="cline-any cline-no">&nbsp;</span>
441
- <span class="cline-any cline-no">&nbsp;</span>
442
- <span class="cline-any cline-neutral">&nbsp;</span>
443
- <span class="cline-any cline-no">&nbsp;</span>
444
- <span class="cline-any cline-no">&nbsp;</span>
445
- <span class="cline-any cline-no">&nbsp;</span>
446
- <span class="cline-any cline-neutral">&nbsp;</span>
447
- <span class="cline-any cline-no">&nbsp;</span>
448
- <span class="cline-any cline-no">&nbsp;</span>
449
- <span class="cline-any cline-no">&nbsp;</span>
450
- <span class="cline-any cline-neutral">&nbsp;</span>
451
- <span class="cline-any cline-no">&nbsp;</span>
452
- <span class="cline-any cline-no">&nbsp;</span>
453
- <span class="cline-any cline-no">&nbsp;</span>
454
- <span class="cline-any cline-no">&nbsp;</span>
455
- <span class="cline-any cline-neutral">&nbsp;</span>
456
- <span class="cline-any cline-no">&nbsp;</span>
457
- <span class="cline-any cline-no">&nbsp;</span>
458
- <span class="cline-any cline-no">&nbsp;</span>
459
- <span class="cline-any cline-neutral">&nbsp;</span>
460
- <span class="cline-any cline-no">&nbsp;</span>
461
- <span class="cline-any cline-no">&nbsp;</span>
462
- <span class="cline-any cline-no">&nbsp;</span>
463
- <span class="cline-any cline-neutral">&nbsp;</span>
464
- <span class="cline-any cline-no">&nbsp;</span>
465
- <span class="cline-any cline-no">&nbsp;</span>
466
- <span class="cline-any cline-no">&nbsp;</span>
467
- <span class="cline-any cline-neutral">&nbsp;</span>
468
- <span class="cline-any cline-no">&nbsp;</span>
469
- <span class="cline-any cline-no">&nbsp;</span>
470
- <span class="cline-any cline-no">&nbsp;</span>
471
- <span class="cline-any cline-neutral">&nbsp;</span>
472
- <span class="cline-any cline-no">&nbsp;</span>
473
- <span class="cline-any cline-no">&nbsp;</span>
474
- <span class="cline-any cline-no">&nbsp;</span>
475
- <span class="cline-any cline-no">&nbsp;</span>
476
- <span class="cline-any cline-no">&nbsp;</span>
477
- <span class="cline-any cline-no">&nbsp;</span>
478
- <span class="cline-any cline-no">&nbsp;</span>
479
- <span class="cline-any cline-no">&nbsp;</span>
480
- <span class="cline-any cline-no">&nbsp;</span>
481
- <span class="cline-any cline-no">&nbsp;</span>
482
- <span class="cline-any cline-no">&nbsp;</span>
483
- <span class="cline-any cline-no">&nbsp;</span>
484
- <span class="cline-any cline-no">&nbsp;</span>
485
- <span class="cline-any cline-no">&nbsp;</span>
486
- <span class="cline-any cline-neutral">&nbsp;</span>
487
- <span class="cline-any cline-no">&nbsp;</span>
488
- <span class="cline-any cline-no">&nbsp;</span>
489
- <span class="cline-any cline-no">&nbsp;</span>
490
- <span class="cline-any cline-neutral">&nbsp;</span>
491
- <span class="cline-any cline-no">&nbsp;</span>
492
- <span class="cline-any cline-no">&nbsp;</span>
493
- <span class="cline-any cline-no">&nbsp;</span>
494
- <span class="cline-any cline-no">&nbsp;</span>
495
- <span class="cline-any cline-no">&nbsp;</span>
496
- <span class="cline-any cline-no">&nbsp;</span>
497
- <span class="cline-any cline-neutral">&nbsp;</span>
498
- <span class="cline-any cline-no">&nbsp;</span>
499
- <span class="cline-any cline-no">&nbsp;</span>
500
- <span class="cline-any cline-no">&nbsp;</span>
501
- <span class="cline-any cline-neutral">&nbsp;</span>
502
- <span class="cline-any cline-no">&nbsp;</span>
503
- <span class="cline-any cline-no">&nbsp;</span>
504
- <span class="cline-any cline-no">&nbsp;</span>
505
- <span class="cline-any cline-neutral">&nbsp;</span>
506
- <span class="cline-any cline-no">&nbsp;</span>
507
- <span class="cline-any cline-no">&nbsp;</span>
508
- <span class="cline-any cline-no">&nbsp;</span>
509
- <span class="cline-any cline-neutral">&nbsp;</span>
510
- <span class="cline-any cline-no">&nbsp;</span>
511
- <span class="cline-any cline-no">&nbsp;</span>
512
- <span class="cline-any cline-no">&nbsp;</span>
513
- <span class="cline-any cline-no">&nbsp;</span>
514
- <span class="cline-any cline-no">&nbsp;</span>
515
- <span class="cline-any cline-no">&nbsp;</span>
516
- <span class="cline-any cline-no">&nbsp;</span>
517
- <span class="cline-any cline-neutral">&nbsp;</span>
518
- <span class="cline-any cline-no">&nbsp;</span>
519
- <span class="cline-any cline-no">&nbsp;</span>
520
- <span class="cline-any cline-no">&nbsp;</span>
521
- <span class="cline-any cline-neutral">&nbsp;</span>
522
- <span class="cline-any cline-no">&nbsp;</span>
523
- <span class="cline-any cline-no">&nbsp;</span>
524
- <span class="cline-any cline-no">&nbsp;</span>
525
- <span class="cline-any cline-no">&nbsp;</span>
526
- <span class="cline-any cline-no">&nbsp;</span>
527
- <span class="cline-any cline-no">&nbsp;</span>
528
- <span class="cline-any cline-no">&nbsp;</span>
529
- <span class="cline-any cline-no">&nbsp;</span>
530
- <span class="cline-any cline-no">&nbsp;</span>
531
- <span class="cline-any cline-no">&nbsp;</span>
532
- <span class="cline-any cline-no">&nbsp;</span>
533
- <span class="cline-any cline-neutral">&nbsp;</span>
534
- <span class="cline-any cline-no">&nbsp;</span>
535
- <span class="cline-any cline-no">&nbsp;</span>
536
- <span class="cline-any cline-no">&nbsp;</span>
537
- <span class="cline-any cline-neutral">&nbsp;</span>
538
- <span class="cline-any cline-no">&nbsp;</span>
539
- <span class="cline-any cline-no">&nbsp;</span>
540
- <span class="cline-any cline-neutral">&nbsp;</span>
541
- <span class="cline-any cline-no">&nbsp;</span>
542
- <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js"><span class="cstat-no" title="statement not covered" >// Import using object destructuring for better compatibility with tests<span class="fstat-no" title="function not covered" ><span class="branch-0 cbranch-no" title="branch not covered" ></span></span></span>
543
- <span class="cstat-no" title="statement not covered" >import { arrayCount } from './arrayUtils.js';</span>
544
- &nbsp;
545
- <span class="cstat-no" title="statement not covered" >/**</span>
546
- <span class="cstat-no" title="statement not covered" > * Returns the number of rows in the given table element.</span>
547
- <span class="cstat-no" title="statement not covered" > *</span>
548
- <span class="cstat-no" title="statement not covered" > * @param {HTMLTableElement} table - The table element to count rows in.</span>
549
- <span class="cstat-no" title="statement not covered" > * @returns {number} The number of rows in the table.</span>
550
- <span class="cstat-no" title="statement not covered" > */</span>
551
- <span class="cstat-no" title="statement not covered" >function rowCount(table) {</span>
552
- <span class="cstat-no" title="statement not covered" > return table.querySelectorAll('tr').length;</span>
553
- <span class="cstat-no" title="statement not covered" >}</span>
554
- &nbsp;
555
- <span class="cstat-no" title="statement not covered" >/**</span>
556
- <span class="cstat-no" title="statement not covered" > * Counts the number of cells (both &lt;td&gt; and &lt;th&gt;) in a given table element.</span>
557
- <span class="cstat-no" title="statement not covered" > *</span>
558
- <span class="cstat-no" title="statement not covered" > * @param {HTMLTableElement} table - The table element to count cells in.</span>
559
- <span class="cstat-no" title="statement not covered" > * @returns {number} The total number of cells in the table.</span>
560
- <span class="cstat-no" title="statement not covered" > */</span>
561
- <span class="cstat-no" title="statement not covered" >function cellCount(table) {</span>
562
- <span class="cstat-no" title="statement not covered" > return table.querySelectorAll('td, th').length;</span>
563
- <span class="cstat-no" title="statement not covered" >}</span>
564
- &nbsp;
565
- <span class="cstat-no" title="statement not covered" >/**</span>
566
- <span class="cstat-no" title="statement not covered" > * Calculates the percentage of table cells that have a border.</span>
567
- <span class="cstat-no" title="statement not covered" > *</span>
568
- <span class="cstat-no" title="statement not covered" > * @param {HTMLTableElement} table - The table element to analyze.</span>
569
- <span class="cstat-no" title="statement not covered" > * @returns {number} The percentage of table cells that have a border.</span>
570
- <span class="cstat-no" title="statement not covered" > */</span>
571
- <span class="cstat-no" title="statement not covered" >function countBordersPct(table) {</span>
572
- <span class="cstat-no" title="statement not covered" > const cells = table.querySelectorAll('td, th');</span>
573
- <span class="cstat-no" title="statement not covered" > const totalCells = cells.length;</span>
574
- <span class="cstat-no" title="statement not covered" > if (totalCells === 0) return 0;</span>
575
- <span class="cstat-no" title="statement not covered" > </span>
576
- <span class="cstat-no" title="statement not covered" > let borderedCells = 0;</span>
577
- &nbsp;
578
- <span class="cstat-no" title="statement not covered" > cells.forEach(cell =&gt; {</span>
579
- <span class="cstat-no" title="statement not covered" > if (window.getComputedStyle(cell).borderWidth !== '0px') {</span>
580
- <span class="cstat-no" title="statement not covered" > borderedCells++;</span>
581
- <span class="cstat-no" title="statement not covered" > }</span>
582
- <span class="cstat-no" title="statement not covered" > });</span>
583
- &nbsp;
584
- <span class="cstat-no" title="statement not covered" > return (borderedCells / totalCells) * 100;</span>
585
- <span class="cstat-no" title="statement not covered" >}</span>
586
- &nbsp;
587
- <span class="cstat-no" title="statement not covered" >/**</span>
588
- <span class="cstat-no" title="statement not covered" > * Calculates the average number of columns in a given HTML table.</span>
589
- <span class="cstat-no" title="statement not covered" > *</span>
590
- <span class="cstat-no" title="statement not covered" > * @param {HTMLTableElement} table - The table element to analyze.</span>
591
- <span class="cstat-no" title="statement not covered" > * @returns {number} The average number of columns per row in the table.</span>
592
- <span class="cstat-no" title="statement not covered" > */</span>
593
- <span class="cstat-no" title="statement not covered" >function colCount(table) {</span>
594
- <span class="cstat-no" title="statement not covered" > const rows = table.querySelectorAll('tr');</span>
595
- <span class="cstat-no" title="statement not covered" > const rowCnt = rows.length;</span>
596
- <span class="cstat-no" title="statement not covered" > if (rowCnt === 0) return 0;</span>
597
- <span class="cstat-no" title="statement not covered" > </span>
598
- <span class="cstat-no" title="statement not covered" > let totalColumns = 0;</span>
599
- &nbsp;
600
- <span class="cstat-no" title="statement not covered" > rows.forEach(row =&gt; {</span>
601
- <span class="cstat-no" title="statement not covered" > totalColumns += row.cells.length;</span>
602
- <span class="cstat-no" title="statement not covered" > });</span>
603
- &nbsp;
604
- <span class="cstat-no" title="statement not covered" > return Math.round(totalColumns / rowCnt);</span>
605
- <span class="cstat-no" title="statement not covered" >}</span>
606
- &nbsp;
607
- <span class="cstat-no" title="statement not covered" >/**</span>
608
- <span class="cstat-no" title="statement not covered" > * Checks if the color differences in the table cells exceed the specified limits.</span>
609
- <span class="cstat-no" title="statement not covered" > *</span>
610
- <span class="cstat-no" title="statement not covered" > * @param {HTMLTableElement} table - The table element to check.</span>
611
- <span class="cstat-no" title="statement not covered" > * @param {number} maxColors - The maximum number of unique colors allowed.</span>
612
- <span class="cstat-no" title="statement not covered" > * @param {number} maxDiffs - The maximum percentage difference allowed for any color.</span>
613
- <span class="cstat-no" title="statement not covered" > * @returns {boolean} - Returns true if the color differences exceed the specified limits, otherwise false.</span>
614
- <span class="cstat-no" title="statement not covered" > */</span>
615
- <span class="cstat-no" title="statement not covered" >function cellColorDiffs(table, maxColors, maxDiffs) {</span>
616
- <span class="cstat-no" title="statement not covered" > const colors = [];</span>
617
- <span class="cstat-no" title="statement not covered" > const cells = table.querySelectorAll('td, th');</span>
618
- <span class="cstat-no" title="statement not covered" > </span>
619
- <span class="cstat-no" title="statement not covered" > if (cells.length === 0) return false;</span>
620
- &nbsp;
621
- <span class="cstat-no" title="statement not covered" > cells.forEach(cell =&gt; {</span>
622
- <span class="cstat-no" title="statement not covered" > colors.push(window.getComputedStyle(cell).backgroundColor);</span>
623
- <span class="cstat-no" title="statement not covered" > });</span>
624
- &nbsp;
625
- <span class="cstat-no" title="statement not covered" > const colorObj = arrayCount(colors);</span>
626
- <span class="cstat-no" title="statement not covered" > // Check if colorObj is undefined or null before using Object.keys</span>
627
- <span class="cstat-no" title="statement not covered" > if (!colorObj) return false;</span>
628
- <span class="cstat-no" title="statement not covered" > </span>
629
- <span class="cstat-no" title="statement not covered" > const uniqueColors = Object.keys(colorObj).length;</span>
630
- &nbsp;
631
- <span class="cstat-no" title="statement not covered" > if (uniqueColors &gt; 1) {</span>
632
- <span class="cstat-no" title="statement not covered" > if (uniqueColors &gt; maxColors) {</span>
633
- <span class="cstat-no" title="statement not covered" > return true;</span>
634
- <span class="cstat-no" title="statement not covered" > }</span>
635
- <span class="cstat-no" title="statement not covered" > return Object.values(colorObj).some(value =&gt; {</span>
636
- <span class="cstat-no" title="statement not covered" > return (value / uniqueColors) * 100 &gt; maxDiffs;</span>
637
- <span class="cstat-no" title="statement not covered" > });</span>
638
- <span class="cstat-no" title="statement not covered" > }</span>
639
- <span class="cstat-no" title="statement not covered" > return false;</span>
640
- <span class="cstat-no" title="statement not covered" >}</span>
641
- &nbsp;
642
- <span class="cstat-no" title="statement not covered" >// Export the utility functions</span>
643
- export { rowCount, cellCount, countBordersPct, colCount, cellColorDiffs };
644
- &nbsp;
645
- <span class="cstat-no" title="statement not covered" >/**</span>
646
- <span class="cstat-no" title="statement not covered" > * Determines if a given table element is a data table based on various heuristics and options.</span>
647
- <span class="cstat-no" title="statement not covered" > *</span>
648
- <span class="cstat-no" title="statement not covered" > * @param {HTMLTableElement} table - The table element to evaluate.</span>
649
- <span class="cstat-no" title="statement not covered" > * @param {Object} [options={}] - Optional settings to override default heuristics.</span>
650
- <span class="cstat-no" title="statement not covered" > * @param {number} [options.numDTColumns=5] - Minimum number of columns to consider as a data table.</span>
651
- <span class="cstat-no" title="statement not covered" > * @param {number} [options.pctCellsWBorder=33] - Minimum percentage of cells with borders to consider as a data table.</span>
652
- <span class="cstat-no" title="statement not covered" > * @param {number} [options.numDTRows=20] - Minimum number of rows to consider as a data table.</span>
653
- <span class="cstat-no" title="statement not covered" > * @param {number} [options.maxWidthLT=95] - Maximum width percentage of the viewport to consider as a data table.</span>
654
- <span class="cstat-no" title="statement not covered" > * @param {number} [options.minCellsLT=10] - Minimum number of cells to consider as a data table.</span>
655
- <span class="cstat-no" title="statement not covered" > * @param {number} [options.maxCellColors=3] - Maximum number of different cell colors to consider as a data table.</span>
656
- <span class="cstat-no" title="statement not covered" > * @param {number} [options.maxColorDiffs=30] - Maximum number of color differences to consider as a data table.</span>
657
- <span class="cstat-no" title="statement not covered" > * @returns {boolean} - Returns true if the table is considered a data table, otherwise false.</span>
658
- <span class="cstat-no" title="statement not covered" > */</span>
659
- <span class="cstat-no" title="statement not covered" >function isDataTable(table, options = {}) {</span>
660
- <span class="cstat-no" title="statement not covered" > const defaults = {</span>
661
- <span class="cstat-no" title="statement not covered" > numDTColumns: 5,</span>
662
- <span class="cstat-no" title="statement not covered" > pctCellsWBorder: 33,</span>
663
- <span class="cstat-no" title="statement not covered" > numDTRows: 20,</span>
664
- <span class="cstat-no" title="statement not covered" > maxWidthLT: 95,</span>
665
- <span class="cstat-no" title="statement not covered" > minCellsLT: 10,</span>
666
- <span class="cstat-no" title="statement not covered" > maxCellColors: 3,</span>
667
- <span class="cstat-no" title="statement not covered" > maxColorDiffs: 30</span>
668
- <span class="cstat-no" title="statement not covered" > };</span>
669
- &nbsp;
670
- <span class="cstat-no" title="statement not covered" > const settings = { ...defaults, ...options };</span>
671
- &nbsp;
672
- <span class="cstat-no" title="statement not covered" > if (!table || table.tagName.toLowerCase() !== 'table') {</span>
673
- <span class="cstat-no" title="statement not covered" > return false;</span>
674
- <span class="cstat-no" title="statement not covered" > }</span>
675
- &nbsp;
676
- &nbsp;
677
- <span class="cstat-no" title="statement not covered" > if (table.closest &amp;&amp; table.closest("[contenteditable='true'], [contenteditable='inherit']")) {</span>
678
- <span class="cstat-no" title="statement not covered" > return true;</span>
679
- <span class="cstat-no" title="statement not covered" > }</span>
680
- &nbsp;
681
- <span class="cstat-no" title="statement not covered" > if (table.getAttribute &amp;&amp; table.getAttribute('role') === 'presentation') {</span>
682
- <span class="cstat-no" title="statement not covered" > return false;</span>
683
- <span class="cstat-no" title="statement not covered" > }</span>
684
- &nbsp;
685
- <span class="cstat-no" title="statement not covered" > if (table.getAttribute &amp;&amp; ['grid', 'treegrid'].includes(table.getAttribute('role'))) {</span>
686
- <span class="cstat-no" title="statement not covered" > return true;</span>
687
- <span class="cstat-no" title="statement not covered" > }</span>
688
- &nbsp;
689
- <span class="cstat-no" title="statement not covered" > const roleChildren = table.querySelectorAll &amp;&amp; table.querySelectorAll('th[role="gridcell"], td[role="rowheader"], td[role="columnheader"]');</span>
690
- <span class="cstat-no" title="statement not covered" > if (roleChildren &amp;&amp; roleChildren.length &gt; 0) {</span>
691
- <span class="cstat-no" title="statement not covered" > return true;</span>
692
- <span class="cstat-no" title="statement not covered" > }</span>
693
- &nbsp;
694
- <span class="cstat-no" title="statement not covered" > if (table.querySelector &amp;&amp; table.querySelector('tr[role="row"]')) {</span>
695
- <span class="cstat-no" title="statement not covered" > return true;</span>
696
- <span class="cstat-no" title="statement not covered" > }</span>
697
- &nbsp;
698
- <span class="cstat-no" title="statement not covered" > if (table.querySelector &amp;&amp; table.querySelector('*[role="rowgroup"]')) {</span>
699
- <span class="cstat-no" title="statement not covered" > return true;</span>
700
- <span class="cstat-no" title="statement not covered" > }</span>
701
- &nbsp;
702
- <span class="cstat-no" title="statement not covered" > if (table.hasAttribute &amp;&amp; table.hasAttribute('datatable') &amp;&amp; table.getAttribute('datatable') === '0') {</span>
703
- <span class="cstat-no" title="statement not covered" > return false;</span>
704
- <span class="cstat-no" title="statement not covered" > }</span>
705
- &nbsp;
706
- <span class="cstat-no" title="statement not covered" > if (table.hasAttribute &amp;&amp; table.hasAttribute('datatable') &amp;&amp; table.getAttribute('datatable') === '1') {</span>
707
- <span class="cstat-no" title="statement not covered" > return true;</span>
708
- <span class="cstat-no" title="statement not covered" > }</span>
709
- &nbsp;
710
- <span class="cstat-no" title="statement not covered" > // Check for table elements that indicate it's a data table</span>
711
- <span class="cstat-no" title="statement not covered" > if (table.hasAttribute &amp;&amp; (table.hasAttribute('summary') || table.hasAttribute('rules'))) {</span>
712
- <span class="cstat-no" title="statement not covered" > return true;</span>
713
- <span class="cstat-no" title="statement not covered" > }</span>
714
- <span class="cstat-no" title="statement not covered" > </span>
715
- <span class="cstat-no" title="statement not covered" > // Look for caption</span>
716
- <span class="cstat-no" title="statement not covered" > if (table.querySelector &amp;&amp; table.querySelector('caption')) {</span>
717
- <span class="cstat-no" title="statement not covered" > return true;</span>
718
- <span class="cstat-no" title="statement not covered" > }</span>
719
- <span class="cstat-no" title="statement not covered" > </span>
720
- <span class="cstat-no" title="statement not covered" > // Look for other data table indicators</span>
721
- <span class="cstat-no" title="statement not covered" > if (table.querySelector &amp;&amp; table.querySelector('col, colgroup, tfoot, thead, th, td[headers], td[scope], td[abbr], td[axis]')) {</span>
722
- <span class="cstat-no" title="statement not covered" > return true;</span>
723
- <span class="cstat-no" title="statement not covered" > }</span>
724
- &nbsp;
725
- <span class="cstat-no" title="statement not covered" > if (table.querySelector &amp;&amp; table.querySelector('table')) {</span>
726
- <span class="cstat-no" title="statement not covered" > return false;</span>
727
- <span class="cstat-no" title="statement not covered" > }</span>
728
- &nbsp;
729
- <span class="cstat-no" title="statement not covered" > const rows = rowCount(table);</span>
730
- <span class="cstat-no" title="statement not covered" > const cells = cellCount(table);</span>
731
- <span class="cstat-no" title="statement not covered" > </span>
732
- <span class="cstat-no" title="statement not covered" > if (rows === 1 || cells === 1) {</span>
733
- <span class="cstat-no" title="statement not covered" > return false;</span>
734
- <span class="cstat-no" title="statement not covered" > }</span>
735
- &nbsp;
736
- <span class="cstat-no" title="statement not covered" > if (colCount(table) &gt;= settings.numDTColumns) {</span>
737
- <span class="cstat-no" title="statement not covered" > return true;</span>
738
- <span class="cstat-no" title="statement not covered" > }</span>
739
- &nbsp;
740
- <span class="cstat-no" title="statement not covered" > if (table.hasAttribute &amp;&amp; table.hasAttribute('border') &amp;&amp; table.getAttribute('border') !== '0') {</span>
741
- <span class="cstat-no" title="statement not covered" > return true;</span>
742
- <span class="cstat-no" title="statement not covered" > }</span>
743
- &nbsp;
744
- <span class="cstat-no" title="statement not covered" > if (countBordersPct(table) &gt; settings.pctCellsWBorder) {</span>
745
- <span class="cstat-no" title="statement not covered" > return true;</span>
746
- <span class="cstat-no" title="statement not covered" > }</span>
747
- &nbsp;
748
- <span class="cstat-no" title="statement not covered" > try {</span>
749
- <span class="cstat-no" title="statement not covered" > if (cellColorDiffs(table, settings.maxCellColors, settings.maxColorDiffs)) {</span>
750
- <span class="cstat-no" title="statement not covered" > return true;</span>
751
- <span class="cstat-no" title="statement not covered" > }</span>
752
- <span class="cstat-no" title="statement not covered" > } catch (e) {</span>
753
- <span class="cstat-no" title="statement not covered" > // Safely ignore errors in color difference calculation</span>
754
- <span class="cstat-no" title="statement not covered" > }</span>
755
- &nbsp;
756
- <span class="cstat-no" title="statement not covered" > if (rows &gt;= settings.numDTRows) {</span>
757
- <span class="cstat-no" title="statement not covered" > return true;</span>
758
- <span class="cstat-no" title="statement not covered" > }</span>
759
- &nbsp;
760
- <span class="cstat-no" title="statement not covered" > // Check if the table is too wide compared to the viewport</span>
761
- <span class="cstat-no" title="statement not covered" > if (table.offsetWidth &amp;&amp; document.documentElement &amp;&amp; document.documentElement.clientWidth) {</span>
762
- <span class="cstat-no" title="statement not covered" > const viewportWidth = document.documentElement.clientWidth;</span>
763
- <span class="cstat-no" title="statement not covered" > if ((table.offsetWidth / viewportWidth) * 100 &gt; settings.maxWidthLT) {</span>
764
- <span class="cstat-no" title="statement not covered" > return false;</span>
765
- <span class="cstat-no" title="statement not covered" > }</span>
766
- <span class="cstat-no" title="statement not covered" > }</span>
767
- <span class="cstat-no" title="statement not covered" > </span>
768
- <span class="cstat-no" title="statement not covered" > if (cells &lt;= settings.minCellsLT) {</span>
769
- <span class="cstat-no" title="statement not covered" > return false;</span>
770
- <span class="cstat-no" title="statement not covered" > }</span>
771
- &nbsp;
772
- <span class="cstat-no" title="statement not covered" > if (table.querySelector &amp;&amp; table.querySelector('embed, object, applet, iframe')) {</span>
773
- <span class="cstat-no" title="statement not covered" > return false;</span>
774
- <span class="cstat-no" title="statement not covered" > }</span>
775
- &nbsp;
776
- <span class="cstat-no" title="statement not covered" > return true;</span>
777
- <span class="cstat-no" title="statement not covered" >}</span>
778
- &nbsp;
779
- <span class="cstat-no" title="statement not covered" >// Export the main function</span>
780
- export { isDataTable };</pre></td></tr></table></pre>
781
-
782
- <div class='push'></div><!-- for sticky footer -->
783
- </div><!-- /wrapper -->
784
- <div class='footer quiet pad2 space-top1 center small'>
785
- Code coverage generated by
786
- <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
787
- at 2025-06-23T19:41:12.391Z
788
- </div>
789
- <script src="../../prettify.js"></script>
790
- <script>
791
- window.onload = function () {
792
- prettyPrint();
793
- };
794
- </script>
795
- <script src="../../sorter.js"></script>
796
- <script src="../../block-navigation.js"></script>
797
- </body>
798
- </html>
799
-