agent-messenger 1.0.0 → 1.1.0

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 (330) hide show
  1. package/.claude/commands/release.md +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.github/workflows/ci.yml +1 -1
  4. package/.github/workflows/e2e.yml.disabled +69 -0
  5. package/README.md +16 -14
  6. package/biome.json +33 -1
  7. package/bun.lock +63 -0
  8. package/dist/package.json +8 -4
  9. package/dist/src/cli.d.ts.map +1 -1
  10. package/dist/src/cli.js +4 -1
  11. package/dist/src/cli.js.map +1 -1
  12. package/dist/src/platforms/discord/cli.js +1 -1
  13. package/dist/src/platforms/discord/client.d.ts.map +1 -1
  14. package/dist/src/platforms/discord/client.js +3 -3
  15. package/dist/src/platforms/discord/client.js.map +1 -1
  16. package/dist/src/platforms/discord/commands/user.d.ts.map +1 -1
  17. package/dist/src/platforms/discord/commands/user.js +10 -1
  18. package/dist/src/platforms/discord/commands/user.js.map +1 -1
  19. package/dist/src/platforms/discord/credential-manager.d.ts.map +1 -1
  20. package/dist/src/platforms/discord/credential-manager.js +18 -12
  21. package/dist/src/platforms/discord/credential-manager.js.map +1 -1
  22. package/dist/src/platforms/slack/cli.js +1 -1
  23. package/dist/src/platforms/slack/credential-manager.d.ts.map +1 -1
  24. package/dist/src/platforms/slack/credential-manager.js +20 -6
  25. package/dist/src/platforms/slack/credential-manager.js.map +1 -1
  26. package/dist/src/platforms/slack/token-extractor.d.ts.map +1 -1
  27. package/dist/src/platforms/slack/token-extractor.js +34 -9
  28. package/dist/src/platforms/slack/token-extractor.js.map +1 -1
  29. package/dist/src/platforms/teams/cli.d.ts.map +1 -0
  30. package/dist/{cli.js → src/platforms/teams/cli.js} +11 -10
  31. package/dist/src/platforms/teams/cli.js.map +1 -0
  32. package/dist/src/platforms/teams/client.d.ts +32 -0
  33. package/dist/src/platforms/teams/client.d.ts.map +1 -0
  34. package/dist/src/platforms/teams/client.js +202 -0
  35. package/dist/src/platforms/teams/client.js.map +1 -0
  36. package/dist/src/platforms/teams/commands/auth.d.ts +14 -0
  37. package/dist/src/platforms/teams/commands/auth.d.ts.map +1 -0
  38. package/dist/src/platforms/teams/commands/auth.js +176 -0
  39. package/dist/src/platforms/teams/commands/auth.js.map +1 -0
  40. package/dist/src/platforms/teams/commands/channel.d.ts +13 -0
  41. package/dist/src/platforms/teams/commands/channel.d.ts.map +1 -0
  42. package/dist/src/platforms/teams/commands/channel.js +97 -0
  43. package/dist/src/platforms/teams/commands/channel.js.map +1 -0
  44. package/dist/src/platforms/teams/commands/file.d.ts +12 -0
  45. package/dist/src/platforms/teams/commands/file.d.ts.map +1 -0
  46. package/dist/src/platforms/teams/commands/file.js +104 -0
  47. package/dist/src/platforms/teams/commands/file.js.map +1 -0
  48. package/dist/{commands → src/platforms/teams/commands}/index.d.ts +5 -2
  49. package/dist/src/platforms/teams/commands/index.d.ts.map +1 -0
  50. package/dist/{commands → src/platforms/teams/commands}/index.js +5 -2
  51. package/dist/src/platforms/teams/commands/index.js.map +1 -0
  52. package/dist/src/platforms/teams/commands/message.d.ts +17 -0
  53. package/dist/src/platforms/teams/commands/message.d.ts.map +1 -0
  54. package/dist/src/platforms/teams/commands/message.js +133 -0
  55. package/dist/src/platforms/teams/commands/message.js.map +1 -0
  56. package/dist/src/platforms/teams/commands/reaction.d.ts +9 -0
  57. package/dist/src/platforms/teams/commands/reaction.d.ts.map +1 -0
  58. package/dist/src/platforms/teams/commands/reaction.js +68 -0
  59. package/dist/src/platforms/teams/commands/reaction.js.map +1 -0
  60. package/dist/src/platforms/teams/commands/snapshot.d.ts +10 -0
  61. package/dist/src/platforms/teams/commands/snapshot.d.ts.map +1 -0
  62. package/dist/src/platforms/teams/commands/snapshot.js +85 -0
  63. package/dist/src/platforms/teams/commands/snapshot.js.map +1 -0
  64. package/dist/src/platforms/teams/commands/team.d.ts +18 -0
  65. package/dist/src/platforms/teams/commands/team.d.ts.map +1 -0
  66. package/dist/src/platforms/teams/commands/team.js +130 -0
  67. package/dist/src/platforms/teams/commands/team.js.map +1 -0
  68. package/dist/src/platforms/teams/commands/user.d.ts.map +1 -0
  69. package/dist/src/platforms/teams/commands/user.js +88 -0
  70. package/dist/src/platforms/teams/commands/user.js.map +1 -0
  71. package/dist/src/platforms/teams/credential-manager.d.ts +18 -0
  72. package/dist/src/platforms/teams/credential-manager.d.ts.map +1 -0
  73. package/dist/src/platforms/teams/credential-manager.js +81 -0
  74. package/dist/src/platforms/teams/credential-manager.js.map +1 -0
  75. package/dist/src/platforms/teams/index.d.ts +4 -0
  76. package/dist/src/platforms/teams/index.d.ts.map +1 -0
  77. package/dist/src/platforms/teams/index.js +6 -0
  78. package/dist/src/platforms/teams/index.js.map +1 -0
  79. package/dist/src/platforms/teams/token-extractor.d.ts +36 -0
  80. package/dist/src/platforms/teams/token-extractor.d.ts.map +1 -0
  81. package/dist/src/platforms/teams/token-extractor.js +335 -0
  82. package/dist/src/platforms/teams/token-extractor.js.map +1 -0
  83. package/dist/src/platforms/teams/types.d.ts +209 -0
  84. package/dist/src/platforms/teams/types.d.ts.map +1 -0
  85. package/dist/src/platforms/teams/types.js +65 -0
  86. package/dist/src/platforms/teams/types.js.map +1 -0
  87. package/docs/teams.md +321 -0
  88. package/e2e/README.md +256 -0
  89. package/e2e/config.ts +45 -0
  90. package/e2e/discord.e2e.test.ts +252 -0
  91. package/e2e/helpers.ts +107 -0
  92. package/e2e/slack.e2e.test.ts +309 -0
  93. package/package.json +8 -4
  94. package/scripts/postbuild.ts +15 -0
  95. package/skills/agent-teams/SKILL.md +292 -0
  96. package/skills/agent-teams/references/authentication.md +375 -0
  97. package/skills/agent-teams/references/common-patterns.md +596 -0
  98. package/skills/agent-teams/templates/monitor-channel.sh +239 -0
  99. package/skills/agent-teams/templates/post-message.sh +224 -0
  100. package/skills/agent-teams/templates/team-summary.sh +210 -0
  101. package/src/cli.ts +4 -0
  102. package/src/platforms/discord/client.ts +3 -3
  103. package/src/platforms/discord/commands/auth.test.ts +48 -32
  104. package/src/platforms/discord/commands/channel.test.ts +54 -42
  105. package/src/platforms/discord/commands/file.test.ts +40 -53
  106. package/src/platforms/discord/commands/guild.test.ts +47 -27
  107. package/src/platforms/discord/commands/message.test.ts +54 -51
  108. package/src/platforms/discord/commands/reaction.test.ts +54 -42
  109. package/src/platforms/discord/commands/user.ts +12 -1
  110. package/src/platforms/discord/credential-manager.test.ts +137 -136
  111. package/src/platforms/discord/credential-manager.ts +20 -13
  112. package/src/platforms/discord/token-extractor.test.ts +133 -383
  113. package/{tests → src/platforms/slack}/cli.test.ts +3 -3
  114. package/{tests/slack-client.test.ts → src/platforms/slack/client.test.ts} +1 -1
  115. package/{tests → src/platforms/slack}/commands/auth.test.ts +25 -13
  116. package/{tests → src/platforms/slack}/commands/channel.test.ts +2 -2
  117. package/{tests → src/platforms/slack}/commands/file.test.ts +2 -2
  118. package/{tests → src/platforms/slack}/commands/message.test.ts +2 -2
  119. package/{tests → src/platforms/slack}/commands/reaction.test.ts +1 -1
  120. package/{tests → src/platforms/slack}/commands/snapshot.test.ts +117 -105
  121. package/{tests → src/platforms/slack}/commands/user.test.ts +3 -3
  122. package/{tests → src/platforms/slack}/commands/workspace.test.ts +44 -95
  123. package/{tests → src/platforms/slack}/credential-manager.test.ts +2 -2
  124. package/src/platforms/slack/credential-manager.ts +22 -7
  125. package/src/platforms/slack/token-extractor-node-test.ts +40 -0
  126. package/src/platforms/slack/token-extractor-node.test.ts +10 -0
  127. package/src/platforms/slack/token-extractor.ts +36 -10
  128. package/{tests → src/platforms/slack}/types.test.ts +1 -1
  129. package/src/platforms/teams/cli.ts +36 -0
  130. package/src/platforms/teams/client.test.ts +500 -0
  131. package/src/platforms/teams/client.ts +365 -0
  132. package/src/platforms/teams/commands/auth.test.ts +99 -0
  133. package/src/platforms/teams/commands/auth.ts +232 -0
  134. package/src/platforms/teams/commands/channel.test.ts +147 -0
  135. package/src/platforms/teams/commands/channel.ts +129 -0
  136. package/src/platforms/teams/commands/file.test.ts +88 -0
  137. package/src/platforms/teams/commands/file.ts +144 -0
  138. package/src/platforms/teams/commands/index.ts +12 -0
  139. package/src/platforms/teams/commands/message.test.ts +110 -0
  140. package/src/platforms/teams/commands/message.ts +188 -0
  141. package/src/platforms/teams/commands/reaction.test.ts +87 -0
  142. package/src/platforms/teams/commands/reaction.ts +104 -0
  143. package/src/platforms/teams/commands/snapshot.test.ts +35 -0
  144. package/src/platforms/teams/commands/snapshot.ts +115 -0
  145. package/src/platforms/teams/commands/team.test.ts +157 -0
  146. package/src/platforms/teams/commands/team.ts +164 -0
  147. package/src/platforms/teams/commands/user.test.ts +83 -0
  148. package/src/platforms/teams/commands/user.ts +112 -0
  149. package/src/platforms/teams/credential-manager.test.ts +178 -0
  150. package/src/platforms/teams/credential-manager.ts +92 -0
  151. package/src/platforms/teams/index.ts +5 -0
  152. package/src/platforms/teams/token-extractor.test.ts +429 -0
  153. package/src/platforms/teams/token-extractor.ts +462 -0
  154. package/src/platforms/teams/types.test.ts +226 -0
  155. package/src/platforms/teams/types.ts +140 -0
  156. package/tsconfig.json +1 -1
  157. package/dist/cli.d.ts.map +0 -1
  158. package/dist/cli.js.map +0 -1
  159. package/dist/commands/auth.d.ts +0 -3
  160. package/dist/commands/auth.d.ts.map +0 -1
  161. package/dist/commands/auth.js +0 -140
  162. package/dist/commands/auth.js.map +0 -1
  163. package/dist/commands/channel.d.ts +0 -3
  164. package/dist/commands/channel.d.ts.map +0 -1
  165. package/dist/commands/channel.js +0 -118
  166. package/dist/commands/channel.js.map +0 -1
  167. package/dist/commands/file.d.ts +0 -3
  168. package/dist/commands/file.d.ts.map +0 -1
  169. package/dist/commands/file.js +0 -113
  170. package/dist/commands/file.js.map +0 -1
  171. package/dist/commands/index.d.ts.map +0 -1
  172. package/dist/commands/index.js.map +0 -1
  173. package/dist/commands/message.d.ts +0 -3
  174. package/dist/commands/message.d.ts.map +0 -1
  175. package/dist/commands/message.js +0 -214
  176. package/dist/commands/message.js.map +0 -1
  177. package/dist/commands/reaction.d.ts +0 -3
  178. package/dist/commands/reaction.d.ts.map +0 -1
  179. package/dist/commands/reaction.js +0 -100
  180. package/dist/commands/reaction.js.map +0 -1
  181. package/dist/commands/snapshot.d.ts +0 -3
  182. package/dist/commands/snapshot.d.ts.map +0 -1
  183. package/dist/commands/snapshot.js +0 -88
  184. package/dist/commands/snapshot.js.map +0 -1
  185. package/dist/commands/user.d.ts.map +0 -1
  186. package/dist/commands/user.js +0 -96
  187. package/dist/commands/user.js.map +0 -1
  188. package/dist/commands/workspace.d.ts +0 -3
  189. package/dist/commands/workspace.d.ts.map +0 -1
  190. package/dist/commands/workspace.js +0 -89
  191. package/dist/commands/workspace.js.map +0 -1
  192. package/dist/lib/credential-manager.d.ts +0 -13
  193. package/dist/lib/credential-manager.d.ts.map +0 -1
  194. package/dist/lib/credential-manager.js +0 -58
  195. package/dist/lib/credential-manager.js.map +0 -1
  196. package/dist/lib/index.d.ts +0 -3
  197. package/dist/lib/index.d.ts.map +0 -1
  198. package/dist/lib/index.js +0 -3
  199. package/dist/lib/index.js.map +0 -1
  200. package/dist/lib/ref-manager.d.ts +0 -26
  201. package/dist/lib/ref-manager.d.ts.map +0 -1
  202. package/dist/lib/ref-manager.js +0 -92
  203. package/dist/lib/ref-manager.js.map +0 -1
  204. package/dist/lib/slack-client.d.ts +0 -37
  205. package/dist/lib/slack-client.d.ts.map +0 -1
  206. package/dist/lib/slack-client.js +0 -379
  207. package/dist/lib/slack-client.js.map +0 -1
  208. package/dist/lib/token-extractor.d.ts +0 -28
  209. package/dist/lib/token-extractor.d.ts.map +0 -1
  210. package/dist/lib/token-extractor.js +0 -401
  211. package/dist/lib/token-extractor.js.map +0 -1
  212. package/dist/src/platforms/discord/client.test.d.ts +0 -2
  213. package/dist/src/platforms/discord/client.test.d.ts.map +0 -1
  214. package/dist/src/platforms/discord/client.test.js +0 -367
  215. package/dist/src/platforms/discord/client.test.js.map +0 -1
  216. package/dist/src/platforms/discord/commands/auth.test.d.ts +0 -2
  217. package/dist/src/platforms/discord/commands/auth.test.d.ts.map +0 -1
  218. package/dist/src/platforms/discord/commands/auth.test.js +0 -65
  219. package/dist/src/platforms/discord/commands/auth.test.js.map +0 -1
  220. package/dist/src/platforms/discord/commands/channel.test.d.ts +0 -2
  221. package/dist/src/platforms/discord/commands/channel.test.d.ts.map +0 -1
  222. package/dist/src/platforms/discord/commands/channel.test.js +0 -136
  223. package/dist/src/platforms/discord/commands/channel.test.js.map +0 -1
  224. package/dist/src/platforms/discord/commands/file.test.d.ts +0 -2
  225. package/dist/src/platforms/discord/commands/file.test.d.ts.map +0 -1
  226. package/dist/src/platforms/discord/commands/file.test.js +0 -83
  227. package/dist/src/platforms/discord/commands/file.test.js.map +0 -1
  228. package/dist/src/platforms/discord/commands/guild.test.d.ts +0 -2
  229. package/dist/src/platforms/discord/commands/guild.test.d.ts.map +0 -1
  230. package/dist/src/platforms/discord/commands/guild.test.js +0 -100
  231. package/dist/src/platforms/discord/commands/guild.test.js.map +0 -1
  232. package/dist/src/platforms/discord/commands/message.test.d.ts +0 -2
  233. package/dist/src/platforms/discord/commands/message.test.d.ts.map +0 -1
  234. package/dist/src/platforms/discord/commands/message.test.js +0 -91
  235. package/dist/src/platforms/discord/commands/message.test.js.map +0 -1
  236. package/dist/src/platforms/discord/commands/reaction.test.d.ts +0 -2
  237. package/dist/src/platforms/discord/commands/reaction.test.d.ts.map +0 -1
  238. package/dist/src/platforms/discord/commands/reaction.test.js +0 -115
  239. package/dist/src/platforms/discord/commands/reaction.test.js.map +0 -1
  240. package/dist/src/platforms/discord/commands/snapshot.test.d.ts +0 -2
  241. package/dist/src/platforms/discord/commands/snapshot.test.d.ts.map +0 -1
  242. package/dist/src/platforms/discord/commands/snapshot.test.js +0 -25
  243. package/dist/src/platforms/discord/commands/snapshot.test.js.map +0 -1
  244. package/dist/src/platforms/discord/commands/user.test.d.ts +0 -2
  245. package/dist/src/platforms/discord/commands/user.test.d.ts.map +0 -1
  246. package/dist/src/platforms/discord/commands/user.test.js +0 -103
  247. package/dist/src/platforms/discord/commands/user.test.js.map +0 -1
  248. package/dist/src/platforms/discord/credential-manager.test.d.ts +0 -2
  249. package/dist/src/platforms/discord/credential-manager.test.d.ts.map +0 -1
  250. package/dist/src/platforms/discord/credential-manager.test.js +0 -136
  251. package/dist/src/platforms/discord/credential-manager.test.js.map +0 -1
  252. package/dist/src/platforms/discord/token-extractor.test.d.ts +0 -2
  253. package/dist/src/platforms/discord/token-extractor.test.d.ts.map +0 -1
  254. package/dist/src/platforms/discord/token-extractor.test.js +0 -789
  255. package/dist/src/platforms/discord/token-extractor.test.js.map +0 -1
  256. package/dist/src/platforms/discord/types.test.d.ts +0 -2
  257. package/dist/src/platforms/discord/types.test.d.ts.map +0 -1
  258. package/dist/src/platforms/discord/types.test.js +0 -211
  259. package/dist/src/platforms/discord/types.test.js.map +0 -1
  260. package/dist/src/shared/utils/concurrency.test.d.ts +0 -2
  261. package/dist/src/shared/utils/concurrency.test.d.ts.map +0 -1
  262. package/dist/src/shared/utils/concurrency.test.js +0 -39
  263. package/dist/src/shared/utils/concurrency.test.js.map +0 -1
  264. package/dist/tests/cli.test.d.ts +0 -2
  265. package/dist/tests/cli.test.d.ts.map +0 -1
  266. package/dist/tests/cli.test.js +0 -83
  267. package/dist/tests/cli.test.js.map +0 -1
  268. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/CURRENT +0 -1
  269. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOCK +0 -0
  270. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOG +0 -3
  271. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/LOG.old +0 -1
  272. package/dist/tests/commands/.test-slack-data/Local Storage/leveldb/MANIFEST-000004 +0 -0
  273. package/dist/tests/commands/auth.test.d.ts +0 -2
  274. package/dist/tests/commands/auth.test.d.ts.map +0 -1
  275. package/dist/tests/commands/auth.test.js +0 -304
  276. package/dist/tests/commands/auth.test.js.map +0 -1
  277. package/dist/tests/commands/channel.test.d.ts +0 -2
  278. package/dist/tests/commands/channel.test.d.ts.map +0 -1
  279. package/dist/tests/commands/channel.test.js +0 -166
  280. package/dist/tests/commands/channel.test.js.map +0 -1
  281. package/dist/tests/commands/file.test.d.ts +0 -2
  282. package/dist/tests/commands/file.test.d.ts.map +0 -1
  283. package/dist/tests/commands/file.test.js +0 -175
  284. package/dist/tests/commands/file.test.js.map +0 -1
  285. package/dist/tests/commands/message.test.d.ts +0 -2
  286. package/dist/tests/commands/message.test.d.ts.map +0 -1
  287. package/dist/tests/commands/message.test.js +0 -293
  288. package/dist/tests/commands/message.test.js.map +0 -1
  289. package/dist/tests/commands/reaction.test.d.ts +0 -2
  290. package/dist/tests/commands/reaction.test.d.ts.map +0 -1
  291. package/dist/tests/commands/reaction.test.js +0 -84
  292. package/dist/tests/commands/reaction.test.js.map +0 -1
  293. package/dist/tests/commands/snapshot.test.d.ts +0 -2
  294. package/dist/tests/commands/snapshot.test.d.ts.map +0 -1
  295. package/dist/tests/commands/snapshot.test.js +0 -280
  296. package/dist/tests/commands/snapshot.test.js.map +0 -1
  297. package/dist/tests/commands/user.test.d.ts +0 -2
  298. package/dist/tests/commands/user.test.d.ts.map +0 -1
  299. package/dist/tests/commands/user.test.js +0 -117
  300. package/dist/tests/commands/user.test.js.map +0 -1
  301. package/dist/tests/commands/workspace.test.d.ts +0 -2
  302. package/dist/tests/commands/workspace.test.d.ts.map +0 -1
  303. package/dist/tests/commands/workspace.test.js +0 -453
  304. package/dist/tests/commands/workspace.test.js.map +0 -1
  305. package/dist/tests/credential-manager.test.d.ts +0 -2
  306. package/dist/tests/credential-manager.test.d.ts.map +0 -1
  307. package/dist/tests/credential-manager.test.js +0 -199
  308. package/dist/tests/credential-manager.test.js.map +0 -1
  309. package/dist/tests/slack-client.test.d.ts +0 -2
  310. package/dist/tests/slack-client.test.d.ts.map +0 -1
  311. package/dist/tests/slack-client.test.js +0 -741
  312. package/dist/tests/slack-client.test.js.map +0 -1
  313. package/dist/tests/types.test.d.ts +0 -2
  314. package/dist/tests/types.test.d.ts.map +0 -1
  315. package/dist/tests/types.test.js +0 -215
  316. package/dist/tests/types.test.js.map +0 -1
  317. package/dist/types/index.d.ts +0 -369
  318. package/dist/types/index.d.ts.map +0 -1
  319. package/dist/types/index.js +0 -92
  320. package/dist/types/index.js.map +0 -1
  321. package/dist/utils/error-handler.d.ts +0 -2
  322. package/dist/utils/error-handler.d.ts.map +0 -1
  323. package/dist/utils/error-handler.js +0 -5
  324. package/dist/utils/error-handler.js.map +0 -1
  325. package/dist/utils/output.d.ts +0 -2
  326. package/dist/utils/output.d.ts.map +0 -1
  327. package/dist/utils/output.js +0 -4
  328. package/dist/utils/output.js.map +0 -1
  329. /package/dist/{cli.d.ts → src/platforms/teams/cli.d.ts} +0 -0
  330. /package/dist/{commands → src/platforms/teams/commands}/user.d.ts +0 -0
