@elliemae/encw-leak-runner 1.0.13 → 1.0.15

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 (144) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +63 -0
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/bin/leak-runner.js +258 -29
  5. package/dist/cjs/browser/heapMemoryProfiler.js +182 -0
  6. package/dist/cjs/browser/iframeHeapProfiler.js +2 -2
  7. package/dist/cjs/index.js +2 -0
  8. package/dist/cjs/runner/scenarioRunner.js +9 -6
  9. package/dist/cjs/scenarios/index.js +7 -4
  10. package/dist/cjs/scenarios/one-admin/index.js +5 -1
  11. package/dist/cjs/scenarios/pipeline/index.js +31 -0
  12. package/dist/cjs/scenarios/pipeline/page-models/PipelinePageModel.js +52 -0
  13. package/dist/cjs/scenarios/pipeline/page-models/index.js +24 -0
  14. package/dist/cjs/scenarios/pipeline/pipeline-task-navigation.scenario.js +56 -0
  15. package/dist/esm/browser/heapMemoryProfiler.js +152 -0
  16. package/dist/esm/browser/iframeHeapProfiler.js +1 -1
  17. package/dist/esm/index.js +2 -0
  18. package/dist/esm/runner/scenarioRunner.js +9 -6
  19. package/dist/esm/scenarios/index.js +8 -5
  20. package/dist/esm/scenarios/one-admin/index.js +5 -1
  21. package/dist/esm/scenarios/pipeline/index.js +11 -0
  22. package/dist/esm/scenarios/pipeline/page-models/PipelinePageModel.js +32 -0
  23. package/dist/esm/scenarios/pipeline/page-models/index.js +4 -0
  24. package/dist/esm/scenarios/pipeline/pipeline-task-navigation.scenario.js +36 -0
  25. package/dist/types/lib/browser/heapMemoryProfiler.d.ts +149 -0
  26. package/dist/types/lib/browser/iframeHeapProfiler.d.ts +1 -1
  27. package/dist/types/lib/browser/tests/heapMemoryProfiler.test.d.ts +1 -0
  28. package/dist/types/lib/config/runnerConfigSchema.d.ts +6 -6
  29. package/dist/types/lib/index.d.ts +2 -0
  30. package/dist/types/lib/scenarios/one-admin/index.d.ts +2 -2
  31. package/dist/types/lib/scenarios/pipeline/index.d.ts +2 -0
  32. package/dist/types/lib/scenarios/pipeline/page-models/PipelinePageModel.d.ts +14 -0
  33. package/dist/types/lib/scenarios/pipeline/page-models/index.d.ts +1 -0
  34. package/dist/types/lib/scenarios/pipeline/pipeline-task-navigation.scenario.d.ts +2 -0
  35. package/leak-runner.config.json +1 -1
  36. package/lib/browser/heapMemoryProfiler.ts +284 -0
  37. package/lib/browser/iframeHeapProfiler.ts +1 -1
  38. package/lib/browser/tests/heapMemoryProfiler.test.ts +64 -0
  39. package/lib/browser/tests/iframeHeapProfiler.test.ts +1 -1
  40. package/lib/index.ts +2 -0
  41. package/lib/runner/scenarioRunner.ts +9 -6
  42. package/lib/scenarios/index.ts +8 -6
  43. package/lib/scenarios/one-admin/index.ts +7 -1
  44. package/lib/scenarios/pipeline/index.ts +12 -0
  45. package/lib/scenarios/pipeline/page-models/PipelinePageModel.ts +46 -0
  46. package/lib/scenarios/pipeline/page-models/index.ts +1 -0
  47. package/lib/scenarios/pipeline/pipeline-task-navigation.scenario.ts +42 -0
  48. package/package.json +5 -4
  49. package/reports/analysis/index.html +1 -1
  50. package/reports/analysis/thresholdEvaluator.ts.html +1 -1
  51. package/reports/browser/heapMemoryProfiler.ts.html +937 -0
  52. package/reports/browser/iframeHeapProfiler.ts.html +5 -5
  53. package/reports/browser/index.html +25 -10
  54. package/reports/cli/commands/index.html +1 -1
  55. package/reports/cli/commands/listCommand.ts.html +1 -1
  56. package/reports/cli/commands/runCommand.ts.html +1 -1
  57. package/reports/cli/index.html +1 -1
  58. package/reports/cli/index.ts.html +1 -1
  59. package/reports/config/index.html +1 -1
  60. package/reports/config/missingRequiredParamError.ts.html +1 -1
  61. package/reports/config/requiredEnvParams.ts.html +1 -1
  62. package/reports/config/runnerConfigLoader.ts.html +1 -1
  63. package/reports/config/runnerConfigSchema.ts.html +1 -1
  64. package/reports/config/sources/cliOverrideConfigSource.ts.html +1 -1
  65. package/reports/config/sources/configSource.ts.html +1 -1
  66. package/reports/config/sources/envVarConfigSource.ts.html +1 -1
  67. package/reports/config/sources/fileConfigSource.ts.html +1 -1
  68. package/reports/config/sources/index.html +1 -1
  69. package/reports/config/unknownEnvError.ts.html +1 -1
  70. package/reports/index.html +63 -33
  71. package/reports/lcov-report/analysis/index.html +1 -1
  72. package/reports/lcov-report/analysis/thresholdEvaluator.ts.html +1 -1
  73. package/reports/lcov-report/browser/heapMemoryProfiler.ts.html +937 -0
  74. package/reports/lcov-report/browser/iframeHeapProfiler.ts.html +5 -5
  75. package/reports/lcov-report/browser/index.html +25 -10
  76. package/reports/lcov-report/cli/commands/index.html +1 -1
  77. package/reports/lcov-report/cli/commands/listCommand.ts.html +1 -1
  78. package/reports/lcov-report/cli/commands/runCommand.ts.html +1 -1
  79. package/reports/lcov-report/cli/index.html +1 -1
  80. package/reports/lcov-report/cli/index.ts.html +1 -1
  81. package/reports/lcov-report/config/index.html +1 -1
  82. package/reports/lcov-report/config/missingRequiredParamError.ts.html +1 -1
  83. package/reports/lcov-report/config/requiredEnvParams.ts.html +1 -1
  84. package/reports/lcov-report/config/runnerConfigLoader.ts.html +1 -1
  85. package/reports/lcov-report/config/runnerConfigSchema.ts.html +1 -1
  86. package/reports/lcov-report/config/sources/cliOverrideConfigSource.ts.html +1 -1
  87. package/reports/lcov-report/config/sources/configSource.ts.html +1 -1
  88. package/reports/lcov-report/config/sources/envVarConfigSource.ts.html +1 -1
  89. package/reports/lcov-report/config/sources/fileConfigSource.ts.html +1 -1
  90. package/reports/lcov-report/config/sources/index.html +1 -1
  91. package/reports/lcov-report/config/unknownEnvError.ts.html +1 -1
  92. package/reports/lcov-report/index.html +63 -33
  93. package/reports/lcov-report/registry/index.html +1 -1
  94. package/reports/lcov-report/registry/scenarioRegistry.ts.html +1 -1
  95. package/reports/lcov-report/reporting/consoleReporter.ts.html +1 -1
  96. package/reports/lcov-report/reporting/index.html +1 -1
  97. package/reports/lcov-report/reporting/junitReporter.ts.html +1 -1
  98. package/reports/lcov-report/runner/aiEnhancementStep.ts.html +1 -1
  99. package/reports/lcov-report/runner/batchRunner.ts.html +1 -1
  100. package/reports/lcov-report/runner/index.html +15 -15
  101. package/reports/lcov-report/runner/scenarioRunner.ts.html +23 -14
  102. package/reports/lcov-report/scenarios/index.html +8 -8
  103. package/reports/lcov-report/scenarios/index.ts.html +20 -14
  104. package/reports/lcov-report/scenarios/one-admin/export-navigation.scenario.ts.html +1 -1
  105. package/reports/lcov-report/scenarios/one-admin/index.html +5 -5
  106. package/reports/lcov-report/scenarios/one-admin/index.ts.html +24 -6
  107. package/reports/lcov-report/scenarios/one-admin/page-models/AdminLandingPageModel.ts.html +1 -1
  108. package/reports/lcov-report/scenarios/one-admin/page-models/ExportPageModel.ts.html +1 -1
  109. package/reports/lcov-report/scenarios/one-admin/page-models/SelectSettingsPageModel.ts.html +1 -1
  110. package/reports/lcov-report/scenarios/one-admin/page-models/index.html +1 -1
  111. package/reports/lcov-report/scenarios/pipeline/index.html +131 -0
  112. package/reports/lcov-report/scenarios/pipeline/index.ts.html +121 -0
  113. package/reports/lcov-report/scenarios/pipeline/page-models/PipelinePageModel.ts.html +223 -0
  114. package/reports/lcov-report/scenarios/pipeline/page-models/index.html +116 -0
  115. package/reports/lcov-report/scenarios/pipeline/pipeline-task-navigation.scenario.ts.html +211 -0
  116. package/reports/lcov-report/types/config.ts.html +1 -1
  117. package/reports/lcov-report/types/index.html +1 -1
  118. package/reports/lcov.info +225 -40
  119. package/reports/registry/index.html +1 -1
  120. package/reports/registry/scenarioRegistry.ts.html +1 -1
  121. package/reports/reporting/consoleReporter.ts.html +1 -1
  122. package/reports/reporting/index.html +1 -1
  123. package/reports/reporting/junitReporter.ts.html +1 -1
  124. package/reports/runner/aiEnhancementStep.ts.html +1 -1
  125. package/reports/runner/batchRunner.ts.html +1 -1
  126. package/reports/runner/index.html +15 -15
  127. package/reports/runner/scenarioRunner.ts.html +23 -14
  128. package/reports/scenarios/index.html +8 -8
  129. package/reports/scenarios/index.ts.html +20 -14
  130. package/reports/scenarios/one-admin/export-navigation.scenario.ts.html +1 -1
  131. package/reports/scenarios/one-admin/index.html +5 -5
  132. package/reports/scenarios/one-admin/index.ts.html +24 -6
  133. package/reports/scenarios/one-admin/page-models/AdminLandingPageModel.ts.html +1 -1
  134. package/reports/scenarios/one-admin/page-models/ExportPageModel.ts.html +1 -1
  135. package/reports/scenarios/one-admin/page-models/SelectSettingsPageModel.ts.html +1 -1
  136. package/reports/scenarios/one-admin/page-models/index.html +1 -1
  137. package/reports/scenarios/pipeline/index.html +131 -0
  138. package/reports/scenarios/pipeline/index.ts.html +121 -0
  139. package/reports/scenarios/pipeline/page-models/PipelinePageModel.ts.html +223 -0
  140. package/reports/scenarios/pipeline/page-models/index.html +116 -0
  141. package/reports/scenarios/pipeline/pipeline-task-navigation.scenario.ts.html +211 -0
  142. package/reports/types/config.ts.html +1 -1
  143. package/reports/types/index.html +1 -1
  144. package/test-report.xml +57 -53
