jsf.js_next_gen 4.1.0-beta.2 → 4.1.0-beta.21

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 (413) hide show
  1. package/AI_CONTRIBUTIONS.md +71 -0
  2. package/README.md +254 -78
  3. package/api-extractor.faces.json +38 -0
  4. package/dist/docs/assets/hierarchy.js +1 -1
  5. package/dist/docs/assets/navigation.js +1 -1
  6. package/dist/docs/assets/search.js +1 -1
  7. package/dist/docs/functions/faces.ajax.addOnError.html +2 -2
  8. package/dist/docs/functions/faces.ajax.addOnEvent.html +2 -2
  9. package/dist/docs/functions/faces.ajax.request.html +2 -2
  10. package/dist/docs/functions/faces.ajax.response.html +2 -2
  11. package/dist/docs/functions/faces.getClientWindow.html +2 -2
  12. package/dist/docs/functions/faces.getProjectStage.html +2 -2
  13. package/dist/docs/functions/faces.getViewState.html +1 -1
  14. package/dist/docs/functions/faces.push.close.html +1 -1
  15. package/dist/docs/functions/faces.push.init.html +6 -6
  16. package/dist/docs/functions/faces.push.open.html +1 -1
  17. package/dist/docs/functions/faces.util.chain.html +2 -2
  18. package/dist/docs/functions/myfaces.ab.html +3 -3
  19. package/dist/docs/functions/myfaces.onDomReady.html +1 -1
  20. package/dist/docs/functions/myfaces.reserveNamespace.html +1 -1
  21. package/dist/docs/hierarchy.html +1 -1
  22. package/dist/docs/index.html +292 -71
  23. package/dist/docs/interfaces/faces.AjaxData.html +6 -0
  24. package/dist/docs/interfaces/faces.AjaxError.html +18 -0
  25. package/dist/docs/interfaces/faces.AjaxEvent.html +8 -0
  26. package/dist/docs/interfaces/faces.ajax.RequestContext.html +6 -0
  27. package/dist/docs/interfaces/faces.ajax.RequestOptions.html +10 -0
  28. package/dist/docs/modules/faces.ajax.html +1 -1
  29. package/dist/docs/modules/faces.html +1 -1
  30. package/dist/docs/modules/faces.push.html +1 -1
  31. package/dist/docs/modules/faces.util.html +1 -1
  32. package/dist/docs/modules/myfaces.html +1 -1
  33. package/dist/docs/modules.html +1 -1
  34. package/dist/docs/types/faces.AjaxErrorStatus.html +2 -0
  35. package/dist/docs/types/faces.AjaxEventStatus.html +2 -0
  36. package/dist/docs/types/faces.ProjectStage.html +2 -0
  37. package/dist/docs/types/faces.ajax.OnErrorCallback.html +2 -0
  38. package/dist/docs/types/faces.ajax.OnEventCallback.html +2 -0
  39. package/dist/docs/types/faces.push.OnCloseHandler.html +2 -0
  40. package/dist/docs/types/faces.push.OnErrorHandler.html +2 -0
  41. package/dist/docs/types/faces.push.OnMessageHandler.html +2 -0
  42. package/dist/docs/types/faces.push.OnOpenHandler.html +2 -0
  43. package/dist/docs/variables/faces.contextpath.html +1 -1
  44. package/dist/docs/variables/faces.implversion.html +1 -1
  45. package/dist/docs/variables/faces.separatorchar.html +1 -1
  46. package/dist/docs/variables/faces.specversion.html +1 -1
  47. package/dist/docs/variables/myfaces.oam.html +1 -1
  48. package/dist/window/faces-development.js +1801 -499
  49. package/dist/window/faces-development.js.map +1 -1
  50. package/{target/api/_api.js → dist/window/faces.d.ts} +124 -151
  51. package/dist/window/faces.js +1 -1
  52. package/dist/window/faces.js.LICENSE.txt +0 -17
  53. package/dist/window/faces.js.map +1 -1
  54. package/dist/window/jsf-development.js +1806 -513
  55. package/dist/window/jsf-development.js.map +1 -1
  56. package/{target/src/main/typescript/api/_api.js → dist/window/jsf.d.ts} +125 -153
  57. package/dist/window/jsf.js +1 -1
  58. package/dist/window/jsf.js.LICENSE.txt +0 -17
  59. package/dist/window/jsf.js.map +1 -1
  60. package/package.json +22 -18
  61. package/scripts/build-dts.mjs +239 -0
  62. package/src/main/typescript/@types/definitions/index.d.ts +22 -122
  63. package/{target/test/frameworkBase/_ext/monadish/fixtures/test2.js → src/main/typescript/@types/definitions/modules.d.ts} +18 -2
  64. package/src/main/typescript/api/_api.ts +132 -29
  65. package/{target/test/frameworkBase/_ext/monadish/fixtures/test.js → src/main/typescript/api/_api_ae_stub.d.ts} +6 -2
  66. package/src/main/typescript/api/faces.ts +2 -2
  67. package/src/main/typescript/api/jsf.ts +15 -23
  68. package/src/main/typescript/impl/AjaxImpl.ts +15 -15
  69. package/src/main/typescript/impl/PushImpl.ts +139 -69
  70. package/src/main/typescript/impl/core/Const.ts +2 -2
  71. package/src/main/typescript/impl/i18n/Messages.ts +1 -1
  72. package/src/main/typescript/impl/util/Assertions.ts +1 -2
  73. package/src/main/typescript/impl/util/AsyncRunnable.ts +3 -4
  74. package/src/main/typescript/impl/util/ExtDomQuery.ts +19 -19
  75. package/src/main/typescript/impl/util/FileUtils.ts +30 -14
  76. package/src/main/typescript/impl/util/HiddenInputBuilder.ts +34 -34
  77. package/src/main/typescript/impl/util/Lang.ts +19 -22
  78. package/src/main/typescript/impl/util/XhrQueueController.ts +25 -3
  79. package/src/main/typescript/impl/xhrCore/ErrorData.ts +17 -12
  80. package/src/main/typescript/impl/xhrCore/EventData.ts +8 -7
  81. package/src/main/typescript/impl/xhrCore/IResponseProcessor.ts +3 -3
  82. package/src/main/typescript/impl/xhrCore/RequestDataResolver.ts +7 -6
  83. package/src/main/typescript/impl/xhrCore/Response.ts +3 -3
  84. package/src/main/typescript/impl/xhrCore/ResponseDataResolver.ts +0 -38
  85. package/src/main/typescript/impl/xhrCore/ResponseProcessor.ts +17 -15
  86. package/src/main/typescript/impl/xhrCore/XhrFormData.ts +72 -63
  87. package/src/main/typescript/impl/xhrCore/XhrRequest.ts +80 -134
  88. package/src/main/typescript/mona_dish_shim.ts +6 -2
  89. package/src/main/typescript/myfaces/OamSubmit.ts +10 -6
  90. package/src/main/typescript/test/api/JsfPushShimTest.spec.ts +126 -0
  91. package/src/main/typescript/test/api/MyFacesABTest.spec.ts +16 -0
  92. package/src/main/typescript/test/api/PushTypeCompatibility.ts +65 -0
  93. package/src/main/typescript/test/frameworkBase/LangTest.spec.ts +16 -0
  94. package/src/main/typescript/test/frameworkBase/_ext/monadish/DomQueryTest.spec.ts +1 -0
  95. package/src/main/typescript/test/frameworkBase/_ext/monadish/XmlQueryTest.spec.ts +16 -0
  96. package/src/main/typescript/test/frameworkBase/_ext/monadish/markups/tobago-with-header.ts +16 -0
  97. package/src/main/typescript/test/frameworkBase/_ext/monadish/markups/tobago-without-header.ts +16 -0
  98. package/src/main/typescript/test/frameworkBase/_ext/shared/StandardInits.ts +55 -9
  99. package/src/main/typescript/test/frameworkBase/_ext/shared/XmlResponses.ts +16 -0
  100. package/src/main/typescript/test/impl/AssertionsTest.spec.ts +168 -0
  101. package/src/main/typescript/test/impl/FileUtilsTest.spec.ts +126 -0
  102. package/src/main/typescript/test/impl/ImplTest.spec.ts +75 -1
  103. package/src/main/typescript/test/impl/ResponseDataResolverTest.spec.ts +62 -0
  104. package/src/main/typescript/test/impl/util/ExtDomQueryTest.spec.ts +91 -1
  105. package/src/main/typescript/test/impl/util/ExtLangTest.spec.ts +110 -0
  106. package/src/main/typescript/test/impl/util/HiddenInputBuilderTest.spec.ts +74 -0
  107. package/src/main/typescript/test/myfaces/OamSubmit.spec.ts +61 -1
  108. package/src/main/typescript/test/queue/AsynchronousQueueTest.spec.ts +191 -2
  109. package/src/main/typescript/test/xhrCore/ClientWindow.spec.ts +16 -0
  110. package/src/main/typescript/test/xhrCore/ErrorChainTest.spec.ts +14 -0
  111. package/src/main/typescript/test/xhrCore/FakeWebsocket.ts +21 -5
  112. package/src/main/typescript/test/xhrCore/RequestTest.spec.ts +363 -4
  113. package/src/main/typescript/test/xhrCore/ResponseTest.spec.ts +218 -4
  114. package/src/main/typescript/test/xhrCore/TobagoFileUploadTest.spec.ts +1 -1
  115. package/src/main/typescript/test/xhrCore/WebsocketTest.spec.ts +764 -0
  116. package/src/main/typescript/test/xhrCore/XhrFormDataTest.spec.ts +265 -62
  117. package/src/main/typescript/test/xhrCore/XhrRequestProgress.spec.ts +16 -0
  118. package/{target/src/main/typescript/test/xhrCore/FakeWebsocket.js → src/main/typescript/tsconfig.ae.json} +16 -23
  119. package/src/main/typescript/{tsconfig.json → tsconfig.dts.json} +11 -27
  120. package/src/main/typescript/tsconfig.test.json +17 -0
  121. package/tsconfig.api-extractor.json +17 -0
  122. package/.claude/settings.local.json +0 -16
  123. package/.github/workflows/codeql-analysis.yml +0 -83
  124. package/.github/workflows/nodejs.yml +0 -26
  125. package/.mocharc.json +0 -10
  126. package/.nyc_output/384344d4-4f46-455f-84c3-010f829098cb.json +0 -1
  127. package/.nyc_output/a0f90016-f4f9-4039-bb51-57f4f7050541.json +0 -1
  128. package/.nyc_output/db388b5d-0b79-4bce-afd2-001aaf6f0245.json +0 -1
  129. package/.nyc_output/processinfo/384344d4-4f46-455f-84c3-010f829098cb.json +0 -1
  130. package/.nyc_output/processinfo/a0f90016-f4f9-4039-bb51-57f4f7050541.json +0 -1
  131. package/.nyc_output/processinfo/db388b5d-0b79-4bce-afd2-001aaf6f0245.json +0 -1
  132. package/.nyc_output/processinfo/index.json +0 -1
  133. package/.nycrc +0 -6
  134. package/build.cmd +0 -1
  135. package/build.sh +0 -3
  136. package/mvnw +0 -286
  137. package/mvnw.cmd +0 -161
  138. package/plans for 4.0.1.txt +0 -8
  139. package/remap.ts +0 -51
  140. package/src/main/typescript/test/xhrCore/WebsocketTest.ts +0 -221
  141. package/target/api/_api.js.map +0 -1
  142. package/target/api/faces.js +0 -45
  143. package/target/api/faces.js.map +0 -1
  144. package/target/api/jsf.js +0 -56
  145. package/target/api/jsf.js.map +0 -1
  146. package/target/impl/AjaxImpl.js +0 -748
  147. package/target/impl/AjaxImpl.js.map +0 -1
  148. package/target/impl/PushImpl.js +0 -265
  149. package/target/impl/PushImpl.js.map +0 -1
  150. package/target/impl/core/Const.js +0 -177
  151. package/target/impl/core/Const.js.map +0 -1
  152. package/target/impl/core/ImplTypes.js +0 -38
  153. package/target/impl/core/ImplTypes.js.map +0 -1
  154. package/target/impl/i18n/Messages.js +0 -113
  155. package/target/impl/i18n/Messages.js.map +0 -1
  156. package/target/impl/util/Assertions.js +0 -101
  157. package/target/impl/util/Assertions.js.map +0 -1
  158. package/target/impl/util/AsyncRunnable.js +0 -78
  159. package/target/impl/util/AsyncRunnable.js.map +0 -1
  160. package/target/impl/util/ExtDomQuery.js +0 -306
  161. package/target/impl/util/ExtDomQuery.js.map +0 -1
  162. package/target/impl/util/FileUtils.js +0 -98
  163. package/target/impl/util/FileUtils.js.map +0 -1
  164. package/target/impl/util/HiddenInputBuilder.js +0 -83
  165. package/target/impl/util/HiddenInputBuilder.js.map +0 -1
  166. package/target/impl/util/IListener.js +0 -3
  167. package/target/impl/util/IListener.js.map +0 -1
  168. package/target/impl/util/Lang.js +0 -263
  169. package/target/impl/util/Lang.js.map +0 -1
  170. package/target/impl/util/XhrQueueController.js +0 -92
  171. package/target/impl/util/XhrQueueController.js.map +0 -1
  172. package/target/impl/xhrCore/ErrorData.js +0 -87
  173. package/target/impl/xhrCore/ErrorData.js.map +0 -1
  174. package/target/impl/xhrCore/EventData.js +0 -52
  175. package/target/impl/xhrCore/EventData.js.map +0 -1
  176. package/target/impl/xhrCore/IResponseProcessor.js +0 -3
  177. package/target/impl/xhrCore/IResponseProcessor.js.map +0 -1
  178. package/target/impl/xhrCore/RequestDataResolver.js +0 -186
  179. package/target/impl/xhrCore/RequestDataResolver.js.map +0 -1
  180. package/target/impl/xhrCore/ResonseDataResolver.js +0 -104
  181. package/target/impl/xhrCore/ResonseDataResolver.js.map +0 -1
  182. package/target/impl/xhrCore/Response.js +0 -186
  183. package/target/impl/xhrCore/Response.js.map +0 -1
  184. package/target/impl/xhrCore/ResponseDataResolver.js +0 -104
  185. package/target/impl/xhrCore/ResponseDataResolver.js.map +0 -1
  186. package/target/impl/xhrCore/ResponseProcessor.js +0 -468
  187. package/target/impl/xhrCore/ResponseProcessor.js.map +0 -1
  188. package/target/impl/xhrCore/XhrFormData.js +0 -163
  189. package/target/impl/xhrCore/XhrFormData.js.map +0 -1
  190. package/target/impl/xhrCore/XhrRequest.js +0 -433
  191. package/target/impl/xhrCore/XhrRequest.js.map +0 -1
  192. package/target/mona_dish_shim.js +0 -70
  193. package/target/mona_dish_shim.js.map +0 -1
  194. package/target/myfaces/OamSubmit.js +0 -128
  195. package/target/myfaces/OamSubmit.js.map +0 -1
  196. package/target/src/main/typescript/api/_api.js.map +0 -1
  197. package/target/src/main/typescript/api/faces.js +0 -45
  198. package/target/src/main/typescript/api/faces.js.map +0 -1
  199. package/target/src/main/typescript/api/jsf.js +0 -56
  200. package/target/src/main/typescript/api/jsf.js.map +0 -1
  201. package/target/src/main/typescript/impl/AjaxImpl.js +0 -748
  202. package/target/src/main/typescript/impl/AjaxImpl.js.map +0 -1
  203. package/target/src/main/typescript/impl/PushImpl.js +0 -265
  204. package/target/src/main/typescript/impl/PushImpl.js.map +0 -1
  205. package/target/src/main/typescript/impl/core/Const.js +0 -177
  206. package/target/src/main/typescript/impl/core/Const.js.map +0 -1
  207. package/target/src/main/typescript/impl/core/ImplTypes.js +0 -38
  208. package/target/src/main/typescript/impl/core/ImplTypes.js.map +0 -1
  209. package/target/src/main/typescript/impl/i18n/Messages.js +0 -113
  210. package/target/src/main/typescript/impl/i18n/Messages.js.map +0 -1
  211. package/target/src/main/typescript/impl/util/Assertions.js +0 -101
  212. package/target/src/main/typescript/impl/util/Assertions.js.map +0 -1
  213. package/target/src/main/typescript/impl/util/AsyncRunnable.js +0 -78
  214. package/target/src/main/typescript/impl/util/AsyncRunnable.js.map +0 -1
  215. package/target/src/main/typescript/impl/util/ExtDomQuery.js +0 -306
  216. package/target/src/main/typescript/impl/util/ExtDomQuery.js.map +0 -1
  217. package/target/src/main/typescript/impl/util/FileUtils.js +0 -98
  218. package/target/src/main/typescript/impl/util/FileUtils.js.map +0 -1
  219. package/target/src/main/typescript/impl/util/HiddenInputBuilder.js +0 -83
  220. package/target/src/main/typescript/impl/util/HiddenInputBuilder.js.map +0 -1
  221. package/target/src/main/typescript/impl/util/IListener.js +0 -3
  222. package/target/src/main/typescript/impl/util/IListener.js.map +0 -1
  223. package/target/src/main/typescript/impl/util/Lang.js +0 -263
  224. package/target/src/main/typescript/impl/util/Lang.js.map +0 -1
  225. package/target/src/main/typescript/impl/util/XhrQueueController.js +0 -92
  226. package/target/src/main/typescript/impl/util/XhrQueueController.js.map +0 -1
  227. package/target/src/main/typescript/impl/xhrCore/ErrorData.js +0 -87
  228. package/target/src/main/typescript/impl/xhrCore/ErrorData.js.map +0 -1
  229. package/target/src/main/typescript/impl/xhrCore/EventData.js +0 -52
  230. package/target/src/main/typescript/impl/xhrCore/EventData.js.map +0 -1
  231. package/target/src/main/typescript/impl/xhrCore/IResponseProcessor.js +0 -3
  232. package/target/src/main/typescript/impl/xhrCore/IResponseProcessor.js.map +0 -1
  233. package/target/src/main/typescript/impl/xhrCore/RequestDataResolver.js +0 -186
  234. package/target/src/main/typescript/impl/xhrCore/RequestDataResolver.js.map +0 -1
  235. package/target/src/main/typescript/impl/xhrCore/Response.js +0 -186
  236. package/target/src/main/typescript/impl/xhrCore/Response.js.map +0 -1
  237. package/target/src/main/typescript/impl/xhrCore/ResponseDataResolver.js +0 -104
  238. package/target/src/main/typescript/impl/xhrCore/ResponseDataResolver.js.map +0 -1
  239. package/target/src/main/typescript/impl/xhrCore/ResponseProcessor.js +0 -468
  240. package/target/src/main/typescript/impl/xhrCore/ResponseProcessor.js.map +0 -1
  241. package/target/src/main/typescript/impl/xhrCore/XhrFormData.js +0 -163
  242. package/target/src/main/typescript/impl/xhrCore/XhrFormData.js.map +0 -1
  243. package/target/src/main/typescript/impl/xhrCore/XhrRequest.js +0 -433
  244. package/target/src/main/typescript/impl/xhrCore/XhrRequest.js.map +0 -1
  245. package/target/src/main/typescript/mona_dish_shim.js +0 -70
  246. package/target/src/main/typescript/mona_dish_shim.js.map +0 -1
  247. package/target/src/main/typescript/myfaces/OamSubmit.js +0 -128
  248. package/target/src/main/typescript/myfaces/OamSubmit.js.map +0 -1
  249. package/target/src/main/typescript/test/api/MyFacesABTest.spec.js +0 -117
  250. package/target/src/main/typescript/test/api/MyFacesABTest.spec.js.map +0 -1
  251. package/target/src/main/typescript/test/frameworkBase/LangTest.spec.js +0 -123
  252. package/target/src/main/typescript/test/frameworkBase/LangTest.spec.js.map +0 -1
  253. package/target/src/main/typescript/test/frameworkBase/_ext/monadish/DomQueryTest.spec.js +0 -657
  254. package/target/src/main/typescript/test/frameworkBase/_ext/monadish/DomQueryTest.spec.js.map +0 -1
  255. package/target/src/main/typescript/test/frameworkBase/_ext/monadish/LangTest.spec.js +0 -107
  256. package/target/src/main/typescript/test/frameworkBase/_ext/monadish/LangTest.spec.js.map +0 -1
  257. package/target/src/main/typescript/test/frameworkBase/_ext/monadish/MappingProbes.js +0 -106
  258. package/target/src/main/typescript/test/frameworkBase/_ext/monadish/MappingProbes.js.map +0 -1
  259. package/target/src/main/typescript/test/frameworkBase/_ext/monadish/MappingTest.spec.js +0 -39
  260. package/target/src/main/typescript/test/frameworkBase/_ext/monadish/MappingTest.spec.js.map +0 -1
  261. package/target/src/main/typescript/test/frameworkBase/_ext/monadish/MonadTest.spec.js +0 -153
  262. package/target/src/main/typescript/test/frameworkBase/_ext/monadish/MonadTest.spec.js.map +0 -1
  263. package/target/src/main/typescript/test/frameworkBase/_ext/monadish/XmlQueryTest.spec.js +0 -2
  264. package/target/src/main/typescript/test/frameworkBase/_ext/monadish/XmlQueryTest.spec.js.map +0 -1
  265. package/target/src/main/typescript/test/frameworkBase/_ext/monadish/markups/tobago-with-header.js +0 -925
  266. package/target/src/main/typescript/test/frameworkBase/_ext/monadish/markups/tobago-with-header.js.map +0 -1
  267. package/target/src/main/typescript/test/frameworkBase/_ext/monadish/markups/tobago-without-header.js +0 -112
  268. package/target/src/main/typescript/test/frameworkBase/_ext/monadish/markups/tobago-without-header.js.map +0 -1
  269. package/target/src/main/typescript/test/frameworkBase/_ext/shared/StandardInits.js +0 -728
  270. package/target/src/main/typescript/test/frameworkBase/_ext/shared/StandardInits.js.map +0 -1
  271. package/target/src/main/typescript/test/frameworkBase/_ext/shared/XmlResponses.js +0 -296
  272. package/target/src/main/typescript/test/frameworkBase/_ext/shared/XmlResponses.js.map +0 -1
  273. package/target/src/main/typescript/test/impl/ImplTest.spec.js +0 -225
  274. package/target/src/main/typescript/test/impl/ImplTest.spec.js.map +0 -1
  275. package/target/src/main/typescript/test/impl/ImplTest_23.spec.js +0 -143
  276. package/target/src/main/typescript/test/impl/ImplTest_23.spec.js.map +0 -1
  277. package/target/src/main/typescript/test/impl/SeparatorCharsTest.spec.js +0 -106
  278. package/target/src/main/typescript/test/impl/SeparatorCharsTest.spec.js.map +0 -1
  279. package/target/src/main/typescript/test/impl/util/ExtDomQueryTest.spec.js +0 -77
  280. package/target/src/main/typescript/test/impl/util/ExtDomQueryTest.spec.js.map +0 -1
  281. package/target/src/main/typescript/test/myfaces/OamSubmit.spec.js +0 -118
  282. package/target/src/main/typescript/test/myfaces/OamSubmit.spec.js.map +0 -1
  283. package/target/src/main/typescript/test/myfaces/OnLoad.spec.js +0 -57
  284. package/target/src/main/typescript/test/myfaces/OnLoad.spec.js.map +0 -1
  285. package/target/src/main/typescript/test/myfaces/ReserveNamespace.spec.js +0 -60
  286. package/target/src/main/typescript/test/myfaces/ReserveNamespace.spec.js.map +0 -1
  287. package/target/src/main/typescript/test/queue/AsynchronousProbe.js +0 -93
  288. package/target/src/main/typescript/test/queue/AsynchronousProbe.js.map +0 -1
  289. package/target/src/main/typescript/test/queue/AsynchronousQueueTest.spec.js +0 -133
  290. package/target/src/main/typescript/test/queue/AsynchronousQueueTest.spec.js.map +0 -1
  291. package/target/src/main/typescript/test/xhrCore/ClientWindow.spec.js +0 -101
  292. package/target/src/main/typescript/test/xhrCore/ClientWindow.spec.js.map +0 -1
  293. package/target/src/main/typescript/test/xhrCore/ErrorChainTest.spec.js +0 -175
  294. package/target/src/main/typescript/test/xhrCore/ErrorChainTest.spec.js.map +0 -1
  295. package/target/src/main/typescript/test/xhrCore/EventTests.spec.js +0 -184
  296. package/target/src/main/typescript/test/xhrCore/EventTests.spec.js.map +0 -1
  297. package/target/src/main/typescript/test/xhrCore/FakeWebsocket.js.map +0 -1
  298. package/target/src/main/typescript/test/xhrCore/FileUploadTest.spec.js +0 -181
  299. package/target/src/main/typescript/test/xhrCore/FileUploadTest.spec.js.map +0 -1
  300. package/target/src/main/typescript/test/xhrCore/NamespacesRequestTest.spec.js +0 -226
  301. package/target/src/main/typescript/test/xhrCore/NamespacesRequestTest.spec.js.map +0 -1
  302. package/target/src/main/typescript/test/xhrCore/OamSubmitTest.spec.js +0 -199
  303. package/target/src/main/typescript/test/xhrCore/OamSubmitTest.spec.js.map +0 -1
  304. package/target/src/main/typescript/test/xhrCore/RequestParamsTest.spec.js +0 -567
  305. package/target/src/main/typescript/test/xhrCore/RequestParamsTest.spec.js.map +0 -1
  306. package/target/src/main/typescript/test/xhrCore/RequestTest.spec.js +0 -845
  307. package/target/src/main/typescript/test/xhrCore/RequestTest.spec.js.map +0 -1
  308. package/target/src/main/typescript/test/xhrCore/RequestTest_23.spec.js +0 -382
  309. package/target/src/main/typescript/test/xhrCore/RequestTest_23.spec.js.map +0 -1
  310. package/target/src/main/typescript/test/xhrCore/ResponseTest.spec.js +0 -667
  311. package/target/src/main/typescript/test/xhrCore/ResponseTest.spec.js.map +0 -1
  312. package/target/src/main/typescript/test/xhrCore/ResponseTest23.spec.js +0 -367
  313. package/target/src/main/typescript/test/xhrCore/ResponseTest23.spec.js.map +0 -1
  314. package/target/src/main/typescript/test/xhrCore/ShadowDomTest.spec.js +0 -123
  315. package/target/src/main/typescript/test/xhrCore/ShadowDomTest.spec.js.map +0 -1
  316. package/target/src/main/typescript/test/xhrCore/TobagoFileUploadTest.spec.js +0 -147
  317. package/target/src/main/typescript/test/xhrCore/TobagoFileUploadTest.spec.js.map +0 -1
  318. package/target/src/main/typescript/test/xhrCore/WebsocketTest.js +0 -207
  319. package/target/src/main/typescript/test/xhrCore/WebsocketTest.js.map +0 -1
  320. package/target/src/main/typescript/test/xhrCore/XhrFormDataTest.spec.js +0 -149
  321. package/target/src/main/typescript/test/xhrCore/XhrFormDataTest.spec.js.map +0 -1
  322. package/target/src/main/typescript/test/xhrCore/XhrRequestProgress.spec.js +0 -130
  323. package/target/src/main/typescript/test/xhrCore/XhrRequestProgress.spec.js.map +0 -1
  324. package/target/test/api/MyFacesABTest.spec.js +0 -117
  325. package/target/test/api/MyFacesABTest.spec.js.map +0 -1
  326. package/target/test/frameworkBase/LangTest.spec.js +0 -123
  327. package/target/test/frameworkBase/LangTest.spec.js.map +0 -1
  328. package/target/test/frameworkBase/_ext/monadish/DomQueryTest.spec.js +0 -657
  329. package/target/test/frameworkBase/_ext/monadish/DomQueryTest.spec.js.map +0 -1
  330. package/target/test/frameworkBase/_ext/monadish/LangTest.spec.js +0 -107
  331. package/target/test/frameworkBase/_ext/monadish/LangTest.spec.js.map +0 -1
  332. package/target/test/frameworkBase/_ext/monadish/MappingProbes.js +0 -106
  333. package/target/test/frameworkBase/_ext/monadish/MappingProbes.js.map +0 -1
  334. package/target/test/frameworkBase/_ext/monadish/MappingTest.spec.js +0 -39
  335. package/target/test/frameworkBase/_ext/monadish/MappingTest.spec.js.map +0 -1
  336. package/target/test/frameworkBase/_ext/monadish/MonadTest.spec.js +0 -153
  337. package/target/test/frameworkBase/_ext/monadish/MonadTest.spec.js.map +0 -1
  338. package/target/test/frameworkBase/_ext/monadish/XmlQueryTest.spec.js +0 -1
  339. package/target/test/frameworkBase/_ext/monadish/XmlQueryTest.spec.js.map +0 -1
  340. package/target/test/frameworkBase/_ext/monadish/fixtures/test.js.map +0 -1
  341. package/target/test/frameworkBase/_ext/monadish/fixtures/test2.js.map +0 -1
  342. package/target/test/frameworkBase/_ext/monadish/markups/tobago-with-header.js +0 -925
  343. package/target/test/frameworkBase/_ext/monadish/markups/tobago-with-header.js.map +0 -1
  344. package/target/test/frameworkBase/_ext/monadish/markups/tobago-without-header.js +0 -112
  345. package/target/test/frameworkBase/_ext/monadish/markups/tobago-without-header.js.map +0 -1
  346. package/target/test/frameworkBase/_ext/shared/StandardInits.js +0 -728
  347. package/target/test/frameworkBase/_ext/shared/StandardInits.js.map +0 -1
  348. package/target/test/frameworkBase/_ext/shared/XmlResponses.js +0 -296
  349. package/target/test/frameworkBase/_ext/shared/XmlResponses.js.map +0 -1
  350. package/target/test/frameworkBase/_ext/shared/fixtures/js/tobago.js +0 -16
  351. package/target/test/frameworkBase/_ext/shared/fixtures/js/tobago.js.map +0 -1
  352. package/target/test/impl/ImplTest.spec.js +0 -225
  353. package/target/test/impl/ImplTest.spec.js.map +0 -1
  354. package/target/test/impl/ImplTest_23.spec.js +0 -143
  355. package/target/test/impl/ImplTest_23.spec.js.map +0 -1
  356. package/target/test/impl/SeparatorCharsTest.spec.js +0 -106
  357. package/target/test/impl/SeparatorCharsTest.spec.js.map +0 -1
  358. package/target/test/impl/util/ExtDomQueryTest.spec.js +0 -77
  359. package/target/test/impl/util/ExtDomQueryTest.spec.js.map +0 -1
  360. package/target/test/myfaces/OamSubmit.spec.js +0 -118
  361. package/target/test/myfaces/OamSubmit.spec.js.map +0 -1
  362. package/target/test/myfaces/OnLoad.spec.js +0 -57
  363. package/target/test/myfaces/OnLoad.spec.js.map +0 -1
  364. package/target/test/myfaces/ReserveNamespace.spec.js +0 -60
  365. package/target/test/myfaces/ReserveNamespace.spec.js.map +0 -1
  366. package/target/test/queue/AsynchronousProbe.js +0 -93
  367. package/target/test/queue/AsynchronousProbe.js.map +0 -1
  368. package/target/test/queue/AsynchronousQueueTest.spec.js +0 -133
  369. package/target/test/queue/AsynchronousQueueTest.spec.js.map +0 -1
  370. package/target/test/xhrCore/ClientWindow.spec.js +0 -101
  371. package/target/test/xhrCore/ClientWindow.spec.js.map +0 -1
  372. package/target/test/xhrCore/ErrorChainTest.spec.js +0 -175
  373. package/target/test/xhrCore/ErrorChainTest.spec.js.map +0 -1
  374. package/target/test/xhrCore/EventTests.spec.js +0 -184
  375. package/target/test/xhrCore/EventTests.spec.js.map +0 -1
  376. package/target/test/xhrCore/FakeWebsocket.js +0 -38
  377. package/target/test/xhrCore/FakeWebsocket.js.map +0 -1
  378. package/target/test/xhrCore/FileUploadTest.spec.js +0 -181
  379. package/target/test/xhrCore/FileUploadTest.spec.js.map +0 -1
  380. package/target/test/xhrCore/NamespacesRequestTest.spec.js +0 -226
  381. package/target/test/xhrCore/NamespacesRequestTest.spec.js.map +0 -1
  382. package/target/test/xhrCore/OamSubmitTest.spec.js +0 -199
  383. package/target/test/xhrCore/OamSubmitTest.spec.js.map +0 -1
  384. package/target/test/xhrCore/RequestParamsTest.spec.js +0 -567
  385. package/target/test/xhrCore/RequestParamsTest.spec.js.map +0 -1
  386. package/target/test/xhrCore/RequestTest.spec.js +0 -845
  387. package/target/test/xhrCore/RequestTest.spec.js.map +0 -1
  388. package/target/test/xhrCore/RequestTest_23.spec.js +0 -382
  389. package/target/test/xhrCore/RequestTest_23.spec.js.map +0 -1
  390. package/target/test/xhrCore/ResponseTest.spec.js +0 -667
  391. package/target/test/xhrCore/ResponseTest.spec.js.map +0 -1
  392. package/target/test/xhrCore/ResponseTest23.spec.js +0 -367
  393. package/target/test/xhrCore/ResponseTest23.spec.js.map +0 -1
  394. package/target/test/xhrCore/ShadowDomTest.spec.js +0 -123
  395. package/target/test/xhrCore/ShadowDomTest.spec.js.map +0 -1
  396. package/target/test/xhrCore/TobagoFileUploadTest.spec.js +0 -147
  397. package/target/test/xhrCore/TobagoFileUploadTest.spec.js.map +0 -1
  398. package/target/test/xhrCore/WebsocketTest.js +0 -207
  399. package/target/test/xhrCore/WebsocketTest.js.map +0 -1
  400. package/target/test/xhrCore/XhrFormDataTest.spec.js +0 -149
  401. package/target/test/xhrCore/XhrFormDataTest.spec.js.map +0 -1
  402. package/target/test/xhrCore/XhrRequestProgress.spec.js +0 -130
  403. package/target/test/xhrCore/XhrRequestProgress.spec.js.map +0 -1
  404. package/target/test/xhrCore/fixtures/addedViewHead1.js +0 -17
  405. package/target/test/xhrCore/fixtures/addedViewHead1.js.map +0 -1
  406. package/target/test/xhrCore/fixtures/addedViewHead2.js +0 -17
  407. package/target/test/xhrCore/fixtures/addedViewHead2.js.map +0 -1
  408. package/target/test/xhrCore/fixtures/addedViewHead3.js +0 -17
  409. package/target/test/xhrCore/fixtures/addedViewHead3.js.map +0 -1
  410. package/target/test/xhrCore/fixtures/nonce_script.js +0 -17
  411. package/target/test/xhrCore/fixtures/nonce_script.js.map +0 -1
  412. package/tsconfig.json +0 -9
  413. package/webpack.config.ts +0 -54