@@ -1,32 +1,23 @@
1
- import { beforeEach, describe, expect, mock, test } from 'bun:test'
2
- import { execSync, spawn } from 'node:child_process'
3
- import { existsSync, readdirSync, readFileSync } from 'node:fs'
1
+ import { afterEach, beforeEach, describe, expect, mock, spyOn, test } from 'bun:test'
4
2
  import { homedir } from 'node:os'
5
3
  import { join } from 'node:path'
6
4
 
7
- import { CDP_PORT, DiscordTokenExtractor, TOKEN_EXTRACTION_JS } from './token-extractor'
8
-
9
- // Mock modules
10
- mock.module('node:fs', () => ({
11
- existsSync: mock(() => false),
12
- readdirSync: mock(() => []),
13
- readFileSync: mock(() => Buffer.from('')),
14
- }))
15
-
16
- const mockSpawn = mock(() => ({
17
- unref: mock(() => {}),
18
- }))
19
-
20
- mock.module('node:child_process', () => ({
21
- execSync: mock(() => ''),
22
- spawn: mockSpawn,
23
- }))
5
+ import { DiscordTokenExtractor, TOKEN_EXTRACTION_JS } from './token-extractor'
24
6
 
25
7
  describe('DiscordTokenExtractor', () => {
26
8
  let extractor: DiscordTokenExtractor
9
+ let originalFetch: typeof fetch
10
+ let originalWebSocket: typeof WebSocket
27
11
 
28
12
  beforeEach(() => {
29
13
  extractor = new DiscordTokenExtractor()
14
+ originalFetch = globalThis.fetch
15
+ originalWebSocket = globalThis.WebSocket
16
+ })
17
+
18
+ afterEach(() => {
19
+ globalThis.fetch = originalFetch
20
+ globalThis.WebSocket = originalWebSocket
30
21
  })
31
22
 
32
23
  describe('getDiscordDirs', () => {
@@ -66,8 +57,7 @@ describe('DiscordTokenExtractor', () => {
66
57
 
67
58
  describe('token patterns', () => {
68
59
  test('validates standard token format (base64.base64.base64)', () => {
69
- // Token: base64(user_id).base64(timestamp).base64(hmac)
70
- const validToken = 'MTIzNDU2Nzg5MDEyMzQ1Njc4.GrE5dA.abcdefghijklmnopqrstuvwxyz1234567890'
60
+ const validToken = 'XXXXXXXXXXXXXXXXXXXXXXXX.YYYYYY.ZZZZZZZZZZZZZZZZZZZZZZZZZ'
71
61
  expect(extractor.isValidToken(validToken)).toBe(true)
72
62
  })
73
63
 
@@ -91,182 +81,79 @@ describe('DiscordTokenExtractor', () => {
91
81
 
92
82
  describe('extract', () => {
93
83
  test('returns null when no Discord directories exist on linux', async () => {
94
- const mockExistsSync = existsSync as unknown as ReturnType<typeof mock>
95
- mockExistsSync.mockImplementation(() => false)
96
-
97
84
  const linuxExtractor = new DiscordTokenExtractor('linux')
85
+ const extractFromLevelDBSpy = spyOn(
86
+ linuxExtractor as any,
87
+ 'extractFromLevelDB'
88
+ ).mockResolvedValue(null)
89
+
98
90
  const result = await linuxExtractor.extract()
99
91
  expect(result).toBeNull()
100
- })
101
92
 
102
- test('extracts token from LevelDB files on linux', async () => {
103
- const mockToken = 'MTIzNDU2Nzg5MDEyMzQ1Njc4.GrE5dA.abcdefghijklmnopqrstuvwxyz1234567890'
104
- const ldbContent = Buffer.from(`some_data"${mockToken}"more_data`)
105
-
106
- const mockExistsSync = existsSync as unknown as ReturnType<typeof mock>
107
- mockExistsSync.mockImplementation((path: string) => {
108
- if (path.includes('discord') || path.includes('leveldb')) return true
109
- if (path.includes('Local Storage')) return true
110
- return false
111
- })
112
-
113
- const mockReaddirSync = readdirSync as unknown as ReturnType<typeof mock>
114
- mockReaddirSync.mockImplementation((path: string) => {
115
- if (path.includes('leveldb')) return ['000001.ldb']
116
- if (path.includes('Local Storage')) return ['leveldb']
117
- return []
118
- })
93
+ extractFromLevelDBSpy.mockRestore()
94
+ })
119
95
 
120
- const mockReadFileSync = readFileSync as unknown as ReturnType<typeof mock>
121
- mockReadFileSync.mockImplementation(() => ldbContent)
96
+ test('extracts token from LevelDB when available', async () => {
97
+ const mockToken = 'XXXXXXXXXXXXXXXXXXXXXXXX.YYYYYY.ZZZZZZZZZZZZZZZZZZZZZZZZZ'
122
98
 
123
99
  const linuxExtractor = new DiscordTokenExtractor('linux')
100
+ const extractFromLevelDBSpy = spyOn(
101
+ linuxExtractor as any,
102
+ 'extractFromLevelDB'
103
+ ).mockResolvedValue({ token: mockToken })
104
+
124
105
  const result = await linuxExtractor.extract()
125
106
 
126
107
  expect(result).not.toBeNull()
127
108
  expect(result?.token).toBe(mockToken)
128
- })
129
-
130
- test('tries LevelDB first on macOS, CDP as fallback', async () => {
131
- const levelDbToken = 'MTIzNDU2Nzg5MDEyMzQ1Njc4.GrE5dA.leveldb_token_123456789012345'
132
- const ldbContent = Buffer.from(`some_data"${levelDbToken}"more_data`)
133
109
 
134
- const mockExistsSync = existsSync as unknown as ReturnType<typeof mock>
135
- mockExistsSync.mockImplementation((path: string) => {
136
- if (path.includes('Discord') || path.includes('leveldb')) return true
137
- if (path.includes('Local Storage')) return true
138
- return false
139
- })
140
-
141
- const mockReaddirSync = readdirSync as unknown as ReturnType<typeof mock>
142
- mockReaddirSync.mockImplementation((path: string) => {
143
- if (path.includes('leveldb')) return ['000001.ldb']
144
- if (path.includes('Local Storage')) return ['leveldb']
145
- return []
146
- })
110
+ extractFromLevelDBSpy.mockRestore()
111
+ })
147
112
 
148
- const mockReadFileSync = readFileSync as unknown as ReturnType<typeof mock>
149
- mockReadFileSync.mockImplementation(() => ldbContent)
113
+ test('tries CDP on macOS when LevelDB extraction fails', async () => {
114
+ const mockToken = 'XXXXXXXXXXXXXXXXXXXXXXXX.YYYYYY.cdp_token_12345678901234567'
150
115
 
151
116
  const darwinExtractor = new DiscordTokenExtractor('darwin', 0)
117
+ const extractFromLevelDBSpy = spyOn(
118
+ darwinExtractor as any,
119
+ 'extractFromLevelDB'
120
+ ).mockResolvedValue(null)
121
+ const tryExtractViaCDPSpy = spyOn(
122
+ darwinExtractor as any,
123
+ 'tryExtractViaCDP'
124
+ ).mockResolvedValue(mockToken)
125
+
152
126
  const result = await darwinExtractor.extract()
153
127
 
154
128
  expect(result).not.toBeNull()
155
- expect(result?.token).toBe(levelDbToken)
156
- })
157
-
158
- test('falls back to leveldb on macOS when CDP fails', async () => {
159
- const mockToken = 'MTIzNDU2Nzg5MDEyMzQ1Njc4.GrE5dA.leveldb_fallback_token_12345'
160
- const ldbContent = Buffer.from(`some_data"${mockToken}"more_data`)
161
-
162
- const originalFetch = globalThis.fetch
163
- globalThis.fetch = mock(async () => ({
164
- ok: true,
165
- json: async () => [],
166
- })) as unknown as typeof fetch
167
-
168
- const mockExistsSync = existsSync as unknown as ReturnType<typeof mock>
169
- mockExistsSync.mockImplementation((path: string) => {
170
- if (path.includes('/Applications/')) return false
171
- if (path.includes('Discord') || path.includes('leveldb')) return true
172
- if (path.includes('Local Storage')) return true
173
- return false
174
- })
175
-
176
- const mockReaddirSync = readdirSync as unknown as ReturnType<typeof mock>
177
- mockReaddirSync.mockImplementation((path: string) => {
178
- if (path.includes('leveldb')) return ['000001.ldb']
179
- if (path.includes('Local Storage')) return ['leveldb']
180
- return []
181
- })
182
-
183
- const mockReadFileSync = readFileSync as unknown as ReturnType<typeof mock>
184
- mockReadFileSync.mockImplementation(() => ldbContent)
185
-
186
- try {
187
- const darwinExtractor = new DiscordTokenExtractor('darwin', 0)
188
- const result = await darwinExtractor.extract()
129
+ expect(result?.token).toBe(mockToken)
189
130
 
190
- expect(result).not.toBeNull()
191
- expect(result?.token).toBe(mockToken)
192
- } finally {
193
- globalThis.fetch = originalFetch
194
- }
131
+ extractFromLevelDBSpy.mockRestore()
132
+ tryExtractViaCDPSpy.mockRestore()
195
133
  })
196
134
 
197
- test('returns first valid token found across variants on linux', async () => {
198
- const mockToken = 'MTIzNDU2Nzg5MDEyMzQ1Njc4.GrE5dA.first_token_found_1234567890'
199
- const ldbContent = Buffer.from(`"${mockToken}"`)
200
-
201
- const mockExistsSync = existsSync as unknown as ReturnType<typeof mock>
202
- mockExistsSync.mockImplementation(() => true)
203
-
204
- const mockReaddirSync = readdirSync as unknown as ReturnType<typeof mock>
205
- mockReaddirSync.mockImplementation((path: string) => {
206
- if (path.includes('leveldb')) return ['test.ldb']
207
- if (path.includes('Local Storage')) return ['leveldb']
208
- return []
209
- })
210
-
211
- const mockReadFileSync = readFileSync as unknown as ReturnType<typeof mock>
212
- mockReadFileSync.mockImplementation(() => ldbContent)
135
+ test('returns first valid token found across variants', async () => {
136
+ const mockToken = 'XXXXXXXXXXXXXXXXXXXXXXXX.YYYYYY.first_token_found_1234567'
213
137
 
214
138
  const linuxExtractor = new DiscordTokenExtractor('linux')
139
+ const extractFromLevelDBSpy = spyOn(
140
+ linuxExtractor as any,
141
+ 'extractFromLevelDB'
142
+ ).mockResolvedValue({ token: mockToken })
143
+
215
144
  const result = await linuxExtractor.extract()
216
145
 
217
146
  expect(result).not.toBeNull()
218
147
  expect(typeof result?.token).toBe('string')
219
- })
220
- })
221
-
222
- describe('encrypted token handling', () => {
223
- test('decrypts Windows DPAPI encrypted token', async () => {
224
- const mockExecSync = execSync as unknown as ReturnType<typeof mock>
225
- const decryptedKey = Buffer.from('0'.repeat(32), 'hex').toString('base64')
226
-
227
- mockExecSync.mockImplementation((cmd: string) => {
228
- if (cmd.includes('powershell') && cmd.includes('ProtectedData')) {
229
- return `${decryptedKey}\n`
230
- }
231
- return ''
232
- })
233
148
 
234
- const winExtractor = new DiscordTokenExtractor('win32')
235
-
236
- // Mock Local State file reading
237
- const mockReadFileSync = readFileSync as unknown as ReturnType<typeof mock>
238
- mockReadFileSync.mockImplementation((path: string) => {
239
- if (path.includes('Local State')) {
240
- return JSON.stringify({
241
- os_crypt: {
242
- encrypted_key: Buffer.from(`DPAPI${'x'.repeat(32)}`).toString('base64'),
243
- },
244
- })
245
- }
246
- return Buffer.from('')
247
- })
248
-
249
- // Test that DPAPI decryption is called
250
- const encryptedToken = `dQw4w9WgXcQ:${Buffer.from('test').toString('base64')}`
251
- expect(winExtractor.isEncryptedToken(encryptedToken)).toBe(true)
149
+ extractFromLevelDBSpy.mockRestore()
252
150
  })
151
+ })
253
152
 
254
- test('decrypts macOS Keychain encrypted token', async () => {
255
- const mockExecSync = execSync as unknown as ReturnType<typeof mock>
256
- const keychainPassword = 'test_password'
257
-
258
- mockExecSync.mockImplementation((cmd: string) => {
259
- if (cmd.includes('security find-generic-password')) {
260
- if (cmd.includes('Discord Safe Storage')) {
261
- return keychainPassword
262
- }
263
- }
264
- throw new Error('Not found')
265
- })
266
-
153
+ describe('getKeychainVariants', () => {
154
+ test('returns keychain variants for macOS', () => {
267
155
  const macExtractor = new DiscordTokenExtractor('darwin')
268
156
 
269
- // Verify keychain command patterns
270
157
  expect(macExtractor.getKeychainVariants()).toEqual([
271
158
  { service: 'discord Safe Storage', account: 'discord Key' },
272
159
  { service: 'discordcanary Safe Storage', account: 'discordcanary Key' },
@@ -297,177 +184,101 @@ describe('DiscordTokenExtractor', () => {
297
184
 
298
185
  describe('process management', () => {
299
186
  describe('isDiscordRunning', () => {
300
- test('returns true when Discord process is found on macOS', async () => {
301
- const mockExecSync = execSync as unknown as ReturnType<typeof mock>
302
- mockExecSync.mockImplementation((cmd: string) => {
303
- if (cmd.includes('pgrep') && cmd.includes('Discord')) {
304
- return '12345\n'
305
- }
306
- return ''
307
- })
308
-
187
+ test('returns true when Discord process is found', async () => {
309
188
  const darwinExtractor = new DiscordTokenExtractor('darwin', 0, 0)
189
+ const checkProcessRunningSpy = spyOn(
190
+ darwinExtractor as any,
191
+ 'checkProcessRunning'
192
+ ).mockReturnValue(true)
193
+
310
194
  const result = await darwinExtractor.isDiscordRunning('stable')
311
195
  expect(result).toBe(true)
196
+
197
+ checkProcessRunningSpy.mockRestore()
312
198
  })
313
199
 
314
200
  test('returns false when no Discord process is found', async () => {
315
- const mockExecSync = execSync as unknown as ReturnType<typeof mock>
316
- mockExecSync.mockImplementation(() => '')
317
-
318
201
  const darwinExtractor = new DiscordTokenExtractor('darwin', 0, 0)
202
+ const checkProcessRunningSpy = spyOn(
203
+ darwinExtractor as any,
204
+ 'checkProcessRunning'
205
+ ).mockReturnValue(false)
206
+
319
207
  const result = await darwinExtractor.isDiscordRunning('stable')
320
208
  expect(result).toBe(false)
209
+
210
+ checkProcessRunningSpy.mockRestore()
321
211
  })
322
212
 
323
213
  test('checks all variants when no specific variant provided', async () => {
324
- const mockExecSync = execSync as unknown as ReturnType<typeof mock>
214
+ const darwinExtractor = new DiscordTokenExtractor('darwin', 0, 0)
325
215
  const checkedProcesses: string[] = []
326
-
327
- mockExecSync.mockImplementation((cmd: string) => {
328
- if (cmd.includes('pgrep')) {
329
- const match = cmd.match(/pgrep -f "([^"]+)"/)
330
- if (match) checkedProcesses.push(match[1])
331
- }
332
- return ''
216
+ const checkProcessRunningSpy = spyOn(
217
+ darwinExtractor as any,
218
+ 'checkProcessRunning'
219
+ ).mockImplementation((name: string) => {
220
+ checkedProcesses.push(name)
221
+ return false
333
222
  })
334
223
 
335
- const darwinExtractor = new DiscordTokenExtractor('darwin', 0, 0)
336
224
  await darwinExtractor.isDiscordRunning()
337
225
 
338
226
  expect(checkedProcesses).toContain('Discord')
339
227
  expect(checkedProcesses).toContain('Discord Canary')
340
228
  expect(checkedProcesses).toContain('Discord PTB')
341
- })
342
-
343
- test('returns true when Windows process is found', async () => {
344
- const mockExecSync = execSync as unknown as ReturnType<typeof mock>
345
- mockExecSync.mockImplementation((cmd: string) => {
346
- if (cmd.includes('tasklist') && cmd.includes('Discord.exe')) {
347
- return 'Discord.exe 12345 Console 1 123,456 K\n'
348
- }
349
- return ''
350
- })
351
229
 
352
- const winExtractor = new DiscordTokenExtractor('win32', 0, 0)
353
- const result = await winExtractor.isDiscordRunning('stable')
354
- expect(result).toBe(true)
230
+ checkProcessRunningSpy.mockRestore()
355
231
  })
356
232
  })
357
233
 
358
234
  describe('killDiscord', () => {
359
- test('kills Discord process on macOS using pkill', async () => {
360
- const mockExecSync = execSync as unknown as ReturnType<typeof mock>
235
+ test('kills Discord process', async () => {
236
+ const darwinExtractor = new DiscordTokenExtractor('darwin', 0, 0)
361
237
  const killedProcesses: string[] = []
362
-
363
- mockExecSync.mockImplementation((cmd: string) => {
364
- if (cmd.includes('pkill')) {
365
- const match = cmd.match(/pkill -f "([^"]+)"/)
366
- if (match) killedProcesses.push(match[1])
238
+ const killProcessSpy = spyOn(darwinExtractor as any, 'killProcess').mockImplementation(
239
+ (name: string) => {
240
+ killedProcesses.push(name)
367
241
  }
368
- return ''
369
- })
242
+ )
370
243
 
371
- const darwinExtractor = new DiscordTokenExtractor('darwin', 0, 0)
372
244
  await darwinExtractor.killDiscord('stable')
373
245
 
374
246
  expect(killedProcesses).toContain('Discord')
375
- })
376
-
377
- test('kills Discord process on Windows using taskkill', async () => {
378
- const mockExecSync = execSync as unknown as ReturnType<typeof mock>
379
- const killedProcesses: string[] = []
380
-
381
- mockExecSync.mockImplementation((cmd: string) => {
382
- if (cmd.includes('taskkill')) {
383
- const match = cmd.match(/taskkill \/F \/IM "([^"]+)"/)
384
- if (match) killedProcesses.push(match[1])
385
- }
386
- return ''
387
- })
388
247
 
389
- const winExtractor = new DiscordTokenExtractor('win32', 0, 0)
390
- await winExtractor.killDiscord('stable')
391
-
392
- expect(killedProcesses).toContain('Discord.exe')
248
+ killProcessSpy.mockRestore()
393
249
  })
394
250
 
395
251
  test('kills all variants when no specific variant provided', async () => {
396
- const mockExecSync = execSync as unknown as ReturnType<typeof mock>
252
+ const darwinExtractor = new DiscordTokenExtractor('darwin', 0, 0)
397
253
  const killedProcesses: string[] = []
398
-
399
- mockExecSync.mockImplementation((cmd: string) => {
400
- if (cmd.includes('pkill')) {
401
- const match = cmd.match(/pkill -f "([^"]+)"/)
402
- if (match) killedProcesses.push(match[1])
254
+ const killProcessSpy = spyOn(darwinExtractor as any, 'killProcess').mockImplementation(
255
+ (name: string) => {
256
+ killedProcesses.push(name)
403
257
  }
404
- return ''
405
- })
258
+ )
406
259
 
407
- const darwinExtractor = new DiscordTokenExtractor('darwin', 0, 0)
408
260
  await darwinExtractor.killDiscord()
409
261
 
410
262
  expect(killedProcesses).toContain('Discord')
411
263
  expect(killedProcesses).toContain('Discord Canary')
412
264
  expect(killedProcesses).toContain('Discord PTB')
265
+
266
+ killProcessSpy.mockRestore()
413
267
  })
414
268
  })
415
269
 
416
270
  describe('launchDiscordWithDebug', () => {
417
271
  test('throws error when Discord app not found', async () => {
418
- const mockExistsSync = existsSync as unknown as ReturnType<typeof mock>
419
- mockExistsSync.mockImplementation(() => false)
420
-
421
272
  const darwinExtractor = new DiscordTokenExtractor('darwin', 0, 0)
273
+ const getAppPathSpy = spyOn(darwinExtractor as any, 'getAppPath').mockReturnValue(
274
+ '/nonexistent/path'
275
+ )
422
276
 
423
277
  await expect(darwinExtractor.launchDiscordWithDebug('stable')).rejects.toThrow(
424
278
  'Discord stable not found'
425
279
  )
426
- })
427
-
428
- test('launches Discord with remote debugging port on macOS', async () => {
429
- const mockExistsSync = existsSync as unknown as ReturnType<typeof mock>
430
- mockExistsSync.mockImplementation((path: string) => {
431
- return path.includes('/Applications/Discord.app')
432
- })
433
-
434
- const mockExecSync = execSync as unknown as ReturnType<typeof mock>
435
- mockExecSync.mockImplementation(() => '')
436
-
437
- let spawnedPath = ''
438
- let spawnedArgs: string[] = []
439
- const mockSpawnFn = spawn as unknown as ReturnType<typeof mock>
440
- mockSpawnFn.mockImplementation((path: string, args: string[]) => {
441
- spawnedPath = path
442
- spawnedArgs = args
443
- return { unref: () => {} }
444
- })
445
-
446
- const darwinExtractor = new DiscordTokenExtractor('darwin', 0, 0)
447
- await darwinExtractor.launchDiscordWithDebug('stable', 9222)
448
-
449
- expect(spawnedPath).toBe('/Applications/Discord.app/Contents/MacOS/Discord')
450
- expect(spawnedArgs).toContain('--remote-debugging-port=9222')
451
- })
452
-
453
- test('uses default CDP port when not specified', async () => {
454
- const mockExistsSync = existsSync as unknown as ReturnType<typeof mock>
455
- mockExistsSync.mockImplementation(() => true)
456
-
457
- const mockExecSync = execSync as unknown as ReturnType<typeof mock>
458
- mockExecSync.mockImplementation(() => '')
459
-
460
- let spawnedArgs: string[] = []
461
- const mockSpawnFn = spawn as unknown as ReturnType<typeof mock>
462
- mockSpawnFn.mockImplementation((_path: string, args: string[]) => {
463
- spawnedArgs = args
464
- return { unref: () => {} }
465
- })
466
-
467
- const darwinExtractor = new DiscordTokenExtractor('darwin', 0, 0)
468
- await darwinExtractor.launchDiscordWithDebug('stable')
469
280
 
470
- expect(spawnedArgs).toContain(`--remote-debugging-port=${CDP_PORT}`)
281
+ getAppPathSpy.mockRestore()
471
282
  })
472
283
  })
473
284
  })
@@ -475,18 +286,13 @@ describe('DiscordTokenExtractor', () => {
475
286
  describe('CDP client methods', () => {
476
287
  describe('discoverCDPTargets', () => {
477
288
  test('returns empty array when CDP endpoint is not reachable', async () => {
478
- const originalFetch = globalThis.fetch
479
289
  globalThis.fetch = mock(async () => {
480
290
  throw new Error('Connection refused')
481
291
  }) as unknown as typeof fetch
482
292
 
483
- try {
484
- const extractor = new DiscordTokenExtractor('darwin')
485
- const targets = await extractor.discoverCDPTargets(19999)
486
- expect(targets).toEqual([])
487
- } finally {
488
- globalThis.fetch = originalFetch
489
- }
293
+ const extractor = new DiscordTokenExtractor('darwin')
294
+ const targets = await extractor.discoverCDPTargets(19999)
295
+ expect(targets).toEqual([])
490
296
  })
491
297
 
492
298
  test('returns targets from CDP endpoint', async () => {
@@ -500,35 +306,25 @@ describe('DiscordTokenExtractor', () => {
500
306
  },
501
307
  ]
502
308
 
503
- const originalFetch = globalThis.fetch
504
309
  globalThis.fetch = mock(async () => ({
505
310
  ok: true,
506
311
  json: async () => mockTargets,
507
312
  })) as unknown as typeof fetch
508
313
 
509
- try {
510
- const extractor = new DiscordTokenExtractor('darwin')
511
- const targets = await extractor.discoverCDPTargets(9222)
512
- expect(targets).toEqual(mockTargets)
513
- } finally {
514
- globalThis.fetch = originalFetch
515
- }
314
+ const extractor = new DiscordTokenExtractor('darwin')
315
+ const targets = await extractor.discoverCDPTargets(9222)
316
+ expect(targets).toEqual(mockTargets)
516
317
  })
517
318
 
518
319
  test('returns empty array on HTTP error', async () => {
519
- const originalFetch = globalThis.fetch
520
320
  globalThis.fetch = mock(async () => ({
521
321
  ok: false,
522
322
  status: 500,
523
323
  })) as unknown as typeof fetch
524
324
 
525
- try {
526
- const extractor = new DiscordTokenExtractor('darwin')
527
- const targets = await extractor.discoverCDPTargets(9222)
528
- expect(targets).toEqual([])
529
- } finally {
530
- globalThis.fetch = originalFetch
531
- }
325
+ const extractor = new DiscordTokenExtractor('darwin')
326
+ const targets = await extractor.discoverCDPTargets(9222)
327
+ expect(targets).toEqual([])
532
328
  })
533
329
  })
534
330
 
@@ -630,19 +426,14 @@ describe('DiscordTokenExtractor', () => {
630
426
  close() {}
631
427
  }
632
428
 
633
- const originalWebSocket = globalThis.WebSocket
634
429
  globalThis.WebSocket = mockWebSocket as unknown as typeof WebSocket
635
430
 
636
- try {
637
- const extractor = new DiscordTokenExtractor('darwin')
638
- const result = await extractor.executeJSViaCDP(
639
- 'ws://localhost:9222/devtools/page/1',
640
- TOKEN_EXTRACTION_JS
641
- )
642
- expect(result).toBe(mockToken)
643
- } finally {
644
- globalThis.WebSocket = originalWebSocket
645
- }
431
+ const extractor = new DiscordTokenExtractor('darwin')
432
+ const result = await extractor.executeJSViaCDP(
433
+ 'ws://localhost:9222/devtools/page/1',
434
+ TOKEN_EXTRACTION_JS
435
+ )
436
+ expect(result).toBe(mockToken)
646
437
  })
647
438
 
648
439
  test('rejects on CDP error response', async () => {
@@ -672,17 +463,12 @@ describe('DiscordTokenExtractor', () => {
672
463
  close() {}
673
464
  }
674
465
 
675
- const originalWebSocket = globalThis.WebSocket
676
466
  globalThis.WebSocket = mockWebSocket as unknown as typeof WebSocket
677
467
 
678
- try {
679
- const extractor = new DiscordTokenExtractor('darwin')
680
- await expect(
681
- extractor.executeJSViaCDP('ws://localhost:9222/devtools/page/1', TOKEN_EXTRACTION_JS)
682
- ).rejects.toThrow('Evaluation failed')
683
- } finally {
684
- globalThis.WebSocket = originalWebSocket
685
- }
468
+ const extractor = new DiscordTokenExtractor('darwin')
469
+ await expect(
470
+ extractor.executeJSViaCDP('ws://localhost:9222/devtools/page/1', TOKEN_EXTRACTION_JS)
471
+ ).rejects.toThrow('Evaluation failed')
686
472
  })
687
473
 
688
474
  test('rejects on WebSocket error', async () => {
@@ -701,39 +487,28 @@ describe('DiscordTokenExtractor', () => {
701
487
  close() {}
702
488
  }
703
489
 
704
- const originalWebSocket = globalThis.WebSocket
705
490
  globalThis.WebSocket = mockWebSocket as unknown as typeof WebSocket
706
491
 
707
- try {
708
- const extractor = new DiscordTokenExtractor('darwin')
709
- await expect(
710
- extractor.executeJSViaCDP('ws://localhost:9222/devtools/page/1', TOKEN_EXTRACTION_JS)
711
- ).rejects.toThrow()
712
- } finally {
713
- globalThis.WebSocket = originalWebSocket
714
- }
492
+ const extractor = new DiscordTokenExtractor('darwin')
493
+ await expect(
494
+ extractor.executeJSViaCDP('ws://localhost:9222/devtools/page/1', TOKEN_EXTRACTION_JS)
495
+ ).rejects.toThrow()
715
496
  })
716
497
  })
717
498
 
718
499
  describe('extractViaCDP', () => {
719
500
  test('returns null when no CDP targets available', async () => {
720
- const originalFetch = globalThis.fetch
721
501
  globalThis.fetch = mock(async () => ({
722
502
  ok: true,
723
503
  json: async () => [],
724
504
  })) as unknown as typeof fetch
725
505
 
726
- try {
727
- const extractor = new DiscordTokenExtractor('darwin')
728
- const result = await extractor.extractViaCDP(9222)
729
- expect(result).toBeNull()
730
- } finally {
731
- globalThis.fetch = originalFetch
732
- }
506
+ const extractor = new DiscordTokenExtractor('darwin')
507
+ const result = await extractor.extractViaCDP(9222)
508
+ expect(result).toBeNull()
733
509
  })
734
510
 
735
511
  test('returns null when no Discord page target found', async () => {
736
- const originalFetch = globalThis.fetch
737
512
  globalThis.fetch = mock(async () => ({
738
513
  ok: true,
739
514
  json: async () => [
@@ -747,19 +522,14 @@ describe('DiscordTokenExtractor', () => {
747
522
  ],
748
523
  })) as unknown as typeof fetch
749
524
 
750
- try {
751
- const extractor = new DiscordTokenExtractor('darwin')
752
- const result = await extractor.extractViaCDP(9222)
753
- expect(result).toBeNull()
754
- } finally {
755
- globalThis.fetch = originalFetch
756
- }
525
+ const extractor = new DiscordTokenExtractor('darwin')
526
+ const result = await extractor.extractViaCDP(9222)
527
+ expect(result).toBeNull()
757
528
  })
758
529
 
759
530
  test('extracts token via CDP when Discord is running with debug port', async () => {
760
- const mockToken = 'MTIzNDU2Nzg5MDEyMzQ1Njc4.GrE5dA.abcdefghijklmnopqrstuvwxyz1234567890'
531
+ const mockToken = 'XXXXXXXXXXXXXXXXXXXXXXXX.YYYYYY.ZZZZZZZZZZZZZZZZZZZZZZZZZ'
761
532
 
762
- const originalFetch = globalThis.fetch
763
533
  globalThis.fetch = mock(async () => ({
764
534
  ok: true,
765
535
  json: async () => [
@@ -797,21 +567,14 @@ describe('DiscordTokenExtractor', () => {
797
567
  close() {}
798
568
  }
799
569
 
800
- const originalWebSocket = globalThis.WebSocket
801
570
  globalThis.WebSocket = mockWebSocket as unknown as typeof WebSocket
802
571
 
803
- try {
804
- const extractor = new DiscordTokenExtractor('darwin')
805
- const result = await extractor.extractViaCDP(9222)
806
- expect(result).toBe(mockToken)
807
- } finally {
808
- globalThis.fetch = originalFetch
809
- globalThis.WebSocket = originalWebSocket
810
- }
572
+ const extractor = new DiscordTokenExtractor('darwin')
573
+ const result = await extractor.extractViaCDP(9222)
574
+ expect(result).toBe(mockToken)
811
575
  })
812
576
 
813
577
  test('returns null when token extraction JS fails', async () => {
814
- const originalFetch = globalThis.fetch
815
578
  globalThis.fetch = mock(async () => ({
816
579
  ok: true,
817
580
  json: async () => [
@@ -849,21 +612,14 @@ describe('DiscordTokenExtractor', () => {
849
612
  close() {}
850
613
  }
851
614
 
852
- const originalWebSocket = globalThis.WebSocket
853
615
  globalThis.WebSocket = mockWebSocket as unknown as typeof WebSocket
854
616
 
855
- try {
856
- const extractor = new DiscordTokenExtractor('darwin')
857
- const result = await extractor.extractViaCDP(9222)
858
- expect(result).toBeNull()
859
- } finally {
860
- globalThis.fetch = originalFetch
861
- globalThis.WebSocket = originalWebSocket
862
- }
617
+ const extractor = new DiscordTokenExtractor('darwin')
618
+ const result = await extractor.extractViaCDP(9222)
619
+ expect(result).toBeNull()
863
620
  })
864
621
 
865
622
  test('returns null when returned value is not a valid token', async () => {
866
- const originalFetch = globalThis.fetch
867
623
  globalThis.fetch = mock(async () => ({
868
624
  ok: true,
869
625
  json: async () => [
@@ -901,17 +657,11 @@ describe('DiscordTokenExtractor', () => {
901
657
  close() {}
902
658
  }
903
659
 
904
- const originalWebSocket = globalThis.WebSocket
905
660
  globalThis.WebSocket = mockWebSocket as unknown as typeof WebSocket
906
661
 
907
- try {
908
- const extractor = new DiscordTokenExtractor('darwin')
909
- const result = await extractor.extractViaCDP(9222)
910
- expect(result).toBeNull()
911
- } finally {
912
- globalThis.fetch = originalFetch
913
- globalThis.WebSocket = originalWebSocket
914
- }
662
+ const extractor = new DiscordTokenExtractor('darwin')
663
+ const result = await extractor.extractViaCDP(9222)
664
+ expect(result).toBeNull()
915
665
  })
916
666
  })
917
667
  })