@@ -0,0 +1,937 @@
1
+
2
+ <!doctype html>
3
+ <html lang="en">
4
+
5
+ <head>
6
+ <title>Code coverage report for browser/heapMemoryProfiler.ts</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">browser</a> heapMemoryProfiler.ts</h1>
23
+ <div class='clearfix'>
24
+
25
+ <div class='fl pad1y space-right2'>
26
+ <span class="strong">47.36% </span>
27
+ <span class="quiet">Statements</span>
28
+ <span class='fraction'>27/57</span>
29
+ </div>
30
+
31
+
32
+ <div class='fl pad1y space-right2'>
33
+ <span class="strong">5.55% </span>
34
+ <span class="quiet">Branches</span>
35
+ <span class='fraction'>1/18</span>
36
+ </div>
37
+
38
+
39
+ <div class='fl pad1y space-right2'>
40
+ <span class="strong">70% </span>
41
+ <span class="quiet">Functions</span>
42
+ <span class='fraction'>7/10</span>
43
+ </div>
44
+
45
+
46
+ <div class='fl pad1y space-right2'>
47
+ <span class="strong">54.16% </span>
48
+ <span class="quiet">Lines</span>
49
+ <span class='fraction'>26/48</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>
305
+ <a name='L240'></a><a href='#L240'>240</a>
306
+ <a name='L241'></a><a href='#L241'>241</a>
307
+ <a name='L242'></a><a href='#L242'>242</a>
308
+ <a name='L243'></a><a href='#L243'>243</a>
309
+ <a name='L244'></a><a href='#L244'>244</a>
310
+ <a name='L245'></a><a href='#L245'>245</a>
311
+ <a name='L246'></a><a href='#L246'>246</a>
312
+ <a name='L247'></a><a href='#L247'>247</a>
313
+ <a name='L248'></a><a href='#L248'>248</a>
314
+ <a name='L249'></a><a href='#L249'>249</a>
315
+ <a name='L250'></a><a href='#L250'>250</a>
316
+ <a name='L251'></a><a href='#L251'>251</a>
317
+ <a name='L252'></a><a href='#L252'>252</a>
318
+ <a name='L253'></a><a href='#L253'>253</a>
319
+ <a name='L254'></a><a href='#L254'>254</a>
320
+ <a name='L255'></a><a href='#L255'>255</a>
321
+ <a name='L256'></a><a href='#L256'>256</a>
322
+ <a name='L257'></a><a href='#L257'>257</a>
323
+ <a name='L258'></a><a href='#L258'>258</a>
324
+ <a name='L259'></a><a href='#L259'>259</a>
325
+ <a name='L260'></a><a href='#L260'>260</a>
326
+ <a name='L261'></a><a href='#L261'>261</a>
327
+ <a name='L262'></a><a href='#L262'>262</a>
328
+ <a name='L263'></a><a href='#L263'>263</a>
329
+ <a name='L264'></a><a href='#L264'>264</a>
330
+ <a name='L265'></a><a href='#L265'>265</a>
331
+ <a name='L266'></a><a href='#L266'>266</a>
332
+ <a name='L267'></a><a href='#L267'>267</a>
333
+ <a name='L268'></a><a href='#L268'>268</a>
334
+ <a name='L269'></a><a href='#L269'>269</a>
335
+ <a name='L270'></a><a href='#L270'>270</a>
336
+ <a name='L271'></a><a href='#L271'>271</a>
337
+ <a name='L272'></a><a href='#L272'>272</a>
338
+ <a name='L273'></a><a href='#L273'>273</a>
339
+ <a name='L274'></a><a href='#L274'>274</a>
340
+ <a name='L275'></a><a href='#L275'>275</a>
341
+ <a name='L276'></a><a href='#L276'>276</a>
342
+ <a name='L277'></a><a href='#L277'>277</a>
343
+ <a name='L278'></a><a href='#L278'>278</a>
344
+ <a name='L279'></a><a href='#L279'>279</a>
345
+ <a name='L280'></a><a href='#L280'>280</a>
346
+ <a name='L281'></a><a href='#L281'>281</a>
347
+ <a name='L282'></a><a href='#L282'>282</a>
348
+ <a name='L283'></a><a href='#L283'>283</a>
349
+ <a name='L284'></a><a href='#L284'>284</a>
350
+ <a name='L285'></a><a href='#L285'>285</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">4x</span>
351
+ <span class="cline-any cline-yes">4x</span>
352
+ <span class="cline-any cline-neutral">&nbsp;</span>
353
+ <span class="cline-any cline-yes">4x</span>
354
+ <span class="cline-any cline-neutral">&nbsp;</span>
355
+ <span class="cline-any cline-neutral">&nbsp;</span>
356
+ <span class="cline-any cline-neutral">&nbsp;</span>
357
+ <span class="cline-any cline-neutral">&nbsp;</span>
358
+ <span class="cline-any cline-neutral">&nbsp;</span>
359
+ <span class="cline-any cline-neutral">&nbsp;</span>
360
+ <span class="cline-any cline-neutral">&nbsp;</span>
361
+ <span class="cline-any cline-neutral">&nbsp;</span>
362
+ <span class="cline-any cline-neutral">&nbsp;</span>
363
+ <span class="cline-any cline-neutral">&nbsp;</span>
364
+ <span class="cline-any cline-neutral">&nbsp;</span>
365
+ <span class="cline-any cline-neutral">&nbsp;</span>
366
+ <span class="cline-any cline-neutral">&nbsp;</span>
367
+ <span class="cline-any cline-neutral">&nbsp;</span>
368
+ <span class="cline-any cline-neutral">&nbsp;</span>
369
+ <span class="cline-any cline-neutral">&nbsp;</span>
370
+ <span class="cline-any cline-neutral">&nbsp;</span>
371
+ <span class="cline-any cline-neutral">&nbsp;</span>
372
+ <span class="cline-any cline-neutral">&nbsp;</span>
373
+ <span class="cline-any cline-neutral">&nbsp;</span>
374
+ <span class="cline-any cline-neutral">&nbsp;</span>
375
+ <span class="cline-any cline-neutral">&nbsp;</span>
376
+ <span class="cline-any cline-neutral">&nbsp;</span>
377
+ <span class="cline-any cline-neutral">&nbsp;</span>
378
+ <span class="cline-any cline-neutral">&nbsp;</span>
379
+ <span class="cline-any cline-neutral">&nbsp;</span>
380
+ <span class="cline-any cline-neutral">&nbsp;</span>
381
+ <span class="cline-any cline-neutral">&nbsp;</span>
382
+ <span class="cline-any cline-neutral">&nbsp;</span>
383
+ <span class="cline-any cline-neutral">&nbsp;</span>
384
+ <span class="cline-any cline-neutral">&nbsp;</span>
385
+ <span class="cline-any cline-neutral">&nbsp;</span>
386
+ <span class="cline-any cline-neutral">&nbsp;</span>
387
+ <span class="cline-any cline-neutral">&nbsp;</span>
388
+ <span class="cline-any cline-neutral">&nbsp;</span>
389
+ <span class="cline-any cline-neutral">&nbsp;</span>
390
+ <span class="cline-any cline-neutral">&nbsp;</span>
391
+ <span class="cline-any cline-neutral">&nbsp;</span>
392
+ <span class="cline-any cline-neutral">&nbsp;</span>
393
+ <span class="cline-any cline-neutral">&nbsp;</span>
394
+ <span class="cline-any cline-neutral">&nbsp;</span>
395
+ <span class="cline-any cline-neutral">&nbsp;</span>
396
+ <span class="cline-any cline-neutral">&nbsp;</span>
397
+ <span class="cline-any cline-neutral">&nbsp;</span>
398
+ <span class="cline-any cline-neutral">&nbsp;</span>
399
+ <span class="cline-any cline-neutral">&nbsp;</span>
400
+ <span class="cline-any cline-neutral">&nbsp;</span>
401
+ <span class="cline-any cline-neutral">&nbsp;</span>
402
+ <span class="cline-any cline-neutral">&nbsp;</span>
403
+ <span class="cline-any cline-neutral">&nbsp;</span>
404
+ <span class="cline-any cline-neutral">&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-neutral">&nbsp;</span>
408
+ <span class="cline-any cline-neutral">&nbsp;</span>
409
+ <span class="cline-any cline-neutral">&nbsp;</span>
410
+ <span class="cline-any cline-neutral">&nbsp;</span>
411
+ <span class="cline-any cline-neutral">&nbsp;</span>
412
+ <span class="cline-any cline-neutral">&nbsp;</span>
413
+ <span class="cline-any cline-neutral">&nbsp;</span>
414
+ <span class="cline-any cline-neutral">&nbsp;</span>
415
+ <span class="cline-any cline-neutral">&nbsp;</span>
416
+ <span class="cline-any cline-neutral">&nbsp;</span>
417
+ <span class="cline-any cline-neutral">&nbsp;</span>
418
+ <span class="cline-any cline-neutral">&nbsp;</span>
419
+ <span class="cline-any cline-neutral">&nbsp;</span>
420
+ <span class="cline-any cline-neutral">&nbsp;</span>
421
+ <span class="cline-any cline-neutral">&nbsp;</span>
422
+ <span class="cline-any cline-neutral">&nbsp;</span>
423
+ <span class="cline-any cline-neutral">&nbsp;</span>
424
+ <span class="cline-any cline-neutral">&nbsp;</span>
425
+ <span class="cline-any cline-neutral">&nbsp;</span>
426
+ <span class="cline-any cline-neutral">&nbsp;</span>
427
+ <span class="cline-any cline-neutral">&nbsp;</span>
428
+ <span class="cline-any cline-neutral">&nbsp;</span>
429
+ <span class="cline-any cline-neutral">&nbsp;</span>
430
+ <span class="cline-any cline-neutral">&nbsp;</span>
431
+ <span class="cline-any cline-neutral">&nbsp;</span>
432
+ <span class="cline-any cline-neutral">&nbsp;</span>
433
+ <span class="cline-any cline-neutral">&nbsp;</span>
434
+ <span class="cline-any cline-neutral">&nbsp;</span>
435
+ <span class="cline-any cline-neutral">&nbsp;</span>
436
+ <span class="cline-any cline-neutral">&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-neutral">&nbsp;</span>
440
+ <span class="cline-any cline-neutral">&nbsp;</span>
441
+ <span class="cline-any cline-neutral">&nbsp;</span>
442
+ <span class="cline-any cline-neutral">&nbsp;</span>
443
+ <span class="cline-any cline-neutral">&nbsp;</span>
444
+ <span class="cline-any cline-neutral">&nbsp;</span>
445
+ <span class="cline-any cline-neutral">&nbsp;</span>
446
+ <span class="cline-any cline-neutral">&nbsp;</span>
447
+ <span class="cline-any cline-neutral">&nbsp;</span>
448
+ <span class="cline-any cline-neutral">&nbsp;</span>
449
+ <span class="cline-any cline-neutral">&nbsp;</span>
450
+ <span class="cline-any cline-neutral">&nbsp;</span>
451
+ <span class="cline-any cline-neutral">&nbsp;</span>
452
+ <span class="cline-any cline-yes">8x</span>
453
+ <span class="cline-any cline-neutral">&nbsp;</span>
454
+ <span class="cline-any cline-yes">7x</span>
455
+ <span class="cline-any cline-neutral">&nbsp;</span>
456
+ <span class="cline-any cline-neutral">&nbsp;</span>
457
+ <span class="cline-any cline-neutral">&nbsp;</span>
458
+ <span class="cline-any cline-neutral">&nbsp;</span>
459
+ <span class="cline-any cline-neutral">&nbsp;</span>
460
+ <span class="cline-any cline-neutral">&nbsp;</span>
461
+ <span class="cline-any cline-neutral">&nbsp;</span>
462
+ <span class="cline-any cline-yes">7x</span>
463
+ <span class="cline-any cline-yes">7x</span>
464
+ <span class="cline-any cline-neutral">&nbsp;</span>
465
+ <span class="cline-any cline-neutral">&nbsp;</span>
466
+ <span class="cline-any cline-neutral">&nbsp;</span>
467
+ <span class="cline-any cline-yes">1x</span>
468
+ <span class="cline-any cline-neutral">&nbsp;</span>
469
+ <span class="cline-any cline-neutral">&nbsp;</span>
470
+ <span class="cline-any cline-neutral">&nbsp;</span>
471
+ <span class="cline-any cline-neutral">&nbsp;</span>
472
+ <span class="cline-any cline-neutral">&nbsp;</span>
473
+ <span class="cline-any cline-yes">1x</span>
474
+ <span class="cline-any cline-neutral">&nbsp;</span>
475
+ <span class="cline-any cline-neutral">&nbsp;</span>
476
+ <span class="cline-any cline-neutral">&nbsp;</span>
477
+ <span class="cline-any cline-neutral">&nbsp;</span>
478
+ <span class="cline-any cline-neutral">&nbsp;</span>
479
+ <span class="cline-any cline-neutral">&nbsp;</span>
480
+ <span class="cline-any cline-neutral">&nbsp;</span>
481
+ <span class="cline-any cline-neutral">&nbsp;</span>
482
+ <span class="cline-any cline-neutral">&nbsp;</span>
483
+ <span class="cline-any cline-neutral">&nbsp;</span>
484
+ <span class="cline-any cline-neutral">&nbsp;</span>
485
+ <span class="cline-any cline-neutral">&nbsp;</span>
486
+ <span class="cline-any cline-neutral">&nbsp;</span>
487
+ <span class="cline-any cline-neutral">&nbsp;</span>
488
+ <span class="cline-any cline-neutral">&nbsp;</span>
489
+ <span class="cline-any cline-yes">1x</span>
490
+ <span class="cline-any cline-neutral">&nbsp;</span>
491
+ <span class="cline-any cline-yes">1x</span>
492
+ <span class="cline-any cline-yes">1x</span>
493
+ <span class="cline-any cline-neutral">&nbsp;</span>
494
+ <span class="cline-any cline-yes">1x</span>
495
+ <span class="cline-any cline-yes">1x</span>
496
+ <span class="cline-any cline-neutral">&nbsp;</span>
497
+ <span class="cline-any cline-neutral">&nbsp;</span>
498
+ <span class="cline-any cline-neutral">&nbsp;</span>
499
+ <span class="cline-any cline-yes">1x</span>
500
+ <span class="cline-any cline-neutral">&nbsp;</span>
501
+ <span class="cline-any cline-yes">1x</span>
502
+ <span class="cline-any cline-neutral">&nbsp;</span>
503
+ <span class="cline-any cline-neutral">&nbsp;</span>
504
+ <span class="cline-any cline-yes">1x</span>
505
+ <span class="cline-any cline-neutral">&nbsp;</span>
506
+ <span class="cline-any cline-neutral">&nbsp;</span>
507
+ <span class="cline-any cline-neutral">&nbsp;</span>
508
+ <span class="cline-any cline-yes">1x</span>
509
+ <span class="cline-any cline-neutral">&nbsp;</span>
510
+ <span class="cline-any cline-neutral">&nbsp;</span>
511
+ <span class="cline-any cline-yes">1x</span>
512
+ <span class="cline-any cline-yes">1x</span>
513
+ <span class="cline-any cline-neutral">&nbsp;</span>
514
+ <span class="cline-any cline-yes">1x</span>
515
+ <span class="cline-any cline-yes">1x</span>
516
+ <span class="cline-any cline-yes">1x</span>
517
+ <span class="cline-any cline-yes">1x</span>
518
+ <span class="cline-any cline-neutral">&nbsp;</span>
519
+ <span class="cline-any cline-neutral">&nbsp;</span>
520
+ <span class="cline-any cline-neutral">&nbsp;</span>
521
+ <span class="cline-any cline-yes">1x</span>
522
+ <span class="cline-any cline-yes">1x</span>
523
+ <span class="cline-any cline-neutral">&nbsp;</span>
524
+ <span class="cline-any cline-neutral">&nbsp;</span>
525
+ <span class="cline-any cline-neutral">&nbsp;</span>
526
+ <span class="cline-any cline-neutral">&nbsp;</span>
527
+ <span class="cline-any cline-neutral">&nbsp;</span>
528
+ <span class="cline-any cline-neutral">&nbsp;</span>
529
+ <span class="cline-any cline-neutral">&nbsp;</span>
530
+ <span class="cline-any cline-neutral">&nbsp;</span>
531
+ <span class="cline-any cline-neutral">&nbsp;</span>
532
+ <span class="cline-any cline-neutral">&nbsp;</span>
533
+ <span class="cline-any cline-neutral">&nbsp;</span>
534
+ <span class="cline-any cline-neutral">&nbsp;</span>
535
+ <span class="cline-any cline-neutral">&nbsp;</span>
536
+ <span class="cline-any cline-no">&nbsp;</span>
537
+ <span class="cline-any cline-no">&nbsp;</span>
538
+ <span class="cline-any cline-neutral">&nbsp;</span>
539
+ <span class="cline-any cline-no">&nbsp;</span>
540
+ <span class="cline-any cline-no">&nbsp;</span>
541
+ <span class="cline-any cline-neutral">&nbsp;</span>
542
+ <span class="cline-any cline-no">&nbsp;</span>
543
+ <span class="cline-any cline-no">&nbsp;</span>
544
+ <span class="cline-any cline-neutral">&nbsp;</span>
545
+ <span class="cline-any cline-neutral">&nbsp;</span>
546
+ <span class="cline-any cline-neutral">&nbsp;</span>
547
+ <span class="cline-any cline-neutral">&nbsp;</span>
548
+ <span class="cline-any cline-neutral">&nbsp;</span>
549
+ <span class="cline-any cline-no">&nbsp;</span>
550
+ <span class="cline-any cline-neutral">&nbsp;</span>
551
+ <span class="cline-any cline-neutral">&nbsp;</span>
552
+ <span class="cline-any cline-neutral">&nbsp;</span>
553
+ <span class="cline-any cline-no">&nbsp;</span>
554
+ <span class="cline-any cline-neutral">&nbsp;</span>
555
+ <span class="cline-any cline-no">&nbsp;</span>
556
+ <span class="cline-any cline-neutral">&nbsp;</span>
557
+ <span class="cline-any cline-neutral">&nbsp;</span>
558
+ <span class="cline-any cline-neutral">&nbsp;</span>
559
+ <span class="cline-any cline-neutral">&nbsp;</span>
560
+ <span class="cline-any cline-no">&nbsp;</span>
561
+ <span class="cline-any cline-neutral">&nbsp;</span>
562
+ <span class="cline-any cline-neutral">&nbsp;</span>
563
+ <span class="cline-any cline-neutral">&nbsp;</span>
564
+ <span class="cline-any cline-neutral">&nbsp;</span>
565
+ <span class="cline-any cline-neutral">&nbsp;</span>
566
+ <span class="cline-any cline-neutral">&nbsp;</span>
567
+ <span class="cline-any cline-neutral">&nbsp;</span>
568
+ <span class="cline-any cline-neutral">&nbsp;</span>
569
+ <span class="cline-any cline-neutral">&nbsp;</span>
570
+ <span class="cline-any cline-neutral">&nbsp;</span>
571
+ <span class="cline-any cline-neutral">&nbsp;</span>
572
+ <span class="cline-any cline-neutral">&nbsp;</span>
573
+ <span class="cline-any cline-neutral">&nbsp;</span>
574
+ <span class="cline-any cline-neutral">&nbsp;</span>
575
+ <span class="cline-any cline-neutral">&nbsp;</span>
576
+ <span class="cline-any cline-neutral">&nbsp;</span>
577
+ <span class="cline-any cline-neutral">&nbsp;</span>
578
+ <span class="cline-any cline-neutral">&nbsp;</span>
579
+ <span class="cline-any cline-neutral">&nbsp;</span>
580
+ <span class="cline-any cline-neutral">&nbsp;</span>
581
+ <span class="cline-any cline-neutral">&nbsp;</span>
582
+ <span class="cline-any cline-neutral">&nbsp;</span>
583
+ <span class="cline-any cline-neutral">&nbsp;</span>
584
+ <span class="cline-any cline-neutral">&nbsp;</span>
585
+ <span class="cline-any cline-neutral">&nbsp;</span>
586
+ <span class="cline-any cline-neutral">&nbsp;</span>
587
+ <span class="cline-any cline-neutral">&nbsp;</span>
588
+ <span class="cline-any cline-neutral">&nbsp;</span>
589
+ <span class="cline-any cline-neutral">&nbsp;</span>
590
+ <span class="cline-any cline-no">&nbsp;</span>
591
+ <span class="cline-any cline-neutral">&nbsp;</span>
592
+ <span class="cline-any cline-no">&nbsp;</span>
593
+ <span class="cline-any cline-neutral">&nbsp;</span>
594
+ <span class="cline-any cline-no">&nbsp;</span>
595
+ <span class="cline-any cline-no">&nbsp;</span>
596
+ <span class="cline-any cline-neutral">&nbsp;</span>
597
+ <span class="cline-any cline-neutral">&nbsp;</span>
598
+ <span class="cline-any cline-no">&nbsp;</span>
599
+ <span class="cline-any cline-neutral">&nbsp;</span>
600
+ <span class="cline-any cline-no">&nbsp;</span>
601
+ <span class="cline-any cline-no">&nbsp;</span>
602
+ <span class="cline-any cline-neutral">&nbsp;</span>
603
+ <span class="cline-any cline-no">&nbsp;</span>
604
+ <span class="cline-any cline-neutral">&nbsp;</span>
605
+ <span class="cline-any cline-neutral">&nbsp;</span>
606
+ <span class="cline-any cline-neutral">&nbsp;</span>
607
+ <span class="cline-any cline-neutral">&nbsp;</span>
608
+ <span class="cline-any cline-neutral">&nbsp;</span>
609
+ <span class="cline-any cline-neutral">&nbsp;</span>
610
+ <span class="cline-any cline-no">&nbsp;</span>
611
+ <span class="cline-any cline-neutral">&nbsp;</span>
612
+ <span class="cline-any cline-neutral">&nbsp;</span>
613
+ <span class="cline-any cline-neutral">&nbsp;</span>
614
+ <span class="cline-any cline-neutral">&nbsp;</span>
615
+ <span class="cline-any cline-no">&nbsp;</span>
616
+ <span class="cline-any cline-neutral">&nbsp;</span>
617
+ <span class="cline-any cline-neutral">&nbsp;</span>
618
+ <span class="cline-any cline-neutral">&nbsp;</span>
619
+ <span class="cline-any cline-neutral">&nbsp;</span>
620
+ <span class="cline-any cline-neutral">&nbsp;</span>
621
+ <span class="cline-any cline-neutral">&nbsp;</span>
622
+ <span class="cline-any cline-neutral">&nbsp;</span>
623
+ <span class="cline-any cline-no">&nbsp;</span>
624
+ <span class="cline-any cline-neutral">&nbsp;</span>
625
+ <span class="cline-any cline-neutral">&nbsp;</span>
626
+ <span class="cline-any cline-neutral">&nbsp;</span>
627
+ <span class="cline-any cline-neutral">&nbsp;</span>
628
+ <span class="cline-any cline-neutral">&nbsp;</span>
629
+ <span class="cline-any cline-neutral">&nbsp;</span>
630
+ <span class="cline-any cline-neutral">&nbsp;</span>
631
+ <span class="cline-any cline-no">&nbsp;</span>
632
+ <span class="cline-any cline-neutral">&nbsp;</span>
633
+ <span class="cline-any cline-neutral">&nbsp;</span>
634
+ <span class="cline-any cline-neutral">&nbsp;</span></td><td class="text"><pre class="prettyprint lang-js">import fs from 'node:fs';
635
+ import path from 'node:path';
636
+ import type { Page, Frame } from '@playwright/test';
637
+ import { HeapDoctor } from '@elliemae/encw-heap-doctor';
638
+ import type { ComparisonReport } from '@elliemae/encw-heap-doctor';
639
+ &nbsp;
640
+ export interface HeapProfilingOptions {
641
+ /**
642
+ * Number of times to execute the flow between the before and after snapshots.
643
+ * More iterations amplify the leak signal — a leak of N bytes per run becomes
644
+ * N × heapIterations in the delta, making small leaks detectable above GC noise.
645
+ * Default: 1.
646
+ */
647
+ heapIterations?: number;
648
+ &nbsp;
649
+ /**
650
+ * Label prefix used in snapshot filenames and as the Memento key.
651
+ * Two files are written: `&lt;label&gt;-before-&lt;epoch&gt;.heapsnapshot` and
652
+ * `&lt;label&gt;-after-&lt;epoch&gt;.heapsnapshot`.
653
+ * Default: 'flow'.
654
+ */
655
+ label?: string;
656
+ &nbsp;
657
+ /**
658
+ * Number of top leak groups to include in the HeapDoctor report.
659
+ * Default: 5 (HeapDoctor default).
660
+ */
661
+ topN?: number;
662
+ &nbsp;
663
+ /**
664
+ * When `true`, throws after comparison if `retainedSizeDelta` exceeds
665
+ * {@link leakThresholdBytes}, causing the Playwright test to fail.
666
+ * Default: false.
667
+ */
668
+ failOnLeak?: boolean;
669
+ &nbsp;
670
+ /**
671
+ * Retained-size growth in bytes above which the test is failed when
672
+ * {@link failOnLeak} is `true`. Set to 0 to fail on any positive delta.
673
+ * Default: 0.
674
+ */
675
+ leakThresholdBytes?: number;
676
+ &nbsp;
677
+ /**
678
+ * Optional allow-list of `Window` origins (e.g. `'https://encompass.q3.ice.com'`).
679
+ *
680
+ * Forwarded to `HeapDoctor`; suppresses retainer chains rooted in unrelated
681
+ * same-site iframes (e.g. partner plugins) that share the main V8 isolate.
682
+ * Chains with no `Window` step are always kept.
683
+ */
684
+ originAllowList?: readonly string[];
685
+ }
686
+ &nbsp;
687
+ /** Parameters for {@link HeapMemoryProfiler.compare}. */
688
+ export interface CompareParams {
689
+ /** Label passed to `captureSnapshot()` for the baseline. */
690
+ beforeLabel: string;
691
+ /** Label passed to `captureSnapshot()` for the post-flow snapshot. */
692
+ afterLabel: string;
693
+ /** Override for the number of top leak groups in the report. */
694
+ topN?: number;
695
+ /** Allow-list of `Window` origins; forwarded to `HeapDoctor`. */
696
+ originAllowList?: readonly string[];
697
+ }
698
+ &nbsp;
699
+ /**
700
+ * Encapsulates heap memory profiling for a single Playwright test.
701
+ *
702
+ * **Responsibilities:**
703
+ * - CDP session lifecycle (open, stream chunks, detach)
704
+ * - `.heapsnapshot` file I/O
705
+ * - Snapshot label cache (Memento store, cleared per test)
706
+ * - HeapDoctor comparison and markdown report writing
707
+ * - Optional test failure on leak threshold breach
708
+ *
709
+ * **Usage:**
710
+ * ```ts
711
+ * class MySpec extends AdminBaseTest {
712
+ * private heapProfiler!: HeapMemoryProfiler;
713
+ *
714
+ * async beforeEach() {
715
+ * await super.beforeEach();
716
+ * this.heapProfiler = new HeapMemoryProfiler(this.page, 'reports/heap-snapshots/my-spec');
717
+ * }
718
+ *
719
+ * async afterEach() {
720
+ * this.heapProfiler.clearSnapshots();
721
+ * await super.afterEach();
722
+ * }
723
+ *
724
+ * async testFlow_Memory() {
725
+ * await this.goto('some.route');
726
+ * await this.heapProfiler.withProfiling(async () =&gt; {
727
+ * await this.somePage.doSomething();
728
+ * }, { heapIterations: 3, label: 'my-flow', failOnLeak: true, leakThresholdBytes: 500_000 });
729
+ * }
730
+ * }
731
+ * ```
732
+ *
733
+ * **Non-Chromium:** All methods silently no-op and return `null` / empty string.
734
+ * The flow inside `withProfiling` still executes normally.
735
+ */
736
+ export class HeapMemoryProfiler {
737
+ /** Memento store: maps snapshot label → absolute file path on disk. */
738
+ private readonly snapshots = new Map&lt;string, string&gt;();
739
+ &nbsp;
740
+ /**
741
+ * @param {Page} page - The Playwright `Page` instance for the current test.
742
+ * @param {string} outputDir - Directory where `.heapsnapshot` and `.md` files are written.
743
+ * Created automatically if it does not exist.
744
+ */
745
+ constructor(
746
+ private readonly page: Page,
747
+ private readonly outputDir: string,
748
+ ) {}
749
+ &nbsp;
750
+ protected getCDPTarget(): Page | Frame {
751
+ return this.page;
752
+ }
753
+ &nbsp;
754
+ // ─── Browser guard ──────────────────────────────────────────────────────────
755
+ &nbsp;
756
+ private isChromium(): boolean {
757
+ return this.page.context().browser()?.browserType().name() === 'chromium';
758
+ }
759
+ &nbsp;
760
+ // ─── Public API ─────────────────────────────────────────────────────────────
761
+ &nbsp;
762
+ /**
763
+ * Capture a Chrome heap snapshot via CDP and persist it to disk.
764
+ *
765
+ * The snapshot is streamed in chunks via `HeapProfiler.addHeapSnapshotChunk`,
766
+ * joined, and written as a single `.heapsnapshot` file. The file path is cached
767
+ * internally under `label` so {@link compare} can resolve it by name.
768
+ * @param {string} label - Logical name for this snapshot (e.g. `'before'`, `'after'`).
769
+ * Used as the filename prefix and as the Memento key.
770
+ * @returns {Promise&lt;string&gt;} Absolute path to the written file, or `''` on non-Chromium browsers.
771
+ */
772
+ async captureSnapshot(label: string): Promise&lt;string&gt; {
773
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (!this.isChromium()) <span class="cstat-no" title="statement not covered" >return '';</span>
774
+ &nbsp;
775
+ const client = await this.page.context().newCDPSession(this.getCDPTarget());
776
+ await client.send('HeapProfiler.enable');
777
+ &nbsp;
778
+ fs.mkdirSync(this.outputDir, { recursive: true });
779
+ const filePath = path.join(
780
+ this.outputDir,
781
+ `${label}-${Date.now()}.heapsnapshot`,
782
+ );
783
+ const writeStream = fs.createWriteStream(filePath);
784
+ &nbsp;
785
+ client.on(
786
+ 'HeapProfiler.addHeapSnapshotChunk',
787
+ ({ chunk }: { chunk: string }) =&gt; {
788
+ writeStream.write(chunk);
789
+ },
790
+ );
791
+ &nbsp;
792
+ await client.send('HeapProfiler.takeHeapSnapshot', {
793
+ reportProgress: false,
794
+ });
795
+ await client.send('HeapProfiler.disable');
796
+ await client.detach();
797
+ &nbsp;
798
+ await new Promise&lt;void&gt;((resolve, reject) =&gt; {
799
+ writeStream.end((err?: Error | null) =&gt; {
800
+ <span class="missing-if-branch" title="if path not taken" >I</span>if (err) <span class="cstat-no" title="statement not covered" >reject(err);</span>
801
+ else resolve();
802
+ });
803
+ });
804
+ &nbsp;
805
+ this.snapshots.set(label, filePath);
806
+ return filePath;
807
+ }
808
+ &nbsp;
809
+ /**
810
+ * Compare two previously captured snapshots by their labels.
811
+ *
812
+ * Runs `HeapDoctor.compare()` on the resolved file paths and writes a
813
+ * markdown report to {@link outputDir}.
814
+ * @param {CompareParams} params - {@link CompareParams}
815
+ * @returns {Promise&lt;ComparisonReport | null&gt;} `ComparisonReport`, or `null` on non-Chromium browsers.
816
+ * @throws If either label has no cached snapshot path.
817
+ * @throws If `HeapDoctor.compare` returns `ok: false`.
818
+ */
819
+ <span class="fstat-no" title="function not covered" > async c</span>ompare(params: CompareParams): Promise&lt;ComparisonReport | null&gt; {
820
+ const { beforeLabel, afterLabel, topN, originAllowList } = <span class="cstat-no" title="statement not covered" >params;</span>
821
+ <span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (!this.isChromium()) <span class="cstat-no" title="statement not covered" >return null;</span></span>
822
+ &nbsp;
823
+ const before = <span class="cstat-no" title="statement not covered" >this.snapshots.get(beforeLabel);</span>
824
+ const after = <span class="cstat-no" title="statement not covered" >this.snapshots.get(afterLabel);</span>
825
+ &nbsp;
826
+ <span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (!before || !after) {</span>
827
+ <span class="cstat-no" title="statement not covered" > throw new Error(</span>
828
+ `HeapMemoryProfiler: snapshot not found for labels "${beforeLabel}" / "${afterLabel}". ` +
829
+ `Call captureSnapshot() before compare().`,
830
+ );
831
+ }
832
+ &nbsp;
833
+ const result = <span class="cstat-no" title="statement not covered" >await new HeapDoctor({ topN, originAllowList }).compare(</span>
834
+ before,
835
+ after,
836
+ );
837
+ <span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (!result.ok) <span class="cstat-no" title="statement not covered" >throw result.error;</span></span>
838
+ &nbsp;
839
+ <span class="cstat-no" title="statement not covered" > fs.writeFileSync(</span>
840
+ path.join(this.outputDir, `comparison-${Date.now()}.md`),
841
+ result.value.markdown,
842
+ );
843
+ &nbsp;
844
+ <span class="cstat-no" title="statement not covered" > return result.value;</span>
845
+ }
846
+ &nbsp;
847
+ /**
848
+ * Orchestrate the full heap profiling sequence for a user flow.
849
+ *
850
+ * Sequence (Template Method):
851
+ * 1. Capture **before** snapshot
852
+ * 2. Execute `flow` exactly `heapIterations` times
853
+ * 3. Capture **after** snapshot
854
+ * 4. Run `HeapDoctor.compare` and write the markdown report
855
+ * 5. If `failOnLeak` is `true` and `retainedSizeDelta &gt; leakThresholdBytes`, throw
856
+ *
857
+ * On non-Chromium browsers: `flow` still runs `heapIterations` times,
858
+ * no snapshots are taken, and `null` is returned.
859
+ * @param {() =&gt; Promise&lt;void&gt;} flow - Async function containing the user actions to profile.
860
+ * @param {HeapProfilingOptions} [options] - {@link HeapProfilingOptions}
861
+ * @returns {Promise&lt;ComparisonReport | null&gt;} `ComparisonReport` on Chromium, `null` on all other browsers.
862
+ */
863
+ <span class="fstat-no" title="function not covered" > async w</span>ithProfiling(
864
+ flow: () =&gt; Promise&lt;void&gt;,
865
+ options: HeapProfilingOptions = <span class="branch-0 cbranch-no" title="branch not covered" >{},</span>
866
+ ): Promise&lt;ComparisonReport | null&gt; {
867
+ const {
868
+ heapIterations = <span class="branch-0 cbranch-no" title="branch not covered" >1,</span>
869
+ label = <span class="branch-0 cbranch-no" title="branch not covered" >'flow',</span>
870
+ topN,
871
+ failOnLeak = <span class="branch-0 cbranch-no" title="branch not covered" >false,</span>
872
+ leakThresholdBytes = <span class="branch-0 cbranch-no" title="branch not covered" >0,</span>
873
+ originAllowList,
874
+ } = <span class="cstat-no" title="statement not covered" >options;</span>
875
+ &nbsp;
876
+ <span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (!this.isChromium()) {</span>
877
+ // eslint-disable-next-line no-await-in-loop
878
+ <span class="cstat-no" title="statement not covered" > for (let i = <span class="cstat-no" title="statement not covered" >0; i</span> &lt; heapIterations; i += 1) <span class="cstat-no" title="statement not covered" >await flow();</span></span>
879
+ <span class="cstat-no" title="statement not covered" > return null;</span>
880
+ }
881
+ &nbsp;
882
+ <span class="cstat-no" title="statement not covered" > await this.captureSnapshot(`${label}-before`);</span>
883
+ // eslint-disable-next-line no-await-in-loop
884
+ <span class="cstat-no" title="statement not covered" > for (let i = <span class="cstat-no" title="statement not covered" >0; i</span> &lt; heapIterations; i += 1) <span class="cstat-no" title="statement not covered" >await flow();</span></span>
885
+ <span class="cstat-no" title="statement not covered" > await this.captureSnapshot(`${label}-after`);</span>
886
+ &nbsp;
887
+ const report = <span class="cstat-no" title="statement not covered" >await this.compare({</span>
888
+ beforeLabel: `${label}-before`,
889
+ afterLabel: `${label}-after`,
890
+ topN,
891
+ originAllowList,
892
+ });
893
+ &nbsp;
894
+ <span class="cstat-no" title="statement not covered" > <span class="missing-if-branch" title="if path not taken" >I</span>if (</span>
895
+ report &amp;&amp;
896
+ failOnLeak &amp;&amp;
897
+ report.delta.retainedSizeDelta &gt; leakThresholdBytes
898
+ ) {
899
+ <span class="cstat-no" title="statement not covered" > throw new Error(</span>
900
+ `Memory leak detected: retained size grew by ${report.delta.retainedSizeDelta} bytes ` +
901
+ `(threshold: ${leakThresholdBytes} bytes). ` +
902
+ `New leak groups: ${report.delta.newLeakGroups.length}. ` +
903
+ `See: ${this.outputDir}`,
904
+ );
905
+ }
906
+ &nbsp;
907
+ <span class="cstat-no" title="statement not covered" > return report;</span>
908
+ }
909
+ &nbsp;
910
+ /**
911
+ * Clear the internal snapshot label cache.
912
+ * Call in `afterEach` to prevent snapshot paths bleeding across tests.
913
+ */
914
+ <span class="fstat-no" title="function not covered" > clearSnapshots(): void {</span>
915
+ <span class="cstat-no" title="statement not covered" > this.snapshots.clear();</span>
916
+ }
917
+ }
918
+ &nbsp;</pre></td></tr></table></pre>
919
+
920
+ <div class='push'></div><!-- for sticky footer -->
921
+ </div><!-- /wrapper -->
922
+ <div class='footer quiet pad2 space-top1 center small'>
923
+ Code coverage generated by
924
+ <a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
925
+ at 2026-05-21T15:52:17.110Z
926
+ </div>
927
+ <script src="../prettify.js"></script>
928
+ <script>
929
+ window.onload = function () {
930
+ prettyPrint();
931
+ };
932
+ </script>
933
+ <script src="../sorter.js"></script>
934
+ <script src="../block-navigation.js"></script>
935
+ </body>
936
+ </html>
937
+