@lhremote/core 0.6.0 → 0.8.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 (356) hide show
  1. package/README.md +39 -0
  2. package/dist/cdp/client.d.ts +5 -1
  3. package/dist/cdp/client.d.ts.map +1 -1
  4. package/dist/cdp/client.js +11 -3
  5. package/dist/cdp/client.js.map +1 -1
  6. package/dist/data/index.d.ts +1 -0
  7. package/dist/data/index.d.ts.map +1 -1
  8. package/dist/data/index.js +1 -0
  9. package/dist/data/index.js.map +1 -1
  10. package/dist/data/linkedin-reference.d.ts +44 -0
  11. package/dist/data/linkedin-reference.d.ts.map +1 -0
  12. package/dist/data/linkedin-reference.js +316 -0
  13. package/dist/data/linkedin-reference.js.map +1 -0
  14. package/dist/data/linkedin-reference.test.d.ts +2 -0
  15. package/dist/data/linkedin-reference.test.d.ts.map +1 -0
  16. package/dist/data/linkedin-reference.test.js +124 -0
  17. package/dist/data/linkedin-reference.test.js.map +1 -0
  18. package/dist/db/index.d.ts +1 -1
  19. package/dist/db/index.d.ts.map +1 -1
  20. package/dist/db/index.js +1 -1
  21. package/dist/db/index.js.map +1 -1
  22. package/dist/db/repositories/action-budget.d.ts +29 -0
  23. package/dist/db/repositories/action-budget.d.ts.map +1 -0
  24. package/dist/db/repositories/action-budget.js +100 -0
  25. package/dist/db/repositories/action-budget.js.map +1 -0
  26. package/dist/db/repositories/action-budget.test.d.ts +2 -0
  27. package/dist/db/repositories/action-budget.test.d.ts.map +1 -0
  28. package/dist/db/repositories/action-budget.test.js +181 -0
  29. package/dist/db/repositories/action-budget.test.js.map +1 -0
  30. package/dist/db/repositories/campaign-hard-delete.integration.test.d.ts +2 -0
  31. package/dist/db/repositories/campaign-hard-delete.integration.test.d.ts.map +1 -0
  32. package/dist/db/repositories/campaign-hard-delete.integration.test.js +78 -0
  33. package/dist/db/repositories/campaign-hard-delete.integration.test.js.map +1 -0
  34. package/dist/db/repositories/campaign.d.ts +14 -0
  35. package/dist/db/repositories/campaign.d.ts.map +1 -1
  36. package/dist/db/repositories/campaign.js +125 -0
  37. package/dist/db/repositories/campaign.js.map +1 -1
  38. package/dist/db/repositories/index.d.ts +1 -0
  39. package/dist/db/repositories/index.d.ts.map +1 -1
  40. package/dist/db/repositories/index.js +1 -0
  41. package/dist/db/repositories/index.js.map +1 -1
  42. package/dist/index.d.ts +6 -5
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +28 -6
  45. package/dist/index.js.map +1 -1
  46. package/dist/linkedin/__tests__/dom-automation.integration.test.d.ts +2 -0
  47. package/dist/linkedin/__tests__/dom-automation.integration.test.d.ts.map +1 -0
  48. package/dist/linkedin/__tests__/dom-automation.integration.test.js +160 -0
  49. package/dist/linkedin/__tests__/dom-automation.integration.test.js.map +1 -0
  50. package/dist/linkedin/__tests__/selectors.integration.test.d.ts +2 -0
  51. package/dist/linkedin/__tests__/selectors.integration.test.d.ts.map +1 -0
  52. package/dist/linkedin/__tests__/selectors.integration.test.js +258 -0
  53. package/dist/linkedin/__tests__/selectors.integration.test.js.map +1 -0
  54. package/dist/linkedin/dom-automation.d.ts +67 -0
  55. package/dist/linkedin/dom-automation.d.ts.map +1 -0
  56. package/dist/linkedin/dom-automation.js +139 -0
  57. package/dist/linkedin/dom-automation.js.map +1 -0
  58. package/dist/linkedin/index.d.ts +3 -0
  59. package/dist/linkedin/index.d.ts.map +1 -0
  60. package/dist/linkedin/index.js +5 -0
  61. package/dist/linkedin/index.js.map +1 -0
  62. package/dist/linkedin/selectors.d.ts +67 -0
  63. package/dist/linkedin/selectors.d.ts.map +1 -0
  64. package/dist/linkedin/selectors.js +74 -0
  65. package/dist/linkedin/selectors.js.map +1 -0
  66. package/dist/operations/build-linkedin-url.d.ts +39 -0
  67. package/dist/operations/build-linkedin-url.d.ts.map +1 -0
  68. package/dist/operations/build-linkedin-url.js +72 -0
  69. package/dist/operations/build-linkedin-url.js.map +1 -0
  70. package/dist/operations/campaign-delete.d.ts +6 -2
  71. package/dist/operations/campaign-delete.d.ts.map +1 -1
  72. package/dist/operations/campaign-delete.js +9 -2
  73. package/dist/operations/campaign-delete.js.map +1 -1
  74. package/dist/operations/campaign-delete.test.js +41 -1
  75. package/dist/operations/campaign-delete.test.js.map +1 -1
  76. package/dist/operations/campaign-erase.d.ts +19 -0
  77. package/dist/operations/campaign-erase.d.ts.map +1 -0
  78. package/dist/operations/campaign-erase.js +22 -0
  79. package/dist/operations/campaign-erase.js.map +1 -0
  80. package/dist/operations/campaign-erase.test.d.ts +2 -0
  81. package/dist/operations/campaign-erase.test.d.ts.map +1 -0
  82. package/dist/operations/campaign-erase.test.js +101 -0
  83. package/dist/operations/campaign-erase.test.js.map +1 -0
  84. package/dist/operations/comment-on-post.d.ts +34 -0
  85. package/dist/operations/comment-on-post.d.ts.map +1 -0
  86. package/dist/operations/comment-on-post.js +108 -0
  87. package/dist/operations/comment-on-post.js.map +1 -0
  88. package/dist/operations/comment-on-post.test.d.ts +2 -0
  89. package/dist/operations/comment-on-post.test.d.ts.map +1 -0
  90. package/dist/operations/comment-on-post.test.js +240 -0
  91. package/dist/operations/comment-on-post.test.js.map +1 -0
  92. package/dist/operations/dismiss-errors.d.ts +22 -0
  93. package/dist/operations/dismiss-errors.d.ts.map +1 -0
  94. package/dist/operations/dismiss-errors.js +55 -0
  95. package/dist/operations/dismiss-errors.js.map +1 -0
  96. package/dist/operations/dismiss-errors.test.d.ts +2 -0
  97. package/dist/operations/dismiss-errors.test.d.ts.map +1 -0
  98. package/dist/operations/dismiss-errors.test.js +136 -0
  99. package/dist/operations/dismiss-errors.test.js.map +1 -0
  100. package/dist/operations/endorse-skills.d.ts +10 -0
  101. package/dist/operations/endorse-skills.d.ts.map +1 -0
  102. package/dist/operations/endorse-skills.js +12 -0
  103. package/dist/operations/endorse-skills.js.map +1 -0
  104. package/dist/operations/enrich-profile.d.ts +18 -0
  105. package/dist/operations/enrich-profile.d.ts.map +1 -0
  106. package/dist/operations/enrich-profile.js +15 -0
  107. package/dist/operations/enrich-profile.js.map +1 -0
  108. package/dist/operations/ephemeral-action.d.ts +22 -0
  109. package/dist/operations/ephemeral-action.d.ts.map +1 -0
  110. package/dist/operations/ephemeral-action.js +31 -0
  111. package/dist/operations/ephemeral-action.js.map +1 -0
  112. package/dist/operations/follow-person.d.ts +9 -0
  113. package/dist/operations/follow-person.d.ts.map +1 -0
  114. package/dist/operations/follow-person.js +11 -0
  115. package/dist/operations/follow-person.js.map +1 -0
  116. package/dist/operations/get-action-budget.d.ts +6 -0
  117. package/dist/operations/get-action-budget.d.ts.map +1 -0
  118. package/dist/operations/get-action-budget.js +22 -0
  119. package/dist/operations/get-action-budget.js.map +1 -0
  120. package/dist/operations/get-action-budget.test.d.ts +2 -0
  121. package/dist/operations/get-action-budget.test.d.ts.map +1 -0
  122. package/dist/operations/get-action-budget.test.js +79 -0
  123. package/dist/operations/get-action-budget.test.js.map +1 -0
  124. package/dist/operations/get-errors.d.ts +9 -3
  125. package/dist/operations/get-errors.d.ts.map +1 -1
  126. package/dist/operations/get-errors.js +41 -4
  127. package/dist/operations/get-errors.js.map +1 -1
  128. package/dist/operations/get-errors.test.js +108 -42
  129. package/dist/operations/get-errors.test.js.map +1 -1
  130. package/dist/operations/get-feed.d.ts +33 -0
  131. package/dist/operations/get-feed.d.ts.map +1 -0
  132. package/dist/operations/get-feed.js +220 -0
  133. package/dist/operations/get-feed.js.map +1 -0
  134. package/dist/operations/get-feed.test.d.ts +2 -0
  135. package/dist/operations/get-feed.test.d.ts.map +1 -0
  136. package/dist/operations/get-feed.test.js +276 -0
  137. package/dist/operations/get-feed.test.js.map +1 -0
  138. package/dist/operations/get-post-engagers.d.ts +40 -0
  139. package/dist/operations/get-post-engagers.d.ts.map +1 -0
  140. package/dist/operations/get-post-engagers.js +128 -0
  141. package/dist/operations/get-post-engagers.js.map +1 -0
  142. package/dist/operations/get-post-engagers.test.d.ts +2 -0
  143. package/dist/operations/get-post-engagers.test.d.ts.map +1 -0
  144. package/dist/operations/get-post-engagers.test.js +19 -0
  145. package/dist/operations/get-post-engagers.test.js.map +1 -0
  146. package/dist/operations/get-post-stats.d.ts +38 -0
  147. package/dist/operations/get-post-stats.d.ts.map +1 -0
  148. package/dist/operations/get-post-stats.js +100 -0
  149. package/dist/operations/get-post-stats.js.map +1 -0
  150. package/dist/operations/get-post-stats.test.d.ts +2 -0
  151. package/dist/operations/get-post-stats.test.d.ts.map +1 -0
  152. package/dist/operations/get-post-stats.test.js +34 -0
  153. package/dist/operations/get-post-stats.test.js.map +1 -0
  154. package/dist/operations/get-post.d.ts +183 -0
  155. package/dist/operations/get-post.d.ts.map +1 -0
  156. package/dist/operations/get-post.js +270 -0
  157. package/dist/operations/get-post.js.map +1 -0
  158. package/dist/operations/get-post.test.d.ts +2 -0
  159. package/dist/operations/get-post.test.d.ts.map +1 -0
  160. package/dist/operations/get-post.test.js +449 -0
  161. package/dist/operations/get-post.test.js.map +1 -0
  162. package/dist/operations/get-profile-activity.d.ts +129 -0
  163. package/dist/operations/get-profile-activity.d.ts.map +1 -0
  164. package/dist/operations/get-profile-activity.js +181 -0
  165. package/dist/operations/get-profile-activity.js.map +1 -0
  166. package/dist/operations/get-profile-activity.test.d.ts +2 -0
  167. package/dist/operations/get-profile-activity.test.d.ts.map +1 -0
  168. package/dist/operations/get-profile-activity.test.js +205 -0
  169. package/dist/operations/get-profile-activity.test.js.map +1 -0
  170. package/dist/operations/get-throttle-status.d.ts +6 -0
  171. package/dist/operations/get-throttle-status.d.ts.map +1 -0
  172. package/dist/operations/get-throttle-status.js +30 -0
  173. package/dist/operations/get-throttle-status.js.map +1 -0
  174. package/dist/operations/get-throttle-status.test.d.ts +2 -0
  175. package/dist/operations/get-throttle-status.test.d.ts.map +1 -0
  176. package/dist/operations/get-throttle-status.test.js +62 -0
  177. package/dist/operations/get-throttle-status.test.js.map +1 -0
  178. package/dist/operations/index.d.ts +24 -0
  179. package/dist/operations/index.d.ts.map +1 -1
  180. package/dist/operations/index.js +35 -0
  181. package/dist/operations/index.js.map +1 -1
  182. package/dist/operations/like-person-posts.d.ts +14 -0
  183. package/dist/operations/like-person-posts.d.ts.map +1 -0
  184. package/dist/operations/like-person-posts.js +28 -0
  185. package/dist/operations/like-person-posts.js.map +1 -0
  186. package/dist/operations/message-person.d.ts +11 -0
  187. package/dist/operations/message-person.d.ts.map +1 -0
  188. package/dist/operations/message-person.js +19 -0
  189. package/dist/operations/message-person.js.map +1 -0
  190. package/dist/operations/react-to-post.d.ts +38 -0
  191. package/dist/operations/react-to-post.d.ts.map +1 -0
  192. package/dist/operations/react-to-post.js +82 -0
  193. package/dist/operations/react-to-post.js.map +1 -0
  194. package/dist/operations/react-to-post.test.d.ts +2 -0
  195. package/dist/operations/react-to-post.test.d.ts.map +1 -0
  196. package/dist/operations/react-to-post.test.js +154 -0
  197. package/dist/operations/react-to-post.test.js.map +1 -0
  198. package/dist/operations/remove-connection.d.ts +6 -0
  199. package/dist/operations/remove-connection.d.ts.map +1 -0
  200. package/dist/operations/remove-connection.js +7 -0
  201. package/dist/operations/remove-connection.js.map +1 -0
  202. package/dist/operations/resolve-linkedin-entity.d.ts +33 -0
  203. package/dist/operations/resolve-linkedin-entity.d.ts.map +1 -0
  204. package/dist/operations/resolve-linkedin-entity.js +198 -0
  205. package/dist/operations/resolve-linkedin-entity.js.map +1 -0
  206. package/dist/operations/search-posts.d.ts +143 -0
  207. package/dist/operations/search-posts.d.ts.map +1 -0
  208. package/dist/operations/search-posts.js +220 -0
  209. package/dist/operations/search-posts.js.map +1 -0
  210. package/dist/operations/search-posts.test.d.ts +2 -0
  211. package/dist/operations/search-posts.test.d.ts.map +1 -0
  212. package/dist/operations/search-posts.test.js +261 -0
  213. package/dist/operations/search-posts.test.js.map +1 -0
  214. package/dist/operations/send-inmail.d.ts +11 -0
  215. package/dist/operations/send-inmail.d.ts.map +1 -0
  216. package/dist/operations/send-inmail.js +19 -0
  217. package/dist/operations/send-inmail.js.map +1 -0
  218. package/dist/operations/send-invite.d.ts +9 -0
  219. package/dist/operations/send-invite.d.ts.map +1 -0
  220. package/dist/operations/send-invite.js +14 -0
  221. package/dist/operations/send-invite.js.map +1 -0
  222. package/dist/operations/visit-profile.d.ts +14 -0
  223. package/dist/operations/visit-profile.d.ts.map +1 -0
  224. package/dist/operations/visit-profile.js +49 -0
  225. package/dist/operations/visit-profile.js.map +1 -0
  226. package/dist/operations/visit-profile.test.d.ts +2 -0
  227. package/dist/operations/visit-profile.test.d.ts.map +1 -0
  228. package/dist/operations/visit-profile.test.js +193 -0
  229. package/dist/operations/visit-profile.test.js.map +1 -0
  230. package/dist/services/app.d.ts.map +1 -1
  231. package/dist/services/app.js +37 -12
  232. package/dist/services/app.js.map +1 -1
  233. package/dist/services/app.test.js +57 -0
  234. package/dist/services/app.test.js.map +1 -1
  235. package/dist/services/boolean-expression.d.ts +29 -0
  236. package/dist/services/boolean-expression.d.ts.map +1 -0
  237. package/dist/services/boolean-expression.js +79 -0
  238. package/dist/services/boolean-expression.js.map +1 -0
  239. package/dist/services/boolean-expression.test.d.ts +2 -0
  240. package/dist/services/boolean-expression.test.d.ts.map +1 -0
  241. package/dist/services/boolean-expression.test.js +64 -0
  242. package/dist/services/boolean-expression.test.js.map +1 -0
  243. package/dist/services/campaign.d.ts +10 -0
  244. package/dist/services/campaign.d.ts.map +1 -1
  245. package/dist/services/campaign.js +16 -0
  246. package/dist/services/campaign.js.map +1 -1
  247. package/dist/services/collection.d.ts +5 -2
  248. package/dist/services/collection.d.ts.map +1 -1
  249. package/dist/services/collection.js +33 -5
  250. package/dist/services/collection.js.map +1 -1
  251. package/dist/services/collection.test.js +64 -6
  252. package/dist/services/collection.test.js.map +1 -1
  253. package/dist/services/ephemeral-campaign.d.ts +64 -0
  254. package/dist/services/ephemeral-campaign.d.ts.map +1 -0
  255. package/dist/services/ephemeral-campaign.js +210 -0
  256. package/dist/services/ephemeral-campaign.js.map +1 -0
  257. package/dist/services/ephemeral-campaign.test.d.ts +2 -0
  258. package/dist/services/ephemeral-campaign.test.d.ts.map +1 -0
  259. package/dist/services/ephemeral-campaign.test.js +333 -0
  260. package/dist/services/ephemeral-campaign.test.js.map +1 -0
  261. package/dist/services/errors.d.ts +21 -0
  262. package/dist/services/errors.d.ts.map +1 -1
  263. package/dist/services/errors.js +35 -0
  264. package/dist/services/errors.js.map +1 -1
  265. package/dist/services/index.d.ts +7 -1
  266. package/dist/services/index.d.ts.map +1 -1
  267. package/dist/services/index.js +7 -1
  268. package/dist/services/index.js.map +1 -1
  269. package/dist/services/instance-context.d.ts.map +1 -1
  270. package/dist/services/instance-context.js +9 -1
  271. package/dist/services/instance-context.js.map +1 -1
  272. package/dist/services/instance-context.test.js +77 -1
  273. package/dist/services/instance-context.test.js.map +1 -1
  274. package/dist/services/instance.d.ts +43 -0
  275. package/dist/services/instance.d.ts.map +1 -1
  276. package/dist/services/instance.js +151 -0
  277. package/dist/services/instance.js.map +1 -1
  278. package/dist/services/instance.test.js +101 -0
  279. package/dist/services/instance.test.js.map +1 -1
  280. package/dist/services/launcher.d.ts +23 -0
  281. package/dist/services/launcher.d.ts.map +1 -1
  282. package/dist/services/launcher.js +81 -11
  283. package/dist/services/launcher.js.map +1 -1
  284. package/dist/services/launcher.test.js +109 -42
  285. package/dist/services/launcher.test.js.map +1 -1
  286. package/dist/services/sn-url-builder.d.ts +21 -0
  287. package/dist/services/sn-url-builder.d.ts.map +1 -0
  288. package/dist/services/sn-url-builder.js +132 -0
  289. package/dist/services/sn-url-builder.js.map +1 -0
  290. package/dist/services/sn-url-builder.test.d.ts +2 -0
  291. package/dist/services/sn-url-builder.test.d.ts.map +1 -0
  292. package/dist/services/sn-url-builder.test.js +130 -0
  293. package/dist/services/sn-url-builder.test.js.map +1 -0
  294. package/dist/services/url-builder.d.ts +12 -0
  295. package/dist/services/url-builder.d.ts.map +1 -0
  296. package/dist/services/url-builder.js +100 -0
  297. package/dist/services/url-builder.js.map +1 -0
  298. package/dist/services/url-builder.test.d.ts +2 -0
  299. package/dist/services/url-builder.test.d.ts.map +1 -0
  300. package/dist/services/url-builder.test.js +79 -0
  301. package/dist/services/url-builder.test.js.map +1 -0
  302. package/dist/services/url-templates.d.ts +41 -0
  303. package/dist/services/url-templates.d.ts.map +1 -0
  304. package/dist/services/url-templates.js +118 -0
  305. package/dist/services/url-templates.js.map +1 -0
  306. package/dist/services/url-templates.test.d.ts +2 -0
  307. package/dist/services/url-templates.test.d.ts.map +1 -0
  308. package/dist/services/url-templates.test.js +159 -0
  309. package/dist/services/url-templates.test.js.map +1 -0
  310. package/dist/types/action-budget.d.ts +52 -0
  311. package/dist/types/action-budget.d.ts.map +1 -0
  312. package/dist/types/action-budget.js +4 -0
  313. package/dist/types/action-budget.js.map +1 -0
  314. package/dist/types/campaign.d.ts +24 -0
  315. package/dist/types/campaign.d.ts.map +1 -1
  316. package/dist/types/feed.d.ts +32 -0
  317. package/dist/types/feed.d.ts.map +1 -0
  318. package/dist/types/feed.js +4 -0
  319. package/dist/types/feed.js.map +1 -0
  320. package/dist/types/index.d.ts +8 -2
  321. package/dist/types/index.d.ts.map +1 -1
  322. package/dist/types/linkedin-url.d.ts +109 -0
  323. package/dist/types/linkedin-url.d.ts.map +1 -0
  324. package/dist/types/linkedin-url.js +4 -0
  325. package/dist/types/linkedin-url.js.map +1 -0
  326. package/dist/types/post-analytics.d.ts +40 -0
  327. package/dist/types/post-analytics.d.ts.map +1 -0
  328. package/dist/types/post-analytics.js +4 -0
  329. package/dist/types/post-analytics.js.map +1 -0
  330. package/dist/types/post.d.ts +43 -0
  331. package/dist/types/post.d.ts.map +1 -0
  332. package/dist/types/post.js +4 -0
  333. package/dist/types/post.js.map +1 -0
  334. package/dist/types/search-posts.d.ts +22 -0
  335. package/dist/types/search-posts.d.ts.map +1 -0
  336. package/dist/types/search-posts.js +4 -0
  337. package/dist/types/search-posts.js.map +1 -0
  338. package/dist/types/ui-health.d.ts +16 -0
  339. package/dist/types/ui-health.d.ts.map +1 -1
  340. package/dist/voyager/index.d.ts +2 -0
  341. package/dist/voyager/index.d.ts.map +1 -0
  342. package/dist/voyager/index.js +4 -0
  343. package/dist/voyager/index.js.map +1 -0
  344. package/dist/voyager/interceptor.d.ts +100 -0
  345. package/dist/voyager/interceptor.d.ts.map +1 -0
  346. package/dist/voyager/interceptor.integration.test.d.ts +2 -0
  347. package/dist/voyager/interceptor.integration.test.d.ts.map +1 -0
  348. package/dist/voyager/interceptor.integration.test.js +89 -0
  349. package/dist/voyager/interceptor.integration.test.js.map +1 -0
  350. package/dist/voyager/interceptor.js +235 -0
  351. package/dist/voyager/interceptor.js.map +1 -0
  352. package/dist/voyager/interceptor.test.d.ts +2 -0
  353. package/dist/voyager/interceptor.test.d.ts.map +1 -0
  354. package/dist/voyager/interceptor.test.js +372 -0
  355. package/dist/voyager/interceptor.test.js.map +1 -0
  356. package/package.json +1 -1
