browser-debugger-cli 0.6.1 → 0.6.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 (334) hide show
  1. package/README.md +64 -3
  2. package/dist/__tests__/smoke/error-handling.smoke.test.js +9 -4
  3. package/dist/__tests__/smoke/error-handling.smoke.test.js.map +1 -1
  4. package/dist/__tests__/smoke/session-lifecycle.smoke.test.js +27 -24
  5. package/dist/__tests__/smoke/session-lifecycle.smoke.test.js.map +1 -1
  6. package/dist/__testutils__/daemonHelpers.d.ts +13 -1
  7. package/dist/__testutils__/daemonHelpers.d.ts.map +1 -1
  8. package/dist/__testutils__/daemonHelpers.js +54 -5
  9. package/dist/__testutils__/daemonHelpers.js.map +1 -1
  10. package/dist/cdp/protocol.d.ts.map +1 -1
  11. package/dist/cdp/protocol.js +6 -10
  12. package/dist/cdp/protocol.js.map +1 -1
  13. package/dist/cdp/schema.d.ts.map +1 -1
  14. package/dist/cdp/schema.js +0 -2
  15. package/dist/cdp/schema.js.map +1 -1
  16. package/dist/commands/cdp.d.ts.map +1 -1
  17. package/dist/commands/cdp.js +1 -20
  18. package/dist/commands/cdp.js.map +1 -1
  19. package/dist/commands/cleanup.d.ts.map +1 -1
  20. package/dist/commands/cleanup.js +17 -15
  21. package/dist/commands/cleanup.js.map +1 -1
  22. package/dist/commands/console.d.ts.map +1 -1
  23. package/dist/commands/console.js +0 -5
  24. package/dist/commands/console.js.map +1 -1
  25. package/dist/commands/details.d.ts.map +1 -1
  26. package/dist/commands/details.js +0 -5
  27. package/dist/commands/details.js.map +1 -1
  28. package/dist/commands/dom/a11y.d.ts +18 -0
  29. package/dist/commands/dom/a11y.d.ts.map +1 -0
  30. package/dist/commands/dom/a11y.js +134 -0
  31. package/dist/commands/dom/a11y.js.map +1 -0
  32. package/dist/commands/dom/evalHelpers.d.ts.map +1 -1
  33. package/dist/commands/dom/evalHelpers.js +1 -6
  34. package/dist/commands/dom/evalHelpers.js.map +1 -1
  35. package/dist/commands/dom/formFillHelpers.d.ts.map +1 -1
  36. package/dist/commands/dom/formFillHelpers.js +0 -9
  37. package/dist/commands/dom/formFillHelpers.js.map +1 -1
  38. package/dist/commands/dom/formInteraction.d.ts.map +1 -1
  39. package/dist/commands/dom/formInteraction.js +0 -5
  40. package/dist/commands/dom/formInteraction.js.map +1 -1
  41. package/dist/commands/dom/formSubmitHelpers.d.ts.map +1 -1
  42. package/dist/commands/dom/formSubmitHelpers.js +0 -13
  43. package/dist/commands/dom/formSubmitHelpers.js.map +1 -1
  44. package/dist/commands/dom/helpers.d.ts.map +1 -1
  45. package/dist/commands/dom/helpers.js +0 -22
  46. package/dist/commands/dom/helpers.js.map +1 -1
  47. package/dist/commands/dom/index.d.ts.map +1 -1
  48. package/dist/commands/dom/index.js +41 -26
  49. package/dist/commands/dom/index.js.map +1 -1
  50. package/dist/commands/dom/reactEventHelpers.d.ts +3 -3
  51. package/dist/commands/dom/reactEventHelpers.d.ts.map +1 -1
  52. package/dist/commands/dom/reactEventHelpers.js +0 -28
  53. package/dist/commands/dom/reactEventHelpers.js.map +1 -1
  54. package/dist/commands/network.d.ts.map +1 -1
  55. package/dist/commands/network.js +159 -10
  56. package/dist/commands/network.js.map +1 -1
  57. package/dist/commands/peek.d.ts.map +1 -1
  58. package/dist/commands/peek.js +17 -12
  59. package/dist/commands/peek.js.map +1 -1
  60. package/dist/commands/shared/CommandRunner.d.ts.map +1 -1
  61. package/dist/commands/shared/CommandRunner.js +0 -8
  62. package/dist/commands/shared/CommandRunner.js.map +1 -1
  63. package/dist/commands/shared/__tests__/validation.unit.test.d.ts +7 -0
  64. package/dist/commands/shared/__tests__/validation.unit.test.d.ts.map +1 -0
  65. package/dist/commands/shared/__tests__/validation.unit.test.js +141 -0
  66. package/dist/commands/shared/__tests__/validation.unit.test.js.map +1 -0
  67. package/dist/commands/shared/startHelpers.d.ts.map +1 -1
  68. package/dist/commands/shared/startHelpers.js +0 -10
  69. package/dist/commands/shared/startHelpers.js.map +1 -1
  70. package/dist/commands/shared/validation.d.ts +17 -0
  71. package/dist/commands/shared/validation.d.ts.map +1 -1
  72. package/dist/commands/shared/validation.js +105 -5
  73. package/dist/commands/shared/validation.js.map +1 -1
  74. package/dist/commands/start.d.ts.map +1 -1
  75. package/dist/commands/start.js +0 -6
  76. package/dist/commands/start.js.map +1 -1
  77. package/dist/commands/status.d.ts.map +1 -1
  78. package/dist/commands/status.js +0 -2
  79. package/dist/commands/status.js.map +1 -1
  80. package/dist/commands/stop.d.ts.map +1 -1
  81. package/dist/commands/stop.js +11 -13
  82. package/dist/commands/stop.js.map +1 -1
  83. package/dist/commands/tail.d.ts.map +1 -1
  84. package/dist/commands/tail.js +0 -7
  85. package/dist/commands/tail.js.map +1 -1
  86. package/dist/commands/types.d.ts +3 -0
  87. package/dist/commands/types.d.ts.map +1 -1
  88. package/dist/commands.d.ts.map +1 -1
  89. package/dist/commands.js +0 -5
  90. package/dist/commands.js.map +1 -1
  91. package/dist/connection/cdp.d.ts.map +1 -1
  92. package/dist/connection/cdp.js +0 -3
  93. package/dist/connection/cdp.js.map +1 -1
  94. package/dist/connection/diagnostics.d.ts.map +1 -1
  95. package/dist/connection/diagnostics.js +7 -4
  96. package/dist/connection/diagnostics.js.map +1 -1
  97. package/dist/connection/pageReadiness.d.ts.map +1 -1
  98. package/dist/connection/pageReadiness.js +0 -1
  99. package/dist/connection/pageReadiness.js.map +1 -1
  100. package/dist/constants.d.ts +6 -0
  101. package/dist/constants.d.ts.map +1 -1
  102. package/dist/constants.js +6 -0
  103. package/dist/constants.js.map +1 -1
  104. package/dist/daemon/__tests__/commandRegistry.contract.test.js +259 -0
  105. package/dist/daemon/__tests__/commandRegistry.contract.test.js.map +1 -1
  106. package/dist/daemon/__tests__/ipcServer.cleanup.unit.test.d.ts +19 -0
  107. package/dist/daemon/__tests__/ipcServer.cleanup.unit.test.d.ts.map +1 -0
  108. package/dist/daemon/__tests__/ipcServer.cleanup.unit.test.js +212 -0
  109. package/dist/daemon/__tests__/ipcServer.cleanup.unit.test.js.map +1 -0
  110. package/dist/daemon/handlers/BaseHandler.d.ts +75 -0
  111. package/dist/daemon/handlers/BaseHandler.d.ts.map +1 -0
  112. package/dist/daemon/handlers/BaseHandler.js +103 -0
  113. package/dist/daemon/handlers/BaseHandler.js.map +1 -0
  114. package/dist/daemon/handlers/CommandHandlers.d.ts +3 -4
  115. package/dist/daemon/handlers/CommandHandlers.d.ts.map +1 -1
  116. package/dist/daemon/handlers/CommandHandlers.js +14 -52
  117. package/dist/daemon/handlers/CommandHandlers.js.map +1 -1
  118. package/dist/daemon/handlers/QueryHandlers.d.ts +8 -6
  119. package/dist/daemon/handlers/QueryHandlers.d.ts.map +1 -1
  120. package/dist/daemon/handlers/QueryHandlers.js +42 -94
  121. package/dist/daemon/handlers/QueryHandlers.js.map +1 -1
  122. package/dist/daemon/handlers/SessionHandlers.d.ts.map +1 -1
  123. package/dist/daemon/handlers/SessionHandlers.js +0 -15
  124. package/dist/daemon/handlers/SessionHandlers.js.map +1 -1
  125. package/dist/daemon/handlers/requestHandlers.d.ts +5 -1
  126. package/dist/daemon/handlers/requestHandlers.d.ts.map +1 -1
  127. package/dist/daemon/handlers/requestHandlers.js +7 -2
  128. package/dist/daemon/handlers/requestHandlers.js.map +1 -1
  129. package/dist/daemon/handlers/responseHandler.d.ts.map +1 -1
  130. package/dist/daemon/handlers/responseHandler.js +19 -8
  131. package/dist/daemon/handlers/responseHandler.js.map +1 -1
  132. package/dist/daemon/ipcServer.d.ts.map +1 -1
  133. package/dist/daemon/ipcServer.js +4 -11
  134. package/dist/daemon/ipcServer.js.map +1 -1
  135. package/dist/daemon/launcher.d.ts.map +1 -1
  136. package/dist/daemon/launcher.js +2 -19
  137. package/dist/daemon/launcher.js.map +1 -1
  138. package/dist/daemon/lifecycle/cdpSetup.d.ts.map +1 -1
  139. package/dist/daemon/lifecycle/cdpSetup.js +0 -4
  140. package/dist/daemon/lifecycle/cdpSetup.js.map +1 -1
  141. package/dist/daemon/lifecycle/chromeConnection.js +0 -1
  142. package/dist/daemon/lifecycle/chromeConnection.js.map +1 -1
  143. package/dist/daemon/lifecycle/signalHandlers.d.ts.map +1 -1
  144. package/dist/daemon/lifecycle/signalHandlers.js +0 -3
  145. package/dist/daemon/lifecycle/signalHandlers.js.map +1 -1
  146. package/dist/daemon/lifecycle/workerCleanup.d.ts.map +1 -1
  147. package/dist/daemon/lifecycle/workerCleanup.js +1 -8
  148. package/dist/daemon/lifecycle/workerCleanup.js.map +1 -1
  149. package/dist/daemon/lifecycle/workerIpc.d.ts.map +1 -1
  150. package/dist/daemon/lifecycle/workerIpc.js +0 -1
  151. package/dist/daemon/lifecycle/workerIpc.js.map +1 -1
  152. package/dist/daemon/server/JsonlParser.d.ts.map +1 -1
  153. package/dist/daemon/server/JsonlParser.js +0 -2
  154. package/dist/daemon/server/JsonlParser.js.map +1 -1
  155. package/dist/daemon/services/SessionService.js +1 -1
  156. package/dist/daemon/services/SessionService.js.map +1 -1
  157. package/dist/daemon/startSession.d.ts.map +1 -1
  158. package/dist/daemon/startSession.js +0 -15
  159. package/dist/daemon/startSession.js.map +1 -1
  160. package/dist/daemon/worker/commandRegistry.d.ts.map +1 -1
  161. package/dist/daemon/worker/commandRegistry.js +34 -1
  162. package/dist/daemon/worker/commandRegistry.js.map +1 -1
  163. package/dist/daemon/worker/plugins.d.ts.map +1 -1
  164. package/dist/daemon/worker/plugins.js +0 -3
  165. package/dist/daemon/worker/plugins.js.map +1 -1
  166. package/dist/daemon/worker.js +0 -9
  167. package/dist/daemon/worker.js.map +1 -1
  168. package/dist/daemon.js +0 -2
  169. package/dist/daemon.js.map +1 -1
  170. package/dist/index.js +0 -14
  171. package/dist/index.js.map +1 -1
  172. package/dist/ipc/__tests__/client.contract.test.js +251 -19
  173. package/dist/ipc/__tests__/client.contract.test.js.map +1 -1
  174. package/dist/ipc/__tests__/jsonl.unit.test.js +19 -1
  175. package/dist/ipc/__tests__/jsonl.unit.test.js.map +1 -1
  176. package/dist/ipc/client.d.ts +47 -1
  177. package/dist/ipc/client.d.ts.map +1 -1
  178. package/dist/ipc/client.js +51 -0
  179. package/dist/ipc/client.js.map +1 -1
  180. package/dist/ipc/index.d.ts.map +1 -1
  181. package/dist/ipc/index.js +0 -6
  182. package/dist/ipc/index.js.map +1 -1
  183. package/dist/ipc/protocol/commands.d.ts +44 -0
  184. package/dist/ipc/protocol/commands.d.ts.map +1 -1
  185. package/dist/ipc/protocol/commands.js +8 -0
  186. package/dist/ipc/protocol/commands.js.map +1 -1
  187. package/dist/ipc/session/queries.d.ts +26 -2
  188. package/dist/ipc/session/queries.d.ts.map +1 -1
  189. package/dist/ipc/transport/index.d.ts.map +1 -1
  190. package/dist/ipc/transport/index.js +0 -1
  191. package/dist/ipc/transport/index.js.map +1 -1
  192. package/dist/ipc/transport/jsonl.d.ts +16 -0
  193. package/dist/ipc/transport/jsonl.d.ts.map +1 -1
  194. package/dist/ipc/transport/jsonl.js +24 -0
  195. package/dist/ipc/transport/jsonl.js.map +1 -1
  196. package/dist/session/chrome.js +2 -2
  197. package/dist/session/chrome.js.map +1 -1
  198. package/dist/session/cleanup.d.ts +21 -0
  199. package/dist/session/cleanup.d.ts.map +1 -1
  200. package/dist/session/cleanup.js +92 -12
  201. package/dist/session/cleanup.js.map +1 -1
  202. package/dist/session/lock.js +1 -1
  203. package/dist/session/lock.js.map +1 -1
  204. package/dist/telemetry/__tests__/a11y.unit.test.d.ts +10 -0
  205. package/dist/telemetry/__tests__/a11y.unit.test.d.ts.map +1 -0
  206. package/dist/telemetry/__tests__/a11y.unit.test.js +265 -0
  207. package/dist/telemetry/__tests__/a11y.unit.test.js.map +1 -0
  208. package/dist/telemetry/__tests__/filters.unit.test.js +119 -1
  209. package/dist/telemetry/__tests__/filters.unit.test.js.map +1 -1
  210. package/dist/telemetry/__tests__/network.contract.test.js +114 -0
  211. package/dist/telemetry/__tests__/network.contract.test.js.map +1 -1
  212. package/dist/telemetry/a11y.d.ts +78 -0
  213. package/dist/telemetry/a11y.d.ts.map +1 -0
  214. package/dist/telemetry/a11y.js +280 -0
  215. package/dist/telemetry/a11y.js.map +1 -0
  216. package/dist/telemetry/dom.d.ts +1 -1
  217. package/dist/telemetry/dom.d.ts.map +1 -1
  218. package/dist/telemetry/dom.js +36 -5
  219. package/dist/telemetry/dom.js.map +1 -1
  220. package/dist/telemetry/filters.d.ts +17 -0
  221. package/dist/telemetry/filters.d.ts.map +1 -1
  222. package/dist/telemetry/filters.js +25 -0
  223. package/dist/telemetry/filters.js.map +1 -1
  224. package/dist/telemetry/har/__tests__/builder.unit.test.d.ts +8 -0
  225. package/dist/telemetry/har/__tests__/builder.unit.test.d.ts.map +1 -0
  226. package/dist/telemetry/har/__tests__/builder.unit.test.js +694 -0
  227. package/dist/telemetry/har/__tests__/builder.unit.test.js.map +1 -0
  228. package/dist/telemetry/har/builder.d.ts +43 -0
  229. package/dist/telemetry/har/builder.d.ts.map +1 -0
  230. package/dist/telemetry/har/builder.js +440 -0
  231. package/dist/telemetry/har/builder.js.map +1 -0
  232. package/dist/telemetry/har/types.d.ts +290 -0
  233. package/dist/telemetry/har/types.d.ts.map +1 -0
  234. package/dist/telemetry/har/types.js +7 -0
  235. package/dist/telemetry/har/types.js.map +1 -0
  236. package/dist/telemetry/network.d.ts.map +1 -1
  237. package/dist/telemetry/network.js +37 -4
  238. package/dist/telemetry/network.js.map +1 -1
  239. package/dist/types.d.ts +108 -0
  240. package/dist/types.d.ts.map +1 -1
  241. package/dist/ui/OutputBuilder.d.ts.map +1 -1
  242. package/dist/ui/OutputBuilder.js +0 -8
  243. package/dist/ui/OutputBuilder.js.map +1 -1
  244. package/dist/ui/errors/CommandError.d.ts.map +1 -1
  245. package/dist/ui/errors/CommandError.js +0 -1
  246. package/dist/ui/errors/CommandError.js.map +1 -1
  247. package/dist/ui/errors/index.d.ts.map +1 -1
  248. package/dist/ui/errors/index.js +0 -2
  249. package/dist/ui/errors/index.js.map +1 -1
  250. package/dist/ui/formatters/__tests__/semantic.unit.test.d.ts +2 -0
  251. package/dist/ui/formatters/__tests__/semantic.unit.test.d.ts.map +1 -0
  252. package/dist/ui/formatters/__tests__/semantic.unit.test.js +111 -0
  253. package/dist/ui/formatters/__tests__/semantic.unit.test.js.map +1 -0
  254. package/dist/ui/formatters/a11y.d.ts +30 -0
  255. package/dist/ui/formatters/a11y.d.ts.map +1 -0
  256. package/dist/ui/formatters/a11y.js +178 -0
  257. package/dist/ui/formatters/a11y.js.map +1 -0
  258. package/dist/ui/formatters/details.d.ts.map +1 -1
  259. package/dist/ui/formatters/details.js +1 -0
  260. package/dist/ui/formatters/details.js.map +1 -1
  261. package/dist/ui/formatters/dom.d.ts.map +1 -1
  262. package/dist/ui/formatters/dom.js +0 -3
  263. package/dist/ui/formatters/dom.js.map +1 -1
  264. package/dist/ui/formatters/index.d.ts +1 -0
  265. package/dist/ui/formatters/index.d.ts.map +1 -1
  266. package/dist/ui/formatters/index.js +1 -0
  267. package/dist/ui/formatters/index.js.map +1 -1
  268. package/dist/ui/formatters/networkHeaders.d.ts +14 -0
  269. package/dist/ui/formatters/networkHeaders.d.ts.map +1 -0
  270. package/dist/ui/formatters/networkHeaders.js +47 -0
  271. package/dist/ui/formatters/networkHeaders.js.map +1 -0
  272. package/dist/ui/formatters/preview.d.ts +2 -0
  273. package/dist/ui/formatters/preview.d.ts.map +1 -1
  274. package/dist/ui/formatters/preview.js +67 -23
  275. package/dist/ui/formatters/preview.js.map +1 -1
  276. package/dist/ui/formatters/semantic.d.ts +36 -0
  277. package/dist/ui/formatters/semantic.d.ts.map +1 -0
  278. package/dist/ui/formatters/semantic.js +98 -0
  279. package/dist/ui/formatters/semantic.js.map +1 -0
  280. package/dist/ui/formatters/status.d.ts.map +1 -1
  281. package/dist/ui/formatters/status.js +1 -12
  282. package/dist/ui/formatters/status.js.map +1 -1
  283. package/dist/ui/formatting.d.ts.map +1 -1
  284. package/dist/ui/formatting.js +0 -6
  285. package/dist/ui/formatting.js.map +1 -1
  286. package/dist/ui/logging/logger.d.ts +1 -1
  287. package/dist/ui/logging/logger.d.ts.map +1 -1
  288. package/dist/ui/logging/logger.js.map +1 -1
  289. package/dist/ui/messages/chrome.d.ts.map +1 -1
  290. package/dist/ui/messages/chrome.js +0 -6
  291. package/dist/ui/messages/chrome.js.map +1 -1
  292. package/dist/ui/messages/commands.d.ts +7 -0
  293. package/dist/ui/messages/commands.d.ts.map +1 -1
  294. package/dist/ui/messages/commands.js +9 -12
  295. package/dist/ui/messages/commands.js.map +1 -1
  296. package/dist/ui/messages/debug.d.ts.map +1 -1
  297. package/dist/ui/messages/debug.js +0 -6
  298. package/dist/ui/messages/debug.js.map +1 -1
  299. package/dist/ui/messages/internal.d.ts.map +1 -1
  300. package/dist/ui/messages/internal.js +0 -3
  301. package/dist/ui/messages/internal.js.map +1 -1
  302. package/dist/ui/messages/preview.d.ts.map +1 -1
  303. package/dist/ui/messages/preview.js +0 -12
  304. package/dist/ui/messages/preview.js.map +1 -1
  305. package/dist/ui/messages/session.d.ts.map +1 -1
  306. package/dist/ui/messages/session.js +0 -3
  307. package/dist/ui/messages/session.js.map +1 -1
  308. package/dist/utils/__tests__/errors.unit.test.d.ts +12 -0
  309. package/dist/utils/__tests__/errors.unit.test.d.ts.map +1 -0
  310. package/dist/utils/__tests__/errors.unit.test.js +255 -0
  311. package/dist/utils/__tests__/errors.unit.test.js.map +1 -0
  312. package/dist/utils/__tests__/http.unit.test.d.ts +12 -0
  313. package/dist/utils/__tests__/http.unit.test.d.ts.map +1 -0
  314. package/dist/utils/__tests__/http.unit.test.js +218 -0
  315. package/dist/utils/__tests__/http.unit.test.js.map +1 -0
  316. package/dist/utils/__tests__/process.unit.test.d.ts +14 -0
  317. package/dist/utils/__tests__/process.unit.test.d.ts.map +1 -0
  318. package/dist/utils/__tests__/process.unit.test.js +124 -0
  319. package/dist/utils/__tests__/process.unit.test.js.map +1 -0
  320. package/dist/utils/__tests__/session.contract.test.js +1 -1
  321. package/dist/utils/__tests__/session.contract.test.js.map +1 -1
  322. package/dist/utils/atomicFile.d.ts.map +1 -1
  323. package/dist/utils/atomicFile.js +9 -6
  324. package/dist/utils/atomicFile.js.map +1 -1
  325. package/dist/utils/exitCodes.d.ts.map +1 -1
  326. package/dist/utils/exitCodes.js +0 -2
  327. package/dist/utils/exitCodes.js.map +1 -1
  328. package/dist/utils/validation.d.ts.map +1 -1
  329. package/dist/utils/validation.js +0 -3
  330. package/dist/utils/validation.js.map +1 -1
  331. package/dist/utils/version.d.ts.map +1 -1
  332. package/dist/utils/version.js +0 -1
  333. package/dist/utils/version.js.map +1 -1
  334. package/package.json +22 -1