@@ -0,0 +1,764 @@
1
+ /*! Licensed to the Apache Software Foundation (ASF) under one or more
2
+ * contributor license agreements. See the NOTICE file distributed with
3
+ * this work for additional information regarding copyright ownership.
4
+ * The ASF licenses this file to you under the Apache License, Version 2.0
5
+ * (the "License"); you may not use this file except in compliance with
6
+ * the License. You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ // AI-generated: this file was created with assistance from Claude (Anthropic) — see AI_CONTRIBUTIONS.md
17
+ import {describe} from "mocha";
18
+ import * as sinon from "sinon";
19
+ import * as nise from "nise";
20
+ import {StandardInits} from "../frameworkBase/_ext/shared/StandardInits";
21
+ import {Implementation} from "../../impl/AjaxImpl";
22
+
23
+ import {expect} from "chai";
24
+
25
+ const defaultMyFaces = StandardInits.defaultMyFaces;
26
+ import {_Es2019Array, Lang} from "mona-dish";
27
+ import {FakeWebsocket} from "./FakeWebsocket";
28
+ import {MAX_RECONNECT_ATTEMPTS, REASON_EXPIRED, RECONNECT_INTERVAL} from "../../impl/core/Const";
29
+ const assertType = Lang.assertType;
30
+
31
+ declare var faces: any;
32
+
33
+ describe('Tests the jsf websocket client side api on high level (generic test without any myfaces dependencies', function () {
34
+ let oldFlatMap = null;
35
+ beforeEach(async function () {
36
+ let oldFlatMap = null;
37
+ let waitForResult = defaultMyFaces();
38
+
39
+ return waitForResult.then((close) => {
40
+
41
+ this.xhr = nise.fakeXhr.useFakeXMLHttpRequest();
42
+ this.requests = [];
43
+ this.xhr.onCreate = (xhr) => {
44
+ this.requests.push(xhr);
45
+ };
46
+ (global as any).XMLHttpRequest = this.xhr;
47
+ window.XMLHttpRequest = this.xhr;
48
+
49
+ this.jsfAjaxResponse = sinon.stub((global as any).faces.ajax, "response");
50
+
51
+ this.fakeWebsocket = new FakeWebsocket();
52
+ this.socket = sinon.stub(window, 'WebSocket').returns(this.fakeWebsocket);
53
+ (global as any).WebSocket = this.socket;
54
+
55
+ this.pushImpl = (global as any).PushImpl;
56
+ this.initSpy = sinon.spy(this.pushImpl, "init");
57
+ oldFlatMap =Array.prototype["flatMap"];
58
+ window["Es2019Array"] = _Es2019Array;
59
+ delete Array.prototype["flatMap"];
60
+
61
+ this.closeIt = () => {
62
+ (global as any).XMLHttpRequest = window.XMLHttpRequest = this.xhr.restore();
63
+ this.jsfAjaxResponse.restore();
64
+ this.socket.restore();
65
+ this.initSpy.restore();
66
+ delete (global as any).WebSocket;
67
+ Implementation.reset();
68
+ close();
69
+ }
70
+ });
71
+
72
+ });
73
+
74
+ afterEach(function () {
75
+ this.closeIt();
76
+ if(oldFlatMap) {
77
+ Array.prototype["flatMap"] = oldFlatMap;
78
+ oldFlatMap = null;
79
+ }
80
+ });
81
+
82
+ it("must register a channel", function (done: Function) {
83
+ // faces.push.init (Faces 4) includes onerror. PushImpl keeps the same signature
84
+ // so the JSF 2.3 compatibility shim can pass null for that callback.
85
+
86
+ try {
87
+ faces.push.init("clientId1", "booga.ws", "mychannel",
88
+ () => { done(); }, // onopen
89
+ () => {}, // onmessage
90
+ () => {}, // onerror
91
+ () => {}, // onclose
92
+ "", // behaviorScripts
93
+ true // autoConnect
94
+ );
95
+
96
+ expect(this.initSpy.called).to.be.true;
97
+
98
+ let calledArgs = this.initSpy?.getCall(0)?.args;
99
+
100
+ expect(calledArgs[0]).to.eq("clientId1");
101
+ expect(calledArgs[1]).to.eq("booga.ws");
102
+ expect(calledArgs[2]).to.eq("mychannel");
103
+
104
+ expect(assertType(calledArgs[3], "function")).to.be.true; // onopen
105
+ expect(assertType(calledArgs[4], "function")).to.be.true; // onmessage
106
+ expect(assertType(calledArgs[5], "function")).to.be.true; // onerror
107
+ expect(assertType(calledArgs[6], "function")).to.be.true; // onclose
108
+ expect(calledArgs[7]).to.eq(""); // behaviorScripts
109
+ expect(calledArgs[8]).to.be.true; // autoConnect
110
+
111
+ // implementation-level state
112
+ expect("clientId1" in this.pushImpl.components, "a component must be registered").to.be.true;
113
+ expect("booga.ws" in this.pushImpl.sockets, "a socket must be registered").to.be.true;
114
+ } finally {
115
+ }
116
+ });
117
+
118
+ it("callbacks must be called", function (done) {
119
+
120
+
121
+ let openCalled = false;
122
+ let closeCalled = false;
123
+ let messageCalled = false;
124
+
125
+ let msg = null;
126
+ let cnl = null;
127
+ new Promise((resolve) => {
128
+ faces.push.init("blarg", "booga.ws", "mychannel", () => {
129
+ openCalled = true;
130
+ this.fakeWebsocket._respond({data: '"booga"'});
131
+ },
132
+
133
+ (message: string, channel: string) => {
134
+ messageCalled = true;
135
+ msg = message;
136
+ cnl = channel;
137
+ resolve(() => true);
138
+ },
139
+ () => {},
140
+ () => {
141
+ closeCalled = true;
142
+ },
143
+ "",
144
+ true
145
+ );
146
+ }).then(() => {
147
+ expect(openCalled, "Open must have been called due to autoConnect").to.be.true;
148
+
149
+
150
+
151
+ expect(messageCalled, "on a server response the message must have been called").to.be.true;
152
+ expect(msg, "proper message must be passed").to.eq("booga");
153
+ expect(cnl, "proper message must be passed").to.eq("mychannel");
154
+
155
+ expect(closeCalled, "websocket still open").to.be.false;
156
+
157
+ faces.push.close("blarg");
158
+ expect(closeCalled, "websocket now closed").to.be.true;
159
+
160
+
161
+ done();
162
+ });
163
+
164
+ });
165
+
166
+
167
+ it("manual open must work", function (done) {
168
+
169
+
170
+ let openCalled = false;
171
+ let closeCalled = false;
172
+ let messageCalled = false;
173
+
174
+ let msg = null;
175
+ let cnl = null;
176
+ new Promise((resolve) => {
177
+ faces.push.init("blarg", "booga.ws", "mychannel", () => {
178
+ openCalled = true;
179
+ this.fakeWebsocket._respond({data: '"booga"'});
180
+ },
181
+
182
+ (message: string, channel: string) => {
183
+ messageCalled = true;
184
+ msg = message;
185
+ cnl = channel;
186
+ resolve(() => true);
187
+ },
188
+ () => {},
189
+ () => {
190
+ closeCalled = true;
191
+ },
192
+ "",
193
+ false
194
+ );
195
+ faces.push.open("blarg");
196
+ }).then(() => {
197
+ expect(openCalled, "Open must have been called due to open").to.be.true;
198
+
199
+ expect(messageCalled, "on a server response the message must have been called").to.be.true;
200
+ expect(msg, "proper message must be passed").to.eq("booga");
201
+ expect(cnl, "proper message must be passed").to.eq("mychannel");
202
+
203
+ expect(closeCalled, "websocket still open").to.be.false;
204
+
205
+ faces.push.close("blarg");
206
+ expect(closeCalled, "websocket now closed").to.be.true;
207
+
208
+
209
+ done();
210
+ });
211
+
212
+ });
213
+
214
+ it("must call onclose(-1) when WebSocket is not available", function () {
215
+ // Null both window and global so DQ.global().WebSocket is falsy regardless of which the impl reads
216
+ const savedWindow = (window as any).WebSocket;
217
+ const savedGlobal = (global as any).WebSocket;
218
+ (window as any).WebSocket = null;
219
+ (global as any).WebSocket = null;
220
+
221
+ let closeCalled = false;
222
+ let closeCode: any = null;
223
+ let closeChannel: any = null;
224
+
225
+ faces.push.init("blarg", "booga.ws", "nochannel",
226
+ () => {},
227
+ () => {},
228
+ () => {},
229
+ (code: number, channel: string) => { closeCalled = true; closeCode = code; closeChannel = channel; },
230
+ "",
231
+ false
232
+ );
233
+
234
+ (window as any).WebSocket = savedWindow;
235
+ (global as any).WebSocket = savedGlobal;
236
+
237
+ expect(closeCalled, "onclose must be called when WebSocket is unavailable").to.be.true;
238
+ expect(closeCode).to.eq(-1);
239
+ expect(closeChannel).to.eq("nochannel");
240
+ });
241
+
242
+ it("must extract channelToken from the query-string part of the URL", function () {
243
+ faces.push.init("blarg", "ws://example.com/push?mytoken", "mychannel",
244
+ () => {}, () => {}, () => {}, () => {}, "", false
245
+ );
246
+
247
+ expect("mytoken" in this.pushImpl.sockets, "socket must be keyed by the query-string token").to.be.true;
248
+ expect(this.pushImpl.components["blarg"].channelToken).to.eq("mytoken");
249
+ });
250
+
251
+ it("must be idempotent on repeated init with the same socketClientId", function () {
252
+ faces.push.init("blarg", "booga.ws", "mychannel",
253
+ () => {}, () => {}, () => {}, () => {}, "", false
254
+ );
255
+ faces.push.init("blarg", "booga.ws", "mychannel",
256
+ () => {}, () => {}, () => {}, () => {}, "", false
257
+ );
258
+
259
+ expect(Object.keys(this.pushImpl.sockets).length).to.eq(1);
260
+ expect(Object.keys(this.pushImpl.components).length).to.eq(1);
261
+ });
262
+
263
+ it("must fan out onopen to all components sharing the same socket URL", function (done) {
264
+ let open1 = false;
265
+ let open2 = false;
266
+
267
+ faces.push.init("blarg", "booga.ws", "mychannel",
268
+ () => { open1 = true; }, () => {}, () => {}, () => {}, "", false
269
+ );
270
+ faces.push.init("clientId2", "booga.ws", "mychannel",
271
+ () => { open2 = true; }, () => {}, () => {}, () => {}, "", false
272
+ );
273
+
274
+ faces.push.open("blarg");
275
+
276
+ setTimeout(() => {
277
+ expect(open1, "first component onopen must be called").to.be.true;
278
+ expect(open2, "second component onopen must be called").to.be.true;
279
+ done();
280
+ }, 20);
281
+ });
282
+
283
+ it("must invoke registered behavior functions on a matching message", function (done) {
284
+ let behaviorCalled = false;
285
+ const behaviors = { "booga": [() => { behaviorCalled = true; }] };
286
+
287
+ new Promise<void>((resolve) => {
288
+ this.pushImpl.init("blarg", "booga.ws", "mychannel",
289
+ () => { this.fakeWebsocket._respond({data: '"booga"'}); },
290
+ () => { resolve(); },
291
+ null,
292
+ () => {},
293
+ behaviors,
294
+ true
295
+ );
296
+ }).then(() => {
297
+ expect(behaviorCalled, "behavior function must be invoked on matching message key").to.be.true;
298
+ done();
299
+ });
300
+ });
301
+
302
+ it("must invoke onerror and reconnect on a reconnectable abnormal close", function (done) {
303
+ let errorCalled = false;
304
+ let closeCalled = false;
305
+ let errorCode: any = null;
306
+ let errorChannel: any = null;
307
+
308
+ new Promise<void>((resolve) => {
309
+ faces.push.init("blarg", "booga.ws", "mychannel",
310
+ () => {
311
+ setTimeout(() => {
312
+ this.fakeWebsocket._close({code: 1006, reason: "abnormal"});
313
+ resolve();
314
+ }, 20);
315
+ },
316
+ () => {},
317
+ (code: number, channel: string) => { errorCalled = true; errorCode = code; errorChannel = channel; },
318
+ () => { closeCalled = true; },
319
+ "",
320
+ true
321
+ );
322
+ }).then(() => {
323
+ setTimeout(() => {
324
+ expect(errorCalled, "onerror must be called before reconnecting").to.be.true;
325
+ expect(closeCalled, "onclose must not be called while reconnecting").to.be.false;
326
+ expect(errorCode).to.eq(1006);
327
+ expect(errorChannel).to.eq("mychannel");
328
+ expect(this.socket.callCount, "a reconnect must create another WebSocket").to.be.greaterThan(1);
329
+ done();
330
+ }, RECONNECT_INTERVAL + 150);
331
+ });
332
+ });
333
+
334
+ it("must use cumulative reconnect delays across consecutive failed reconnect attempts", function () {
335
+ const clock = sinon.useFakeTimers();
336
+ const firstSocket = new FakeWebsocket();
337
+ const secondSocket = new FakeWebsocket();
338
+ const thirdSocket = new FakeWebsocket();
339
+
340
+ try {
341
+ this.socket.resetBehavior();
342
+ this.socket.onCall(0).returns(firstSocket);
343
+ this.socket.onCall(1).returns(secondSocket);
344
+ this.socket.onCall(2).returns(thirdSocket);
345
+
346
+ faces.push.init("blarg", "booga.ws", "mychannel",
347
+ () => {},
348
+ () => {},
349
+ () => {},
350
+ () => {},
351
+ "",
352
+ true
353
+ );
354
+
355
+ clock.tick(10);
356
+ expect(this.socket.callCount, "initial open must create one WebSocket").to.eq(1);
357
+
358
+ firstSocket._close({code: 1006, reason: "abnormal"});
359
+ expect(firstSocket.readyState, "first socket must be closed before reconnect").to.eq(3);
360
+ expect(this.pushImpl.sockets["booga.ws"].socket,
361
+ "closed socket reference must be cleared before first reconnect is scheduled").to.eq(null);
362
+ clock.tick(RECONNECT_INTERVAL - 1);
363
+ expect(this.socket.callCount, "first reconnect must wait one reconnect interval").to.eq(1);
364
+ clock.tick(1);
365
+ expect(this.socket.callCount, "first reconnect must create the second WebSocket").to.eq(2);
366
+ expect(this.pushImpl.sockets["booga.ws"].socket,
367
+ "first reconnect must store the replacement WebSocket").to.eq(secondSocket);
368
+
369
+ secondSocket._close({code: 1006, reason: "abnormal"});
370
+ expect(secondSocket.readyState, "second socket must be closed before reconnect").to.eq(3);
371
+ expect(this.pushImpl.sockets["booga.ws"].socket,
372
+ "closed socket reference must be cleared before second reconnect is scheduled").to.eq(null);
373
+ clock.tick((RECONNECT_INTERVAL * 2) - 1);
374
+ expect(this.socket.callCount, "second reconnect must wait two reconnect intervals").to.eq(2);
375
+ clock.tick(1);
376
+ expect(this.socket.callCount, "second reconnect must create the third WebSocket").to.eq(3);
377
+ expect(this.pushImpl.sockets["booga.ws"].socket,
378
+ "second reconnect must store the replacement WebSocket").to.eq(thirdSocket);
379
+ } finally {
380
+ clock.restore();
381
+ }
382
+ });
383
+
384
+ it("must not fire onopen again when a reconnect succeeds after a prior working connection", function () {
385
+ // Spec (Jakarta Faces 3+): "This will be invoked on the very first connection attempt."
386
+ // "This will not be invoked when the web socket auto-reconnects a broken connection
387
+ // after the first successful connection."
388
+ // Also verifies reconnectAttempts resets to 0 so a further drop can start a fresh cycle.
389
+ const clock = sinon.useFakeTimers();
390
+ const firstSocket = new FakeWebsocket();
391
+ // Plain object instead of FakeWebsocket: we manually fire onopen so there is no
392
+ // constructor setTimeout that fires at an uncontrolled point in fake-timer time.
393
+ const reconnectWs: any = {
394
+ readyState: 0,
395
+ onopen: () => {}, onmessage: () => {}, onclose: () => {}, onerror: () => {},
396
+ send() {},
397
+ close() { this.readyState = 3; this.onclose({}); }
398
+ };
399
+
400
+ try {
401
+ this.socket.resetBehavior();
402
+ this.socket.onCall(0).returns(firstSocket);
403
+ this.socket.onCall(1).returns(reconnectWs);
404
+
405
+ let openCount = 0;
406
+ faces.push.init("blarg", "booga.ws", "mychannel",
407
+ () => { openCount++; },
408
+ () => {}, () => {}, () => {},
409
+ "",
410
+ true
411
+ );
412
+
413
+ // initial connection succeeds — onopen must fire exactly once
414
+ clock.tick(10);
415
+ expect(openCount, "onopen must fire on the initial connect").to.eq(1);
416
+
417
+ // abnormal close → reconnect scheduled, reconnectAttempts increments to 1
418
+ firstSocket._close({code: 1006, reason: "abnormal"});
419
+ clock.tick(RECONNECT_INTERVAL); // fires open() → reconnectWs bound via bindCallbacks
420
+
421
+ // reconnect succeeds: manually trigger onopen on the newly-bound socket
422
+ reconnectWs.readyState = 1;
423
+ reconnectWs.onopen({});
424
+
425
+ expect(openCount, "onopen must not fire again on a successful reconnect").to.eq(1);
426
+ expect(this.pushImpl.sockets["booga.ws"].reconnectAttempts,
427
+ "reconnectAttempts must reset to 0 after successful reconnect").to.eq(0);
428
+ } finally {
429
+ clock.restore();
430
+ }
431
+ });
432
+
433
+ it("must call onclose and stop reconnecting after MAX_RECONNECT_ATTEMPTS failed attempts", function () {
434
+ const clock = sinon.useFakeTimers();
435
+ // Create the initial socket AFTER installing fake timers so its constructor
436
+ // setTimeout is under fake-timer control — clock.tick(10) will fire onopen.
437
+ // All reconnect attempts return the same object; bindCallbacks() rebinds on each open().
438
+ const initialSocket = new FakeWebsocket();
439
+ this.socket.resetBehavior();
440
+ this.socket.returns(initialSocket);
441
+
442
+ let closeCalled = false;
443
+ let closeCode: any = null;
444
+
445
+ try {
446
+ faces.push.init("blarg", "booga.ws", "mychannel",
447
+ () => {},
448
+ () => {},
449
+ () => {},
450
+ (code: number) => { closeCalled = true; closeCode = code; },
451
+ "",
452
+ true
453
+ );
454
+
455
+ // tick past FakeWebsocket constructor setTimeout so initial onopen fires (hasEverConnected = true)
456
+ clock.tick(10);
457
+
458
+ // drive MAX_RECONNECT_ATTEMPTS abnormal closes; each close schedules the next open
459
+ // and the tick fires it, leaving reconnectAttempts = MAX_RECONNECT_ATTEMPTS after the loop
460
+ for (let attempt = 1; attempt <= MAX_RECONNECT_ATTEMPTS; attempt++) {
461
+ initialSocket._close({code: 1006, reason: "abnormal"});
462
+ clock.tick(RECONNECT_INTERVAL * attempt);
463
+ }
464
+
465
+ expect(closeCalled, "onclose must not fire while reconnect budget remains").to.be.false;
466
+
467
+ // this close tips reconnectAttempts over the limit → terminal path
468
+ initialSocket._close({code: 1006, reason: "abnormal"});
469
+
470
+ expect(closeCalled, "onclose must fire once all reconnect attempts are exhausted").to.be.true;
471
+ expect(closeCode).to.eq(1006);
472
+ } finally {
473
+ clock.restore();
474
+ }
475
+ });
476
+
477
+ it("must call onclose callback when server closes with REASON_EXPIRED", function (done) {
478
+ let closeCalled = false;
479
+ let closeCode: any = null;
480
+
481
+ new Promise<void>((resolve) => {
482
+ faces.push.init("blarg", "booga.ws", "mychannel",
483
+ () => { this.fakeWebsocket._close({code: 1000, reason: REASON_EXPIRED}); },
484
+ () => {},
485
+ () => {},
486
+ (code: number) => { closeCalled = true; closeCode = code; resolve(); },
487
+ "",
488
+ true
489
+ );
490
+ }).then(() => {
491
+ expect(closeCalled, "onclose must be called on REASON_EXPIRED terminal close").to.be.true;
492
+ expect(closeCode).to.eq(1000);
493
+ done();
494
+ });
495
+ });
496
+
497
+ it("must treat any close code 1000 as terminal and not reconnect", function (done) {
498
+ let closeCalled = false;
499
+ let errorCalled = false;
500
+ let closeCode: any = null;
501
+ const wsCallCount = this.socket.callCount;
502
+
503
+ new Promise<void>((resolve) => {
504
+ faces.push.init("blarg", "booga.ws", "mychannel",
505
+ () => { this.fakeWebsocket._close({code: 1000, reason: "Normal Closure"}); },
506
+ () => {},
507
+ () => { errorCalled = true; },
508
+ (code: number) => { closeCalled = true; closeCode = code; resolve(); },
509
+ "",
510
+ true
511
+ );
512
+ }).then(() => {
513
+ expect(closeCalled, "onclose must be called for any 1000 terminal close").to.be.true;
514
+ expect(closeCode).to.eq(1000);
515
+ expect(errorCalled, "onerror must not be called for a normal terminal close").to.be.false;
516
+ expect(this.socket.callCount, "no reconnect WebSocket must be created after 1000").to.eq(wsCallCount + 1);
517
+ done();
518
+ });
519
+ });
520
+
521
+ it("must treat close code 1008 (Policy Violation) as terminal and not reconnect", function (done) {
522
+ // 1008 = server rejected due to authorization/security failure.
523
+ // Reconnecting would hit the same rejection, so it must be treated as terminal:
524
+ // onclose fires, onerror does not, no new WebSocket is created.
525
+ let closeCalled = false;
526
+ let errorCalled = false;
527
+ let closeCode: any = null;
528
+ const wsCallCount = this.socket.callCount;
529
+
530
+ new Promise<void>((resolve) => {
531
+ faces.push.init("blarg", "booga.ws", "mychannel",
532
+ () => { this.fakeWebsocket._close({code: 1008, reason: "Policy Violation"}); },
533
+ () => {},
534
+ () => { errorCalled = true; },
535
+ (code: number) => { closeCalled = true; closeCode = code; resolve(); },
536
+ "",
537
+ true
538
+ );
539
+ }).then(() => {
540
+ expect(closeCalled, "onclose must be called for a 1008 terminal close").to.be.true;
541
+ expect(closeCode).to.eq(1008);
542
+ expect(errorCalled, "onerror must not be called for a terminal close").to.be.false;
543
+ expect(this.socket.callCount, "no reconnect WebSocket must be created after 1008").to.eq(wsCallCount + 1);
544
+ done();
545
+ });
546
+ });
547
+
548
+ it("must treat failed first connection attempt as terminal and not reconnect", function () {
549
+ const firstSocket: any = {
550
+ readyState: 0,
551
+ onopen: () => {}, onmessage: () => {}, onclose: () => {}, onerror: () => {},
552
+ send() {},
553
+ close() { this.readyState = 3; this.onclose({}); }
554
+ };
555
+ this.socket.resetBehavior();
556
+ this.socket.returns(firstSocket);
557
+
558
+ let closeCalled = false;
559
+ let errorCalled = false;
560
+ let closeCode: any = null;
561
+
562
+ faces.push.init("blarg", "booga.ws", "mychannel",
563
+ () => {},
564
+ () => {},
565
+ () => { errorCalled = true; },
566
+ (code: number) => { closeCalled = true; closeCode = code; },
567
+ "",
568
+ true
569
+ );
570
+
571
+ firstSocket.readyState = 3;
572
+ firstSocket.onclose({code: 1006, reason: "initial failure"});
573
+
574
+ expect(closeCalled, "onclose must be called when the first connection attempt fails").to.be.true;
575
+ expect(closeCode).to.eq(1006);
576
+ expect(errorCalled, "onerror must not be called for a failed first connection attempt").to.be.false;
577
+ expect(this.socket.callCount, "no reconnect WebSocket must be created after first-attempt failure").to.eq(1);
578
+ });
579
+
580
+ it("must fire onopen again when open() is called after a terminal close", function (done) {
581
+ // After any terminal close (1000, 1008, max retries, first-attempt failure),
582
+ // a subsequent explicit faces.push.open() must treat the new attempt as a
583
+ // fresh first connection — onopen fires again and the error/reconnect state is reset.
584
+ let openCount = 0;
585
+ let closeCount = 0;
586
+
587
+ new Promise<void>((resolve) => {
588
+ faces.push.init("blarg", "booga.ws", "mychannel",
589
+ () => {
590
+ openCount++;
591
+ if (openCount === 1) {
592
+ // trigger terminal close from within onopen of first connection
593
+ this.fakeWebsocket._close({code: 1000, reason: "Normal"});
594
+ } else {
595
+ resolve();
596
+ }
597
+ },
598
+ () => {},
599
+ () => {},
600
+ () => { closeCount++; },
601
+ "",
602
+ true
603
+ );
604
+ }).then(() => {
605
+ expect(openCount, "onopen must fire twice — once per explicit connection").to.eq(2);
606
+ expect(closeCount, "onclose must fire exactly once for the terminal close").to.eq(1);
607
+ done();
608
+ });
609
+
610
+ // Create secondSocket here so its constructor timer fires ~10ms AFTER bindCallbacks()
611
+ // is called by the explicit open(), not 50ms before it.
612
+ setTimeout(() => {
613
+ const secondSocket = new FakeWebsocket();
614
+ this.socket.onCall(1).returns(secondSocket);
615
+ faces.push.open("blarg");
616
+ }, 50);
617
+ });
618
+
619
+ it("must close existing sockets when PushImpl.reset() is called", function () {
620
+ faces.push.init("blarg", "booga.ws", "mychannel",
621
+ () => {},
622
+ () => {},
623
+ () => {},
624
+ () => {},
625
+ "",
626
+ true
627
+ );
628
+
629
+ const closeSpy = sinon.spy(this.fakeWebsocket, "close");
630
+
631
+ this.pushImpl.reset();
632
+
633
+ expect(closeSpy.calledOnce, "reset must close the existing WebSocket").to.be.true;
634
+ });
635
+
636
+ it("must ignore late native onopen callback after reset tears down the channel registry", function () {
637
+ let openCalled = false;
638
+
639
+ faces.push.init("blarg", "booga.ws", "mychannel",
640
+ () => { openCalled = true; },
641
+ () => {},
642
+ () => {},
643
+ () => {},
644
+ "",
645
+ true
646
+ );
647
+
648
+ this.pushImpl.reset();
649
+
650
+ expect(() => this.fakeWebsocket.onopen({})).not.to.throw();
651
+ expect(openCalled, "user onopen must have fired for the initial connection attempt").to.be.true;
652
+ });
653
+
654
+ it("must ignore pending onclose callback after reset tears down the channel registry", function () {
655
+ let closeCount = 0;
656
+
657
+ faces.push.init("blarg", "booga.ws", "mychannel",
658
+ () => {},
659
+ () => {},
660
+ () => {},
661
+ () => { closeCount++; },
662
+ "",
663
+ true
664
+ );
665
+
666
+ this.pushImpl.reset();
667
+ const closeCountAfterReset = closeCount;
668
+
669
+ expect(() => this.fakeWebsocket._close({code: 1006, reason: "abnormal"})).not.to.throw();
670
+ expect(closeCount, "late onclose must not call component callbacks after reset").to.eq(closeCountAfterReset);
671
+ });
672
+
673
+ it("must ignore pending onmessage callback after reset tears down the channel registry", function () {
674
+ let messageCount = 0;
675
+
676
+ faces.push.init("blarg", "booga.ws", "mychannel",
677
+ () => {},
678
+ () => { messageCount++; },
679
+ () => {},
680
+ () => {},
681
+ "",
682
+ true
683
+ );
684
+
685
+ this.pushImpl.reset();
686
+
687
+ expect(() => this.fakeWebsocket._respond({data: JSON.stringify("message")})).not.to.throw();
688
+ expect(messageCount, "late onmessage must not call component callbacks after reset").to.eq(0);
689
+ });
690
+
691
+ it("must ignore native WebSocket error events", function () {
692
+ let errorCalled = false;
693
+
694
+ faces.push.init("blarg", "booga.ws", "mychannel",
695
+ () => {},
696
+ () => {},
697
+ () => { errorCalled = true; },
698
+ () => {},
699
+ "",
700
+ true
701
+ );
702
+
703
+ expect(() => this.fakeWebsocket._error({data: '{"code":1006}'})).not.to.throw();
704
+ expect(errorCalled, "Faces onerror is only fired from reconnectable close handling").to.be.false;
705
+ });
706
+
707
+ it("must remove stale components whose DOM element has been removed", function (done) {
708
+ const channelToken = "booga.ws"; // no '?' so token == full URL
709
+
710
+ new Promise<void>((resolve) => {
711
+ faces.push.init("nonexistent-id", "booga.ws", "mychannel",
712
+ () => { this.fakeWebsocket._respond({data: '"ping"'}); resolve(); },
713
+ () => {},
714
+ () => {},
715
+ () => {},
716
+ "",
717
+ true
718
+ );
719
+ }).then(() => {
720
+ expect(this.pushImpl.clientIdsByTokens[channelToken].length,
721
+ "stale component must be removed from clientIdsByTokens").to.eq(0);
722
+ done();
723
+ });
724
+ });
725
+
726
+ it("must close the socket when all components are gone after an error-close", function () {
727
+ const channelToken = "booga.ws";
728
+
729
+ faces.push.init("clientId_close_test", "booga.ws", "mychannel",
730
+ () => {},
731
+ () => {},
732
+ () => {},
733
+ () => {},
734
+ "",
735
+ true
736
+ );
737
+
738
+ // After push.init with autoConnect=true, Socket.open() has already assigned
739
+ // its handler to fakeWebsocket.onopen. Invoking it directly marks the socket
740
+ // as hasEverConnected=true, which is required for the subsequent abnormal close
741
+ // to take the reconnectable (non-terminal) path.
742
+ this.fakeWebsocket.onopen({});
743
+
744
+ // Remove the component from the registry so the channel has no valid
745
+ // components. notifyErrorAndPruneMissingComponents will splice the
746
+ // clientId out, leaving the array empty, then closeIfChannelHasNoComponents
747
+ // detects this and closes the socket.
748
+ delete this.pushImpl.components["clientId_close_test"];
749
+
750
+ const closeSpy = sinon.spy(this.fakeWebsocket, "close");
751
+ try {
752
+ // Abnormal close (1006) is reconnectable — goes through the
753
+ // notifyErrorAndPruneMissingComponents → closeIfChannelHasNoComponents path.
754
+ this.fakeWebsocket._close({code: 1006});
755
+
756
+ expect(this.pushImpl.clientIdsByTokens[channelToken].length,
757
+ "clientIds array must be empty after stale component pruning").to.eq(0);
758
+ expect(closeSpy.called || this.fakeWebsocket.readyState === 3,
759
+ "socket must be closed when channel has no remaining components").to.be.true;
760
+ } finally {
761
+ closeSpy.restore();
762
+ }
763
+ });
764
+ });