@@ -0,0 +1,258 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { afterAll, beforeAll, describe, expect, it } from "vitest";
4
+ import { CDPClient } from "../../cdp/client.js";
5
+ import { discoverTargets } from "../../cdp/discovery.js";
6
+ import { discoverInstancePort, killInstanceProcesses, } from "../../cdp/instance-discovery.js";
7
+ import { startInstanceWithRecovery, waitForInstanceShutdown, } from "../../services/instance-lifecycle.js";
8
+ import { LauncherService } from "../../services/launcher.js";
9
+ import { describeE2E, launchApp, quitApp, retryAsync, } from "../../testing/e2e-helpers.js";
10
+ import { delay } from "../../utils/delay.js";
11
+ import { COMMENT_INPUT, COMMENT_SUBMIT_BUTTON, FEED_POST_CONTAINER, PAGINATION_TRIGGER, POST_AUTHOR_INFO, POST_AUTHOR_NAME, POST_TEXT_CONTENT, REACTION_CELEBRATE, REACTION_FUNNY, REACTION_INSIGHTFUL, REACTION_LIKE, REACTION_LOVE, REACTION_SUPPORT, REACTION_TRIGGER, REACTIONS_MENU, SCROLL_CONTAINER, SELECTORS, } from "../selectors.js";
12
+ /**
13
+ * Query the number of elements matching a CSS selector in the LinkedIn
14
+ * WebView via CDP `Runtime.evaluate`.
15
+ */
16
+ async function queryCount(client, selector) {
17
+ return client.evaluate(`document.querySelectorAll(${JSON.stringify(selector)}).length`);
18
+ }
19
+ /**
20
+ * Dispatch a `mouseenter` + `mouseover` sequence on the first element
21
+ * matching `selector` to trigger hover-dependent UI (e.g. reactions menu).
22
+ */
23
+ async function hoverFirst(client, selector) {
24
+ await client.evaluate(`(() => {
25
+ const el = document.querySelector(${JSON.stringify(selector)});
26
+ if (!el) return;
27
+ el.dispatchEvent(new MouseEvent('mouseenter', { bubbles: true }));
28
+ el.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
29
+ })()`);
30
+ }
31
+ /**
32
+ * Click the first element matching `selector`.
33
+ */
34
+ async function clickFirst(client, selector) {
35
+ await client.evaluate(`(() => {
36
+ const el = document.querySelector(${JSON.stringify(selector)});
37
+ if (el) el.click();
38
+ })()`);
39
+ }
40
+ /**
41
+ * Navigate the CDP client to a URL and wait for the page load event.
42
+ */
43
+ async function navigateAndWait(client, url) {
44
+ await client.send("Page.enable");
45
+ try {
46
+ const loadPromise = client.waitForEvent("Page.loadEventFired", 30_000);
47
+ await client.navigate(url);
48
+ await loadPromise;
49
+ }
50
+ finally {
51
+ await client.send("Page.disable").catch(() => { });
52
+ }
53
+ }
54
+ /** LinkedIn feed page URL. */
55
+ const FEED_URL = "https://www.linkedin.com/feed/";
56
+ /** Selector for the "Comment" button in the social action bar. */
57
+ const COMMENT_BUTTON = 'button[aria-label*="Comment" i]';
58
+ describeE2E("LinkedIn selectors registry", () => {
59
+ let app;
60
+ let launcherPort;
61
+ let accountId;
62
+ let linkedInClient;
63
+ beforeAll(async () => {
64
+ // 1. Launch LinkedHelper
65
+ const launched = await launchApp();
66
+ app = launched.app;
67
+ launcherPort = launched.port;
68
+ // 2. Start an account instance
69
+ const launcher = new LauncherService(launcherPort);
70
+ await retryAsync(() => launcher.connect(), { retries: 3, delay: 1_000 });
71
+ const accounts = await launcher.listAccounts();
72
+ expect(accounts.length, "No accounts configured in LinkedHelper").toBeGreaterThan(0);
73
+ accountId = accounts[0].id;
74
+ await startInstanceWithRecovery(launcher, accountId, launcherPort);
75
+ launcher.disconnect();
76
+ // 3. Discover the instance's CDP port
77
+ const instancePort = await discoverInstancePort(launcherPort);
78
+ if (instancePort === null) {
79
+ throw new Error("Instance CDP port not discovered");
80
+ }
81
+ // 4. Connect directly to the LinkedIn WebView target
82
+ const liTarget = await retryAsync(async () => {
83
+ const t = await discoverTargets(instancePort);
84
+ const li = t.find((tgt) => tgt.type === "page" && tgt.url.includes("linkedin.com"));
85
+ if (!li)
86
+ throw new Error("LinkedIn target not found yet");
87
+ return li;
88
+ }, { retries: 10, delay: 2_000 });
89
+ linkedInClient = new CDPClient(instancePort);
90
+ await linkedInClient.connect(liTarget.id);
91
+ // 5. Navigate to the feed page and wait for it to load
92
+ await navigateAndWait(linkedInClient, FEED_URL);
93
+ // Give the SPA a moment to render dynamic content
94
+ await delay(3_000);
95
+ }, 180_000);
96
+ afterAll(async () => {
97
+ linkedInClient?.disconnect();
98
+ if (accountId !== undefined) {
99
+ const launcher = new LauncherService(launcherPort);
100
+ try {
101
+ await launcher.connect();
102
+ try {
103
+ await launcher.stopInstance(accountId);
104
+ await waitForInstanceShutdown(launcherPort);
105
+ }
106
+ catch {
107
+ await killInstanceProcesses(launcherPort);
108
+ }
109
+ }
110
+ catch {
111
+ // Best-effort cleanup
112
+ }
113
+ finally {
114
+ launcher.disconnect();
115
+ }
116
+ }
117
+ await quitApp(app);
118
+ }, 60_000);
119
+ // ── Module export sanity checks ─────────────────────────────────
120
+ describe("module exports", () => {
121
+ it("SELECTORS object contains all expected keys", () => {
122
+ const expectedKeys = [
123
+ "FEED_POST_CONTAINER",
124
+ "POST_TEXT_CONTENT",
125
+ "POST_AUTHOR_NAME",
126
+ "POST_AUTHOR_INFO",
127
+ "COMMENT_INPUT",
128
+ "REACTION_TRIGGER",
129
+ "REACTIONS_MENU",
130
+ "REACTION_LIKE",
131
+ "REACTION_CELEBRATE",
132
+ "REACTION_SUPPORT",
133
+ "REACTION_LOVE",
134
+ "REACTION_INSIGHTFUL",
135
+ "REACTION_FUNNY",
136
+ "COMMENT_SUBMIT_BUTTON",
137
+ "SCROLL_CONTAINER",
138
+ "PAGINATION_TRIGGER",
139
+ ];
140
+ for (const key of expectedKeys) {
141
+ expect(SELECTORS).toHaveProperty(key);
142
+ expect(typeof SELECTORS[key], `${key} should be a non-empty string`).toBe("string");
143
+ expect(SELECTORS[key].length, `${key} should not be empty`).toBeGreaterThan(0);
144
+ }
145
+ });
146
+ });
147
+ // ── Feed page selectors ─────────────────────────────────────────
148
+ describe("feed page selectors", () => {
149
+ it("FEED_POST_CONTAINER matches at least one element", async () => {
150
+ const count = await queryCount(linkedInClient, FEED_POST_CONTAINER);
151
+ expect(count, `Selector "${FEED_POST_CONTAINER}" matched 0 elements`).toBeGreaterThan(0);
152
+ });
153
+ it("POST_TEXT_CONTENT matches at least one element", async () => {
154
+ const count = await queryCount(linkedInClient, POST_TEXT_CONTENT);
155
+ expect(count, `Selector "${POST_TEXT_CONTENT}" matched 0 elements`).toBeGreaterThan(0);
156
+ });
157
+ it("POST_AUTHOR_NAME matches at least one element", async () => {
158
+ const count = await queryCount(linkedInClient, POST_AUTHOR_NAME);
159
+ expect(count, `Selector "${POST_AUTHOR_NAME}" matched 0 elements`).toBeGreaterThan(0);
160
+ });
161
+ it("POST_AUTHOR_INFO matches at least one element", async () => {
162
+ const count = await queryCount(linkedInClient, POST_AUTHOR_INFO);
163
+ expect(count, `Selector "${POST_AUTHOR_INFO}" matched 0 elements`).toBeGreaterThan(0);
164
+ });
165
+ it("REACTION_TRIGGER matches at least one element", async () => {
166
+ const count = await queryCount(linkedInClient, REACTION_TRIGGER);
167
+ expect(count, `Selector "${REACTION_TRIGGER}" matched 0 elements`).toBeGreaterThan(0);
168
+ });
169
+ it("SCROLL_CONTAINER matches at least one element", async () => {
170
+ const count = await queryCount(linkedInClient, SCROLL_CONTAINER);
171
+ expect(count, `Selector "${SCROLL_CONTAINER}" matched 0 elements`).toBeGreaterThan(0);
172
+ });
173
+ });
174
+ // ── Reactions menu selectors (hover-triggered) ──────────────────
175
+ describe("reactions menu selectors", () => {
176
+ beforeAll(async () => {
177
+ // Hover over the first reaction trigger to reveal the reactions menu
178
+ await hoverFirst(linkedInClient, REACTION_TRIGGER);
179
+ // Wait for the popup to render
180
+ await delay(1_500);
181
+ });
182
+ it("REACTIONS_MENU matches at least one element", async () => {
183
+ const count = await queryCount(linkedInClient, REACTIONS_MENU);
184
+ expect(count, `Selector "${REACTIONS_MENU}" matched 0 elements`).toBeGreaterThan(0);
185
+ });
186
+ it("REACTION_LIKE matches at least one element", async () => {
187
+ const count = await queryCount(linkedInClient, REACTION_LIKE);
188
+ expect(count, `Selector "${REACTION_LIKE}" matched 0 elements`).toBeGreaterThan(0);
189
+ });
190
+ it("REACTION_CELEBRATE matches at least one element", async () => {
191
+ const count = await queryCount(linkedInClient, REACTION_CELEBRATE);
192
+ expect(count, `Selector "${REACTION_CELEBRATE}" matched 0 elements`).toBeGreaterThan(0);
193
+ });
194
+ it("REACTION_SUPPORT matches at least one element", async () => {
195
+ const count = await queryCount(linkedInClient, REACTION_SUPPORT);
196
+ expect(count, `Selector "${REACTION_SUPPORT}" matched 0 elements`).toBeGreaterThan(0);
197
+ });
198
+ it("REACTION_LOVE matches at least one element", async () => {
199
+ const count = await queryCount(linkedInClient, REACTION_LOVE);
200
+ expect(count, `Selector "${REACTION_LOVE}" matched 0 elements`).toBeGreaterThan(0);
201
+ });
202
+ it("REACTION_INSIGHTFUL matches at least one element", async () => {
203
+ const count = await queryCount(linkedInClient, REACTION_INSIGHTFUL);
204
+ expect(count, `Selector "${REACTION_INSIGHTFUL}" matched 0 elements`).toBeGreaterThan(0);
205
+ });
206
+ it("REACTION_FUNNY matches at least one element", async () => {
207
+ const count = await queryCount(linkedInClient, REACTION_FUNNY);
208
+ expect(count, `Selector "${REACTION_FUNNY}" matched 0 elements`).toBeGreaterThan(0);
209
+ });
210
+ });
211
+ // ── Comment selectors (click-triggered) ─────────────────────────
212
+ describe("comment selectors", () => {
213
+ beforeAll(async () => {
214
+ // Dismiss the reactions menu by clicking elsewhere
215
+ await clickFirst(linkedInClient, "body");
216
+ await delay(500);
217
+ // Click the "Comment" button on the first post to expand the section
218
+ await clickFirst(linkedInClient, COMMENT_BUTTON);
219
+ await delay(1_500);
220
+ });
221
+ it("COMMENT_INPUT matches at least one element", async () => {
222
+ const count = await queryCount(linkedInClient, COMMENT_INPUT);
223
+ expect(count, `Selector "${COMMENT_INPUT}" matched 0 elements`).toBeGreaterThan(0);
224
+ });
225
+ it("COMMENT_SUBMIT_BUTTON matches at least one element", async () => {
226
+ // The submit button only appears after typing into the editor
227
+ await linkedInClient.evaluate(`(() => {
228
+ const editor = document.querySelector(${JSON.stringify(COMMENT_INPUT)});
229
+ if (editor) {
230
+ editor.textContent = ' ';
231
+ editor.dispatchEvent(new Event('input', { bubbles: true }));
232
+ }
233
+ })()`);
234
+ await delay(1_000);
235
+ const count = await queryCount(linkedInClient, COMMENT_SUBMIT_BUTTON);
236
+ expect(count, `Selector "${COMMENT_SUBMIT_BUTTON}" matched 0 elements`).toBeGreaterThan(0);
237
+ // Clean up: clear the editor text
238
+ await linkedInClient.evaluate(`(() => {
239
+ const editor = document.querySelector(${JSON.stringify(COMMENT_INPUT)});
240
+ if (editor) {
241
+ editor.textContent = '';
242
+ editor.dispatchEvent(new Event('input', { bubbles: true }));
243
+ }
244
+ })()`);
245
+ });
246
+ });
247
+ // ── Pagination trigger ──────────────────────────────────────────
248
+ describe("pagination selectors", () => {
249
+ it("PAGINATION_TRIGGER matches at least one element after scrolling", async () => {
250
+ // Scroll to the bottom to trigger pagination rendering
251
+ await linkedInClient.evaluate("window.scrollTo(0, document.body.scrollHeight)");
252
+ await delay(3_000);
253
+ const count = await queryCount(linkedInClient, PAGINATION_TRIGGER);
254
+ expect(count, `Selector "${PAGINATION_TRIGGER}" matched 0 elements`).toBeGreaterThan(0);
255
+ });
256
+ });
257
+ });
258
+ //# sourceMappingURL=selectors.integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selectors.integration.test.js","sourceRoot":"","sources":["../../../src/linkedin/__tests__/selectors.integration.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ import type { CDPClient } from "../cdp/client.js";
2
+ /** Options for {@link waitForElement}. */
3
+ export interface WaitForElementOptions {
4
+ /** Maximum time to wait in ms (default: 30 000). */
5
+ timeout?: number;
6
+ /** Polling interval in ms (default: 100). */
7
+ pollInterval?: number;
8
+ }
9
+ /** Text input method for {@link typeText}. */
10
+ export type TypeMethod = "type";
11
+ /**
12
+ * Poll the DOM until an element matching the selector appears.
13
+ *
14
+ * @param client - Connected CDP client targeting the page.
15
+ * @param selector - CSS selector to query.
16
+ * @param options - Timeout and polling interval.
17
+ * @throws {CDPTimeoutError} If the element does not appear within the timeout.
18
+ */
19
+ export declare function waitForElement(client: CDPClient, selector: string, options?: WaitForElementOptions): Promise<void>;
20
+ /**
21
+ * Scroll the page until the target element is visible in the viewport.
22
+ *
23
+ * The element must already exist in the DOM. Use {@link waitForElement}
24
+ * first if it may not be present yet.
25
+ *
26
+ * @param client - Connected CDP client targeting the page.
27
+ * @param selector - CSS selector for the element to scroll to.
28
+ * @throws {CDPEvaluationError} If the element is not found.
29
+ */
30
+ export declare function scrollTo(client: CDPClient, selector: string): Promise<void>;
31
+ /**
32
+ * Trigger a hover on an element by dispatching `mouseenter` + `mouseover`.
33
+ *
34
+ * This is used to reveal hover-dependent UI such as the LinkedIn
35
+ * reactions menu popup.
36
+ *
37
+ * @param client - Connected CDP client targeting the page.
38
+ * @param selector - CSS selector for the element to hover.
39
+ * @throws {CDPEvaluationError} If the element is not found.
40
+ */
41
+ export declare function hover(client: CDPClient, selector: string): Promise<void>;
42
+ /**
43
+ * Click an element via its JavaScript `.click()` method.
44
+ *
45
+ * Uses JS `.click()` rather than `Input.dispatchMouseEvent` because the
46
+ * latter does not reliably trigger handlers on LinkedIn's React components.
47
+ *
48
+ * @param client - Connected CDP client targeting the page.
49
+ * @param selector - CSS selector for the element to click.
50
+ * @throws {CDPEvaluationError} If the element is not found.
51
+ */
52
+ export declare function click(client: CDPClient, selector: string): Promise<void>;
53
+ /**
54
+ * Type text into a focused element character-by-character.
55
+ *
56
+ * The element is focused first, then each character is dispatched via
57
+ * CDP `Input.dispatchKeyEvent` with randomised inter-keystroke delays
58
+ * (50–150 ms) to approximate human typing cadence.
59
+ *
60
+ * @param client - Connected CDP client targeting the page.
61
+ * @param selector - CSS selector for the input element.
62
+ * @param text - The string to type.
63
+ * @param method - Input method (default: `"type"`).
64
+ * @throws {CDPEvaluationError} If the element is not found.
65
+ */
66
+ export declare function typeText(client: CDPClient, selector: string, text: string, method?: TypeMethod): Promise<void>;
67
+ //# sourceMappingURL=dom-automation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dom-automation.d.ts","sourceRoot":"","sources":["../../src/linkedin/dom-automation.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAgBlD,0CAA0C;AAC1C,MAAM,WAAW,qBAAqB;IACpC,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6CAA6C;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,8CAA8C;AAC9C,MAAM,MAAM,UAAU,GAAG,MAAM,CAAC;AAEhC;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE,qBAAqB,GAC9B,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED;;;;;;;;;GASG;AACH,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;;;;;;;;GASG;AACH,wBAAsB,KAAK,CACzB,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED;;;;;;;;;GASG;AACH,wBAAsB,KAAK,CACzB,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,QAAQ,CAC5B,MAAM,EAAE,SAAS,EACjB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,MAAM,GAAE,UAAmB,GAC1B,OAAO,CAAC,IAAI,CAAC,CAoCf"}
@@ -0,0 +1,139 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ import { CDPEvaluationError, CDPTimeoutError } from "../cdp/errors.js";
4
+ import { delay } from "../utils/delay.js";
5
+ /** Default timeout for DOM operations (ms). */
6
+ const DEFAULT_TIMEOUT = 30_000;
7
+ /** Default polling interval for waitForElement (ms). */
8
+ const DEFAULT_POLL_INTERVAL = 100;
9
+ /** Minimum delay between keystrokes (ms). */
10
+ const MIN_KEYSTROKE_DELAY = 50;
11
+ /** Maximum delay between keystrokes (ms). */
12
+ const MAX_KEYSTROKE_DELAY = 150;
13
+ /**
14
+ * Poll the DOM until an element matching the selector appears.
15
+ *
16
+ * @param client - Connected CDP client targeting the page.
17
+ * @param selector - CSS selector to query.
18
+ * @param options - Timeout and polling interval.
19
+ * @throws {CDPTimeoutError} If the element does not appear within the timeout.
20
+ */
21
+ export async function waitForElement(client, selector, options) {
22
+ const timeout = options?.timeout ?? DEFAULT_TIMEOUT;
23
+ const pollInterval = options?.pollInterval ?? DEFAULT_POLL_INTERVAL;
24
+ const deadline = Date.now() + timeout;
25
+ while (Date.now() < deadline) {
26
+ const found = await client.evaluate(`document.querySelector(${JSON.stringify(selector)}) !== null`);
27
+ if (found)
28
+ return;
29
+ await delay(pollInterval);
30
+ }
31
+ throw new CDPTimeoutError(`Timed out waiting for element "${selector}" after ${timeout.toString()}ms`);
32
+ }
33
+ /**
34
+ * Scroll the page until the target element is visible in the viewport.
35
+ *
36
+ * The element must already exist in the DOM. Use {@link waitForElement}
37
+ * first if it may not be present yet.
38
+ *
39
+ * @param client - Connected CDP client targeting the page.
40
+ * @param selector - CSS selector for the element to scroll to.
41
+ * @throws {CDPEvaluationError} If the element is not found.
42
+ */
43
+ export async function scrollTo(client, selector) {
44
+ const scrolled = await client.evaluate(`(() => {
45
+ const el = document.querySelector(${JSON.stringify(selector)});
46
+ if (!el) return false;
47
+ el.scrollIntoView({ behavior: "instant", block: "center" });
48
+ return true;
49
+ })()`);
50
+ if (!scrolled) {
51
+ throw new CDPEvaluationError(`Element "${selector}" not found for scrollTo`);
52
+ }
53
+ }
54
+ /**
55
+ * Trigger a hover on an element by dispatching `mouseenter` + `mouseover`.
56
+ *
57
+ * This is used to reveal hover-dependent UI such as the LinkedIn
58
+ * reactions menu popup.
59
+ *
60
+ * @param client - Connected CDP client targeting the page.
61
+ * @param selector - CSS selector for the element to hover.
62
+ * @throws {CDPEvaluationError} If the element is not found.
63
+ */
64
+ export async function hover(client, selector) {
65
+ const hovered = await client.evaluate(`(() => {
66
+ const el = document.querySelector(${JSON.stringify(selector)});
67
+ if (!el) return false;
68
+ el.dispatchEvent(new MouseEvent('mouseenter', { bubbles: true }));
69
+ el.dispatchEvent(new MouseEvent('mouseover', { bubbles: true }));
70
+ return true;
71
+ })()`);
72
+ if (!hovered) {
73
+ throw new CDPEvaluationError(`Element "${selector}" not found for hover`);
74
+ }
75
+ }
76
+ /**
77
+ * Click an element via its JavaScript `.click()` method.
78
+ *
79
+ * Uses JS `.click()` rather than `Input.dispatchMouseEvent` because the
80
+ * latter does not reliably trigger handlers on LinkedIn's React components.
81
+ *
82
+ * @param client - Connected CDP client targeting the page.
83
+ * @param selector - CSS selector for the element to click.
84
+ * @throws {CDPEvaluationError} If the element is not found.
85
+ */
86
+ export async function click(client, selector) {
87
+ const clicked = await client.evaluate(`(() => {
88
+ const el = document.querySelector(${JSON.stringify(selector)});
89
+ if (!el) return false;
90
+ el.click();
91
+ return true;
92
+ })()`);
93
+ if (!clicked) {
94
+ throw new CDPEvaluationError(`Element "${selector}" not found for click`);
95
+ }
96
+ }
97
+ /**
98
+ * Type text into a focused element character-by-character.
99
+ *
100
+ * The element is focused first, then each character is dispatched via
101
+ * CDP `Input.dispatchKeyEvent` with randomised inter-keystroke delays
102
+ * (50–150 ms) to approximate human typing cadence.
103
+ *
104
+ * @param client - Connected CDP client targeting the page.
105
+ * @param selector - CSS selector for the input element.
106
+ * @param text - The string to type.
107
+ * @param method - Input method (default: `"type"`).
108
+ * @throws {CDPEvaluationError} If the element is not found.
109
+ */
110
+ export async function typeText(client, selector, text, method = "type") {
111
+ const focused = await client.evaluate(`(() => {
112
+ const el = document.querySelector(${JSON.stringify(selector)});
113
+ if (!el) return false;
114
+ el.focus();
115
+ return true;
116
+ })()`);
117
+ if (!focused) {
118
+ throw new CDPEvaluationError(`Element "${selector}" not found for typeText`);
119
+ }
120
+ switch (method) {
121
+ case "type":
122
+ for (const char of text) {
123
+ await client.send("Input.dispatchKeyEvent", {
124
+ type: "keyDown",
125
+ key: char,
126
+ text: char,
127
+ });
128
+ await client.send("Input.dispatchKeyEvent", {
129
+ type: "keyUp",
130
+ key: char,
131
+ });
132
+ const keystrokeDelay = MIN_KEYSTROKE_DELAY +
133
+ Math.random() * (MAX_KEYSTROKE_DELAY - MIN_KEYSTROKE_DELAY);
134
+ await delay(keystrokeDelay);
135
+ }
136
+ break;
137
+ }
138
+ }
139
+ //# sourceMappingURL=dom-automation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dom-automation.js","sourceRoot":"","sources":["../../src/linkedin/dom-automation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { click, hover, scrollTo, typeText, type TypeMethod, waitForElement, type WaitForElementOptions, } from "./dom-automation.js";
2
+ export { COMMENT_INPUT, COMMENT_SUBMIT_BUTTON, FEED_POST_CONTAINER, PAGINATION_TRIGGER, POST_AUTHOR_INFO, POST_AUTHOR_NAME, POST_TEXT_CONTENT, REACTION_CELEBRATE, REACTION_FUNNY, REACTION_INSIGHTFUL, REACTION_LIKE, REACTION_LOVE, REACTION_SUPPORT, REACTION_TRIGGER, REACTIONS_MENU, SCROLL_CONTAINER, SELECTORS, type SelectorName, } from "./selectors.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/linkedin/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,EACL,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,KAAK,UAAU,EACf,cAAc,EACd,KAAK,qBAAqB,GAC3B,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,SAAS,EACT,KAAK,YAAY,GAClB,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,5 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-only
2
+ // Copyright (C) 2026 Oleksii PELYKH
3
+ export { click, hover, scrollTo, typeText, waitForElement, } from "./dom-automation.js";
4
+ export { COMMENT_INPUT, COMMENT_SUBMIT_BUTTON, FEED_POST_CONTAINER, PAGINATION_TRIGGER, POST_AUTHOR_INFO, POST_AUTHOR_NAME, POST_TEXT_CONTENT, REACTION_CELEBRATE, REACTION_FUNNY, REACTION_INSIGHTFUL, REACTION_LIKE, REACTION_LOVE, REACTION_SUPPORT, REACTION_TRIGGER, REACTIONS_MENU, SCROLL_CONTAINER, SELECTORS, } from "./selectors.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/linkedin/index.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,oCAAoC;AAEpC,OAAO,EACL,KAAK,EACL,KAAK,EACL,QAAQ,EACR,QAAQ,EAER,cAAc,GAEf,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,mBAAmB,EACnB,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,SAAS,GAEV,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Centralized CSS selector registry for LinkedIn DOM elements.
3
+ *
4
+ * Each selector targets a specific UI element needed for content
5
+ * interaction (feed reading, commenting, reacting). When LinkedIn
6
+ * changes their DOM structure, integration tests identify broken
7
+ * selectors by name.
8
+ */
9
+ /** Individual feed post wrapper. */
10
+ export declare const FEED_POST_CONTAINER = "div.feed-shared-update-v2";
11
+ /** Text content within a feed post. */
12
+ export declare const POST_TEXT_CONTENT = ".feed-shared-update-v2__description";
13
+ /** Post author's display name. */
14
+ export declare const POST_AUTHOR_NAME = ".update-components-actor__title";
15
+ /** Post author's headline / description line. */
16
+ export declare const POST_AUTHOR_INFO = ".update-components-actor__description";
17
+ /** Rich-text editor for writing comments (Quill-based). */
18
+ export declare const COMMENT_INPUT = ".comments-comment-texteditor .ql-editor";
19
+ /** Main reaction trigger button (Like / React). */
20
+ export declare const REACTION_TRIGGER = "button.react-button__trigger";
21
+ /** Reactions popup menu container (appears on hover). */
22
+ export declare const REACTIONS_MENU = ".reactions-menu";
23
+ /** Like reaction button inside the reactions menu. */
24
+ export declare const REACTION_LIKE = ".reactions-menu button[aria-label=\"React Like\"]";
25
+ /** Celebrate reaction button inside the reactions menu. */
26
+ export declare const REACTION_CELEBRATE = ".reactions-menu button[aria-label=\"React Celebrate\"]";
27
+ /** Support reaction button inside the reactions menu. */
28
+ export declare const REACTION_SUPPORT = ".reactions-menu button[aria-label=\"React Support\"]";
29
+ /** Love reaction button inside the reactions menu. */
30
+ export declare const REACTION_LOVE = ".reactions-menu button[aria-label=\"React Love\"]";
31
+ /** Insightful reaction button inside the reactions menu. */
32
+ export declare const REACTION_INSIGHTFUL = ".reactions-menu button[aria-label=\"React Insightful\"]";
33
+ /** Funny reaction button inside the reactions menu. */
34
+ export declare const REACTION_FUNNY = ".reactions-menu button[aria-label=\"React Funny\"]";
35
+ /** Submit button for the comment form. */
36
+ export declare const COMMENT_SUBMIT_BUTTON = "button[class*=\"comments-comment-box__submit-button\"]";
37
+ /** Main scrollable feed container. */
38
+ export declare const SCROLL_CONTAINER = ".scaffold-finite-scroll";
39
+ /** "Show more" / load-more button for feed pagination. */
40
+ export declare const PAGINATION_TRIGGER = ".scaffold-finite-scroll__load-button";
41
+ /**
42
+ * Aggregated registry of all selectors, keyed by name.
43
+ *
44
+ * Useful for iterating over all selectors in tests or for
45
+ * dynamic lookup by name at runtime.
46
+ */
47
+ export declare const SELECTORS: {
48
+ readonly FEED_POST_CONTAINER: "div.feed-shared-update-v2";
49
+ readonly POST_TEXT_CONTENT: ".feed-shared-update-v2__description";
50
+ readonly POST_AUTHOR_NAME: ".update-components-actor__title";
51
+ readonly POST_AUTHOR_INFO: ".update-components-actor__description";
52
+ readonly COMMENT_INPUT: ".comments-comment-texteditor .ql-editor";
53
+ readonly REACTION_TRIGGER: "button.react-button__trigger";
54
+ readonly REACTIONS_MENU: ".reactions-menu";
55
+ readonly REACTION_LIKE: ".reactions-menu button[aria-label=\"React Like\"]";
56
+ readonly REACTION_CELEBRATE: ".reactions-menu button[aria-label=\"React Celebrate\"]";
57
+ readonly REACTION_SUPPORT: ".reactions-menu button[aria-label=\"React Support\"]";
58
+ readonly REACTION_LOVE: ".reactions-menu button[aria-label=\"React Love\"]";
59
+ readonly REACTION_INSIGHTFUL: ".reactions-menu button[aria-label=\"React Insightful\"]";
60
+ readonly REACTION_FUNNY: ".reactions-menu button[aria-label=\"React Funny\"]";
61
+ readonly COMMENT_SUBMIT_BUTTON: "button[class*=\"comments-comment-box__submit-button\"]";
62
+ readonly SCROLL_CONTAINER: ".scaffold-finite-scroll";
63
+ readonly PAGINATION_TRIGGER: ".scaffold-finite-scroll__load-button";
64
+ };
65
+ /** Union of all selector names in the registry. */
66
+ export type SelectorName = keyof typeof SELECTORS;
67
+ //# sourceMappingURL=selectors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selectors.d.ts","sourceRoot":"","sources":["../../src/linkedin/selectors.ts"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AAIH,oCAAoC;AACpC,eAAO,MAAM,mBAAmB,8BAA8B,CAAC;AAE/D,uCAAuC;AACvC,eAAO,MAAM,iBAAiB,wCAAwC,CAAC;AAIvE,kCAAkC;AAClC,eAAO,MAAM,gBAAgB,oCAAoC,CAAC;AAElE,iDAAiD;AACjD,eAAO,MAAM,gBAAgB,0CAA0C,CAAC;AAIxE,2DAA2D;AAC3D,eAAO,MAAM,aAAa,4CAA4C,CAAC;AAIvE,mDAAmD;AACnD,eAAO,MAAM,gBAAgB,iCAAiC,CAAC;AAE/D,yDAAyD;AACzD,eAAO,MAAM,cAAc,oBAAoB,CAAC;AAEhD,sDAAsD;AACtD,eAAO,MAAM,aAAa,sDAAoD,CAAC;AAE/E,2DAA2D;AAC3D,eAAO,MAAM,kBAAkB,2DAAyD,CAAC;AAEzF,yDAAyD;AACzD,eAAO,MAAM,gBAAgB,yDAAuD,CAAC;AAErF,sDAAsD;AACtD,eAAO,MAAM,aAAa,sDAAoD,CAAC;AAE/E,4DAA4D;AAC5D,eAAO,MAAM,mBAAmB,4DAA0D,CAAC;AAE3F,uDAAuD;AACvD,eAAO,MAAM,cAAc,uDAAqD,CAAC;AAIjF,0CAA0C;AAC1C,eAAO,MAAM,qBAAqB,2DAAyD,CAAC;AAI5F,sCAAsC;AACtC,eAAO,MAAM,gBAAgB,4BAA4B,CAAC;AAI1D,0DAA0D;AAC1D,eAAO,MAAM,kBAAkB,yCAAyC,CAAC;AAEzE;;;;;GAKG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;CAiBZ,CAAC;AAEX,mDAAmD;AACnD,MAAM,MAAM,YAAY,GAAG,MAAM,OAAO,SAAS,CAAC"}