@@ -0,0 +1,694 @@
1
+ /**
2
+ * HAR Builder Unit Tests
3
+ *
4
+ * Tests the contract of buildHAR function - transforming NetworkRequest[] to HAR 1.2 format.
5
+ * Following TESTING_PHILOSOPHY.md: Test the contract, not the implementation.
6
+ */
7
+ import assert from 'node:assert/strict';
8
+ import { describe, test } from 'node:test';
9
+ import { buildHAR } from '../../../telemetry/har/builder.js';
10
+ describe('HAR Builder', () => {
11
+ const baseMetadata = {
12
+ version: '0.7.0',
13
+ chromeVersion: '131.0.0.0',
14
+ };
15
+ /**
16
+ * Helper to get first entry with TypeScript assertion.
17
+ */
18
+ function getFirstEntry(entries) {
19
+ const entry = entries[0];
20
+ assert.ok(entry, 'Entry should exist');
21
+ return entry;
22
+ }
23
+ /**
24
+ * Calculate total time from timings (same logic as builder).
25
+ */
26
+ function calculateExpectedTotalTime(timings) {
27
+ const phases = ['blocked', 'dns', 'connect', 'send', 'wait', 'receive'];
28
+ return phases.reduce((total, phase) => {
29
+ const time = timings[phase];
30
+ return total + (time !== undefined && time >= 0 ? time : 0);
31
+ }, 0);
32
+ }
33
+ describe('Basic structure', () => {
34
+ test('creates valid HAR 1.2 structure', () => {
35
+ const requests = [];
36
+ const har = buildHAR(requests, baseMetadata);
37
+ assert.equal(har.log.version, '1.2');
38
+ assert.equal(har.log.creator.name, 'bdg');
39
+ assert.equal(har.log.creator.version, '0.7.0');
40
+ assert.ok(Array.isArray(har.log.entries));
41
+ });
42
+ test('includes browser info when chromeVersion provided', () => {
43
+ const har = buildHAR([], baseMetadata);
44
+ assert.ok(har.log.browser);
45
+ assert.equal(har.log.browser.name, 'Chrome');
46
+ assert.equal(har.log.browser.version, '131.0.0.0');
47
+ });
48
+ test('omits browser info when chromeVersion not provided', () => {
49
+ const har = buildHAR([], { version: '0.7.0' });
50
+ assert.equal(har.log.browser, undefined);
51
+ });
52
+ });
53
+ describe('Request transformation', () => {
54
+ test('transforms basic GET request', () => {
55
+ const requests = [
56
+ {
57
+ requestId: 'req-1',
58
+ url: 'https://example.com/api',
59
+ method: 'GET',
60
+ timestamp: Date.now(),
61
+ },
62
+ ];
63
+ const har = buildHAR(requests, baseMetadata);
64
+ assert.equal(har.log.entries.length, 1);
65
+ const entry = getFirstEntry(har.log.entries);
66
+ assert.equal(entry.request.method, 'GET');
67
+ assert.equal(entry.request.url, 'https://example.com/api');
68
+ assert.equal(entry.request.httpVersion, 'HTTP/1.1');
69
+ });
70
+ test('includes request headers', () => {
71
+ const requests = [
72
+ {
73
+ requestId: 'req-1',
74
+ url: 'https://example.com',
75
+ method: 'GET',
76
+ timestamp: Date.now(),
77
+ requestHeaders: {
78
+ 'user-agent': 'test-agent',
79
+ accept: 'application/json',
80
+ },
81
+ },
82
+ ];
83
+ const har = buildHAR(requests, baseMetadata);
84
+ const headers = getFirstEntry(har.log.entries).request.headers;
85
+ assert.equal(headers.length, 2);
86
+ assert.ok(headers.some((h) => h.name === 'user-agent' && h.value === 'test-agent'));
87
+ assert.ok(headers.some((h) => h.name === 'accept' && h.value === 'application/json'));
88
+ });
89
+ test('extracts query parameters from URL', () => {
90
+ const requests = [
91
+ {
92
+ requestId: 'req-1',
93
+ url: 'https://example.com/api?foo=bar&baz=qux',
94
+ method: 'GET',
95
+ timestamp: Date.now(),
96
+ },
97
+ ];
98
+ const har = buildHAR(requests, baseMetadata);
99
+ const query = getFirstEntry(har.log.entries).request.queryString;
100
+ assert.equal(query.length, 2);
101
+ assert.ok(query.some((q) => q.name === 'foo' && q.value === 'bar'));
102
+ assert.ok(query.some((q) => q.name === 'baz' && q.value === 'qux'));
103
+ });
104
+ test('includes POST body', () => {
105
+ const requests = [
106
+ {
107
+ requestId: 'req-1',
108
+ url: 'https://example.com/api',
109
+ method: 'POST',
110
+ timestamp: Date.now(),
111
+ requestBody: '{"key":"value"}',
112
+ requestHeaders: {
113
+ 'content-type': 'application/json',
114
+ },
115
+ },
116
+ ];
117
+ const har = buildHAR(requests, baseMetadata);
118
+ const postData = getFirstEntry(har.log.entries).request.postData;
119
+ assert.ok(postData);
120
+ assert.equal(postData.mimeType, 'application/json');
121
+ assert.equal(postData.text, '{"key":"value"}');
122
+ });
123
+ test('calculates request headers size including HTTP line', () => {
124
+ const requests = [
125
+ {
126
+ requestId: 'req-1',
127
+ url: 'https://example.com/path',
128
+ method: 'GET',
129
+ timestamp: Date.now(),
130
+ requestHeaders: {
131
+ host: 'example.com',
132
+ },
133
+ },
134
+ ];
135
+ const har = buildHAR(requests, baseMetadata);
136
+ const headersSize = getFirstEntry(har.log.entries).request.headersSize;
137
+ // Should include "GET /path HTTP/1.1\r\n" + "host: example.com\r\n" + "\r\n"
138
+ assert.ok(headersSize > 0);
139
+ assert.ok(headersSize > 'host: example.com'.length); // More than just header
140
+ });
141
+ });
142
+ describe('Response transformation', () => {
143
+ test('includes response status and headers', () => {
144
+ const requests = [
145
+ {
146
+ requestId: 'req-1',
147
+ url: 'https://example.com',
148
+ method: 'GET',
149
+ timestamp: Date.now(),
150
+ status: 200,
151
+ mimeType: 'text/html',
152
+ responseHeaders: {
153
+ 'content-type': 'text/html; charset=utf-8',
154
+ },
155
+ },
156
+ ];
157
+ const har = buildHAR(requests, baseMetadata);
158
+ const response = getFirstEntry(har.log.entries).response;
159
+ assert.equal(response.status, 200);
160
+ assert.equal(response.statusText, 'OK');
161
+ assert.equal(response.httpVersion, 'HTTP/1.1');
162
+ assert.ok(response.headers.some((h) => h.name === 'content-type'));
163
+ });
164
+ test('includes response body', () => {
165
+ const requests = [
166
+ {
167
+ requestId: 'req-1',
168
+ url: 'https://example.com',
169
+ method: 'GET',
170
+ timestamp: Date.now(),
171
+ status: 200,
172
+ mimeType: 'application/json',
173
+ responseBody: '{"result":"ok"}',
174
+ },
175
+ ];
176
+ const har = buildHAR(requests, baseMetadata);
177
+ const content = getFirstEntry(har.log.entries).response.content;
178
+ assert.equal(content.mimeType, 'application/json');
179
+ assert.equal(content.text, '{"result":"ok"}');
180
+ assert.ok(content.size > 0);
181
+ });
182
+ test('base64 encodes binary content', () => {
183
+ const requests = [
184
+ {
185
+ requestId: 'req-1',
186
+ url: 'https://example.com/image.png',
187
+ method: 'GET',
188
+ timestamp: Date.now(),
189
+ status: 200,
190
+ mimeType: 'image/png',
191
+ responseBody: 'binary-data',
192
+ },
193
+ ];
194
+ const har = buildHAR(requests, baseMetadata);
195
+ const content = getFirstEntry(har.log.entries).response.content;
196
+ assert.equal(content.mimeType, 'image/png');
197
+ assert.equal(content.encoding, 'base64');
198
+ assert.ok(content.text); // Should be base64 encoded
199
+ });
200
+ test('uses encodedDataLength for response bodySize', () => {
201
+ const requests = [
202
+ {
203
+ requestId: 'req-1',
204
+ url: 'https://example.com',
205
+ method: 'GET',
206
+ timestamp: Date.now(),
207
+ status: 200,
208
+ responseBody: 'test',
209
+ encodedDataLength: 1234, // Wire size (compressed)
210
+ decodedBodyLength: 5678, // Decoded size
211
+ },
212
+ ];
213
+ const har = buildHAR(requests, baseMetadata);
214
+ const response = getFirstEntry(har.log.entries).response;
215
+ assert.equal(response.bodySize, 1234); // Should use wire size
216
+ assert.equal(response.content.size, 5678); // Should use decoded size
217
+ });
218
+ test('calculates response headers size including status line', () => {
219
+ const requests = [
220
+ {
221
+ requestId: 'req-1',
222
+ url: 'https://example.com',
223
+ method: 'GET',
224
+ timestamp: Date.now(),
225
+ status: 200,
226
+ responseHeaders: {
227
+ 'content-type': 'text/html',
228
+ },
229
+ },
230
+ ];
231
+ const har = buildHAR(requests, baseMetadata);
232
+ const headersSize = getFirstEntry(har.log.entries).response.headersSize;
233
+ // Should include "HTTP/1.1 200 OK\r\n" + headers + "\r\n"
234
+ assert.ok(headersSize > 0);
235
+ assert.ok(headersSize > 'content-type: text/html'.length);
236
+ });
237
+ });
238
+ describe('Timing calculations', () => {
239
+ test('uses real timing data when available', () => {
240
+ const requests = [
241
+ {
242
+ requestId: 'req-1',
243
+ url: 'https://example.com',
244
+ method: 'GET',
245
+ timestamp: Date.now(),
246
+ timing: {
247
+ requestTime: 1000.0,
248
+ dnsStart: 0,
249
+ dnsEnd: 50,
250
+ connectStart: 50,
251
+ connectEnd: 150,
252
+ sslStart: 75,
253
+ sslEnd: 125,
254
+ sendStart: 150,
255
+ sendEnd: 155,
256
+ receiveHeadersEnd: 200,
257
+ },
258
+ loadingFinishedTime: 1000.25, // 250ms after requestTime
259
+ },
260
+ ];
261
+ const har = buildHAR(requests, baseMetadata);
262
+ const timings = getFirstEntry(har.log.entries).timings;
263
+ assert.equal(timings.dns, 50); // dnsEnd - dnsStart
264
+ assert.equal(timings.connect, 100); // connectEnd - connectStart
265
+ assert.equal(timings.ssl, 50); // sslEnd - sslStart
266
+ assert.equal(timings.send, 5); // sendEnd - sendStart
267
+ assert.equal(timings.wait, 45); // receiveHeadersEnd - sendEnd
268
+ assert.equal(timings.receive, 50); // (loadingFinishedTime - requestTime)*1000 - receiveHeadersEnd
269
+ });
270
+ test('uses -1 for unknown timing fields', () => {
271
+ const requests = [
272
+ {
273
+ requestId: 'req-1',
274
+ url: 'https://example.com',
275
+ method: 'GET',
276
+ timestamp: Date.now(),
277
+ timing: {
278
+ requestTime: 1000.0,
279
+ dnsStart: -1,
280
+ dnsEnd: -1,
281
+ connectStart: -1,
282
+ connectEnd: -1,
283
+ sendStart: 150,
284
+ sendEnd: 155,
285
+ receiveHeadersEnd: 200,
286
+ },
287
+ },
288
+ ];
289
+ const har = buildHAR(requests, baseMetadata);
290
+ const timings = getFirstEntry(har.log.entries).timings;
291
+ assert.equal(timings.dns, -1);
292
+ assert.equal(timings.connect, -1);
293
+ assert.equal(timings.send, 5); // Still calculates known values
294
+ });
295
+ test('calculates total time from timing breakdown', () => {
296
+ const requests = [
297
+ {
298
+ requestId: 'req-1',
299
+ url: 'https://example.com',
300
+ method: 'GET',
301
+ timestamp: Date.now(),
302
+ timing: {
303
+ requestTime: 1000.0,
304
+ dnsStart: 0,
305
+ dnsEnd: 50,
306
+ connectStart: 50,
307
+ connectEnd: 150,
308
+ sendStart: 150,
309
+ sendEnd: 155,
310
+ receiveHeadersEnd: 200,
311
+ },
312
+ loadingFinishedTime: 1000.25,
313
+ },
314
+ ];
315
+ const har = buildHAR(requests, baseMetadata);
316
+ const { timings, time } = getFirstEntry(har.log.entries);
317
+ // time should be sum of all phases (except ssl which overlaps)
318
+ assert.equal(time, calculateExpectedTotalTime(timings));
319
+ });
320
+ test('handles missing timing data gracefully', () => {
321
+ const requests = [
322
+ {
323
+ requestId: 'req-1',
324
+ url: 'https://example.com',
325
+ method: 'GET',
326
+ timestamp: Date.now(),
327
+ // No timing data
328
+ },
329
+ ];
330
+ const har = buildHAR(requests, baseMetadata);
331
+ const { timings, time } = getFirstEntry(har.log.entries);
332
+ assert.equal(timings.blocked, -1);
333
+ assert.equal(timings.dns, -1);
334
+ assert.equal(timings.connect, -1);
335
+ assert.equal(timings.send, -1);
336
+ assert.equal(timings.wait, -1);
337
+ assert.equal(timings.receive, -1);
338
+ assert.equal(time, 0); // No timing data = 0 total
339
+ });
340
+ });
341
+ describe('Server metadata', () => {
342
+ test('includes server IP and connection ID when available', () => {
343
+ const requests = [
344
+ {
345
+ requestId: 'req-1',
346
+ url: 'https://example.com',
347
+ method: 'GET',
348
+ timestamp: Date.now(),
349
+ serverIPAddress: '192.168.1.1',
350
+ connection: '42',
351
+ },
352
+ ];
353
+ const har = buildHAR(requests, baseMetadata);
354
+ const entry = getFirstEntry(har.log.entries);
355
+ assert.equal(entry.serverIPAddress, '192.168.1.1');
356
+ assert.equal(entry.connection, '42');
357
+ });
358
+ test('omits server metadata when not available', () => {
359
+ const requests = [
360
+ {
361
+ requestId: 'req-1',
362
+ url: 'https://example.com',
363
+ method: 'GET',
364
+ timestamp: Date.now(),
365
+ },
366
+ ];
367
+ const har = buildHAR(requests, baseMetadata);
368
+ const entry = getFirstEntry(har.log.entries);
369
+ assert.equal(entry.serverIPAddress, undefined);
370
+ assert.equal(entry.connection, undefined);
371
+ });
372
+ });
373
+ describe('Edge cases', () => {
374
+ test('handles empty request array', () => {
375
+ const har = buildHAR([], baseMetadata);
376
+ assert.equal(har.log.entries.length, 0);
377
+ });
378
+ test('handles request with no headers', () => {
379
+ const requests = [
380
+ {
381
+ requestId: 'req-1',
382
+ url: 'https://example.com',
383
+ method: 'GET',
384
+ timestamp: Date.now(),
385
+ },
386
+ ];
387
+ const har = buildHAR(requests, baseMetadata);
388
+ const { request, response } = getFirstEntry(har.log.entries);
389
+ assert.equal(request.headers.length, 0);
390
+ assert.equal(response.headers.length, 0);
391
+ });
392
+ test('handles failed request (status 0)', () => {
393
+ const requests = [
394
+ {
395
+ requestId: 'req-1',
396
+ url: 'https://example.com',
397
+ method: 'GET',
398
+ timestamp: Date.now(),
399
+ status: 0,
400
+ },
401
+ ];
402
+ const har = buildHAR(requests, baseMetadata);
403
+ const response = getFirstEntry(har.log.entries).response;
404
+ assert.equal(response.status, 0);
405
+ assert.equal(response.statusText, 'Unknown');
406
+ });
407
+ test('handles URL with special characters', () => {
408
+ const requests = [
409
+ {
410
+ requestId: 'req-1',
411
+ url: 'https://example.com/path?query=hello%20world&foo=bar%26baz',
412
+ method: 'GET',
413
+ timestamp: Date.now(),
414
+ },
415
+ ];
416
+ const har = buildHAR(requests, baseMetadata);
417
+ const entry = getFirstEntry(har.log.entries);
418
+ assert.equal(entry.request.url, 'https://example.com/path?query=hello%20world&foo=bar%26baz');
419
+ assert.ok(entry.request.queryString.length > 0);
420
+ });
421
+ });
422
+ describe('Cookie handling', () => {
423
+ test('extracts cookies from request headers', () => {
424
+ const requests = [
425
+ {
426
+ requestId: 'req-1',
427
+ url: 'https://example.com',
428
+ method: 'GET',
429
+ timestamp: Date.now(),
430
+ requestHeaders: {
431
+ cookie: 'session=abc123; theme=dark',
432
+ },
433
+ },
434
+ ];
435
+ const har = buildHAR(requests, baseMetadata);
436
+ const cookies = getFirstEntry(har.log.entries).request.cookies;
437
+ assert.equal(cookies.length, 2);
438
+ assert.ok(cookies.some((c) => c.name === 'session' && c.value === 'abc123'));
439
+ assert.ok(cookies.some((c) => c.name === 'theme' && c.value === 'dark'));
440
+ });
441
+ test('extracts cookies from set-cookie header', () => {
442
+ const requests = [
443
+ {
444
+ requestId: 'req-1',
445
+ url: 'https://example.com',
446
+ method: 'GET',
447
+ timestamp: Date.now(),
448
+ responseHeaders: {
449
+ 'set-cookie': 'session=xyz789; path=/; secure',
450
+ },
451
+ },
452
+ ];
453
+ const har = buildHAR(requests, baseMetadata);
454
+ const cookies = getFirstEntry(har.log.entries).response.cookies;
455
+ assert.ok(cookies.length > 0);
456
+ assert.ok(cookies.some((c) => c.name === 'session'));
457
+ });
458
+ });
459
+ describe('Receive time edge cases', () => {
460
+ test('handles loadingFinishedTime before receiveHeadersEnd (invalid data)', () => {
461
+ const requests = [
462
+ {
463
+ requestId: 'req-1',
464
+ url: 'https://example.com',
465
+ method: 'GET',
466
+ timestamp: Date.now(),
467
+ timing: {
468
+ requestTime: 1000.0,
469
+ receiveHeadersEnd: 200,
470
+ sendEnd: 150,
471
+ sendStart: 140,
472
+ sslEnd: 130,
473
+ sslStart: 100,
474
+ connectEnd: 100,
475
+ connectStart: 50,
476
+ dnsEnd: 50,
477
+ dnsStart: 0,
478
+ },
479
+ loadingFinishedTime: 999.9, // Before requestTime (impossible but test robustness)
480
+ },
481
+ ];
482
+ const har = buildHAR(requests, baseMetadata);
483
+ const timings = getFirstEntry(har.log.entries).timings;
484
+ // Should produce negative receive time, which is valid per HAR spec for unknown/invalid
485
+ // receive = (999.9 - 1000.0) * 1000 - 200 = -100 - 200 = -300
486
+ // Use approximate comparison for floating point
487
+ assert.ok(Math.abs(timings.receive - -300) < 0.001, `Expected -300, got ${timings.receive}`);
488
+ });
489
+ test('handles large file download (significant receive time)', () => {
490
+ const requests = [
491
+ {
492
+ requestId: 'req-1',
493
+ url: 'https://example.com/large-file.zip',
494
+ method: 'GET',
495
+ timestamp: Date.now(),
496
+ timing: {
497
+ requestTime: 1000.0,
498
+ receiveHeadersEnd: 200,
499
+ sendEnd: 150,
500
+ sendStart: 140,
501
+ sslEnd: 130,
502
+ sslStart: 100,
503
+ connectEnd: 100,
504
+ connectStart: 50,
505
+ dnsEnd: 50,
506
+ dnsStart: 0,
507
+ },
508
+ loadingFinishedTime: 1005.5, // 5.5 seconds after requestTime
509
+ },
510
+ ];
511
+ const har = buildHAR(requests, baseMetadata);
512
+ const timings = getFirstEntry(har.log.entries).timings;
513
+ // receive = (1005.5 - 1000.0) * 1000 - 200 = 5500 - 200 = 5300ms
514
+ assert.equal(timings.receive, 5300);
515
+ });
516
+ test('handles missing loadingFinishedTime gracefully', () => {
517
+ const requests = [
518
+ {
519
+ requestId: 'req-1',
520
+ url: 'https://example.com',
521
+ method: 'GET',
522
+ timestamp: Date.now(),
523
+ timing: {
524
+ requestTime: 1000.0,
525
+ receiveHeadersEnd: 200,
526
+ sendEnd: 150,
527
+ sendStart: 140,
528
+ sslEnd: 130,
529
+ sslStart: 100,
530
+ connectEnd: 100,
531
+ connectStart: 50,
532
+ dnsEnd: 50,
533
+ dnsStart: 0,
534
+ },
535
+ // No loadingFinishedTime
536
+ },
537
+ ];
538
+ const har = buildHAR(requests, baseMetadata);
539
+ const timings = getFirstEntry(har.log.entries).timings;
540
+ assert.equal(timings.receive, -1); // Unknown
541
+ });
542
+ });
543
+ describe('Binary content encoding validation', () => {
544
+ test('base64 encodes binary content correctly', () => {
545
+ const binaryData = 'test-binary-data';
546
+ const expectedBase64 = Buffer.from(binaryData).toString('base64');
547
+ const requests = [
548
+ {
549
+ requestId: 'req-1',
550
+ url: 'https://example.com/image.png',
551
+ method: 'GET',
552
+ timestamp: Date.now(),
553
+ status: 200,
554
+ mimeType: 'image/png',
555
+ responseBody: binaryData,
556
+ },
557
+ ];
558
+ const har = buildHAR(requests, baseMetadata);
559
+ const content = getFirstEntry(har.log.entries).response.content;
560
+ assert.equal(content.encoding, 'base64');
561
+ assert.equal(content.text, expectedBase64);
562
+ });
563
+ test('detects various binary MIME types', () => {
564
+ const binaryTypes = [
565
+ 'image/jpeg',
566
+ 'image/gif',
567
+ 'video/mp4',
568
+ 'audio/mpeg',
569
+ 'application/pdf',
570
+ 'application/zip',
571
+ ];
572
+ for (const mimeType of binaryTypes) {
573
+ const requests = [
574
+ {
575
+ requestId: 'req-1',
576
+ url: 'https://example.com/file',
577
+ method: 'GET',
578
+ timestamp: Date.now(),
579
+ status: 200,
580
+ mimeType,
581
+ responseBody: 'data',
582
+ },
583
+ ];
584
+ const har = buildHAR(requests, baseMetadata);
585
+ const content = getFirstEntry(har.log.entries).response.content;
586
+ assert.equal(content.encoding, 'base64', `Should base64 encode ${mimeType}`);
587
+ assert.equal(content.text, Buffer.from('data').toString('base64'));
588
+ }
589
+ });
590
+ test('does not encode text content', () => {
591
+ const textTypes = ['text/html', 'text/plain', 'application/json', 'application/javascript'];
592
+ for (const mimeType of textTypes) {
593
+ const requests = [
594
+ {
595
+ requestId: 'req-1',
596
+ url: 'https://example.com/file',
597
+ method: 'GET',
598
+ timestamp: Date.now(),
599
+ status: 200,
600
+ mimeType,
601
+ responseBody: '{"test":"data"}',
602
+ },
603
+ ];
604
+ const har = buildHAR(requests, baseMetadata);
605
+ const content = getFirstEntry(har.log.entries).response.content;
606
+ assert.equal(content.encoding, undefined, `Should not encode ${mimeType}`);
607
+ assert.equal(content.text, '{"test":"data"}');
608
+ }
609
+ });
610
+ });
611
+ describe('Complex header parsing', () => {
612
+ test('handles headers with special characters', () => {
613
+ const requests = [
614
+ {
615
+ requestId: 'req-1',
616
+ url: 'https://example.com',
617
+ method: 'GET',
618
+ timestamp: Date.now(),
619
+ requestHeaders: {
620
+ 'user-agent': 'Mozilla/5.0 (X11; Linux x86_64)',
621
+ 'accept-language': 'en-US,en;q=0.9',
622
+ 'x-custom': 'value=with=equals',
623
+ },
624
+ },
625
+ ];
626
+ const har = buildHAR(requests, baseMetadata);
627
+ const headers = getFirstEntry(har.log.entries).request.headers;
628
+ assert.ok(headers.some((h) => h.name === 'user-agent' && h.value.includes('X11')));
629
+ assert.ok(headers.some((h) => h.name === 'accept-language' && h.value.includes('q=0.9')));
630
+ assert.ok(headers.some((h) => h.name === 'x-custom' && h.value === 'value=with=equals'));
631
+ });
632
+ test('handles empty header values', () => {
633
+ const requests = [
634
+ {
635
+ requestId: 'req-1',
636
+ url: 'https://example.com',
637
+ method: 'GET',
638
+ timestamp: Date.now(),
639
+ requestHeaders: {
640
+ 'empty-header': '',
641
+ 'normal-header': 'value',
642
+ },
643
+ },
644
+ ];
645
+ const har = buildHAR(requests, baseMetadata);
646
+ const headers = getFirstEntry(har.log.entries).request.headers;
647
+ assert.ok(headers.some((h) => h.name === 'empty-header' && h.value === ''));
648
+ assert.ok(headers.some((h) => h.name === 'normal-header' && h.value === 'value'));
649
+ });
650
+ test('calculates header size for complex headers', () => {
651
+ const requests = [
652
+ {
653
+ requestId: 'req-1',
654
+ url: 'https://example.com/path?query=value',
655
+ method: 'POST',
656
+ timestamp: Date.now(),
657
+ requestHeaders: {
658
+ 'content-type': 'application/json; charset=utf-8',
659
+ authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9',
660
+ 'x-request-id': '550e8400-e29b-41d4-a716-446655440000',
661
+ },
662
+ },
663
+ ];
664
+ const har = buildHAR(requests, baseMetadata);
665
+ const headersSize = getFirstEntry(har.log.entries).request.headersSize;
666
+ // Should include: "POST /path?query=value HTTP/1.1\r\n" + all headers + "\r\n"
667
+ const expectedMinSize = 'POST /path?query=value HTTP/1.1\r\n'.length +
668
+ 'content-type: application/json; charset=utf-8\r\n'.length +
669
+ 'authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\r\n'.length +
670
+ 'x-request-id: 550e8400-e29b-41d4-a716-446655440000\r\n'.length +
671
+ '\r\n'.length;
672
+ assert.ok(headersSize >= expectedMinSize, `Headers size ${headersSize} should be >= ${expectedMinSize}`);
673
+ });
674
+ test('handles cookie headers with special characters', () => {
675
+ const requests = [
676
+ {
677
+ requestId: 'req-1',
678
+ url: 'https://example.com',
679
+ method: 'GET',
680
+ timestamp: Date.now(),
681
+ requestHeaders: {
682
+ cookie: 'token=abc%3D%3D123; path=/admin; expires=Wed, 21 Oct 2025 07:28:00 GMT',
683
+ },
684
+ },
685
+ ];
686
+ const har = buildHAR(requests, baseMetadata);
687
+ const cookies = getFirstEntry(har.log.entries).request.cookies;
688
+ // Should parse cookie name/value pairs (ignoring attributes like path, expires)
689
+ assert.ok(cookies.length >= 1);
690
+ assert.ok(cookies.some((c) => c.name === 'token'));
691
+ });
692
+ });
693
+ });
694
+ //# sourceMappingURL=builder.unit.test.js.map