@cratis/arc 22.0.2 → 22.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/dist/cjs/queries/ObservableQueryFor.js +6 -1
  2. package/dist/cjs/queries/ObservableQueryFor.js.map +1 -1
  3. package/dist/cjs/queries/QueryInstanceCache.js +6 -6
  4. package/dist/cjs/queries/QueryInstanceCache.js.map +1 -1
  5. package/dist/cjs/queries/QueryResult.js +23 -4
  6. package/dist/cjs/queries/QueryResult.js.map +1 -1
  7. package/dist/cjs/queries/QueryResultWithState.js +20 -7
  8. package/dist/cjs/queries/QueryResultWithState.js.map +1 -1
  9. package/dist/cjs/queries/ServerSentEventHubConnection.js +120 -58
  10. package/dist/cjs/queries/ServerSentEventHubConnection.js.map +1 -1
  11. package/dist/cjs/queries/WebSocketHubConnection.js +121 -51
  12. package/dist/cjs/queries/WebSocketHubConnection.js.map +1 -1
  13. package/dist/esm/queries/IQueryResult.d.ts +1 -0
  14. package/dist/esm/queries/IQueryResult.d.ts.map +1 -1
  15. package/dist/esm/queries/ObservableQueryFor.d.ts.map +1 -1
  16. package/dist/esm/queries/ObservableQueryFor.js +6 -1
  17. package/dist/esm/queries/ObservableQueryFor.js.map +1 -1
  18. package/dist/esm/queries/QueryInstanceCache.d.ts +1 -1
  19. package/dist/esm/queries/QueryInstanceCache.d.ts.map +1 -1
  20. package/dist/esm/queries/QueryInstanceCache.js +6 -6
  21. package/dist/esm/queries/QueryInstanceCache.js.map +1 -1
  22. package/dist/esm/queries/QueryResult.d.ts +2 -0
  23. package/dist/esm/queries/QueryResult.d.ts.map +1 -1
  24. package/dist/esm/queries/QueryResult.js +23 -4
  25. package/dist/esm/queries/QueryResult.js.map +1 -1
  26. package/dist/esm/queries/QueryResultWithState.d.ts +3 -3
  27. package/dist/esm/queries/QueryResultWithState.d.ts.map +1 -1
  28. package/dist/esm/queries/QueryResultWithState.js +20 -7
  29. package/dist/esm/queries/QueryResultWithState.js.map +1 -1
  30. package/dist/esm/queries/ServerSentEventHubConnection.d.ts +11 -4
  31. package/dist/esm/queries/ServerSentEventHubConnection.d.ts.map +1 -1
  32. package/dist/esm/queries/ServerSentEventHubConnection.js +120 -58
  33. package/dist/esm/queries/ServerSentEventHubConnection.js.map +1 -1
  34. package/dist/esm/queries/WebSocketHubConnection.d.ts +13 -2
  35. package/dist/esm/queries/WebSocketHubConnection.d.ts.map +1 -1
  36. package/dist/esm/queries/WebSocketHubConnection.js +121 -51
  37. package/dist/esm/queries/WebSocketHubConnection.js.map +1 -1
  38. package/dist/esm/queries/for_ObservableQueryFor/when_performing/with_a_not_ready_result.d.ts +2 -0
  39. package/dist/esm/queries/for_ObservableQueryFor/when_performing/with_a_not_ready_result.d.ts.map +1 -0
  40. package/dist/esm/queries/for_ObservableQueryFor/when_performing/with_a_not_ready_result.js +34 -0
  41. package/dist/esm/queries/for_ObservableQueryFor/when_performing/with_a_not_ready_result.js.map +1 -0
  42. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_direct_mode_and_sse_transport.js +26 -2
  43. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_direct_mode_and_sse_transport.js.map +1 -1
  44. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_direct_mode_disabled_and_sse_transport.js +60 -3
  45. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_direct_mode_disabled_and_sse_transport.js.map +1 -1
  46. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_web_socket_hub_payload_without_readiness.d.ts +2 -0
  47. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_web_socket_hub_payload_without_readiness.d.ts.map +1 -0
  48. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_web_socket_hub_payload_without_readiness.js +83 -0
  49. package/dist/esm/queries/for_ObservableQueryFor/when_subscribing/with_web_socket_hub_payload_without_readiness.js.map +1 -0
  50. package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_only_readiness_changed.d.ts +2 -0
  51. package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_only_readiness_changed.d.ts.map +1 -0
  52. package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_only_readiness_changed.js +22 -0
  53. package/dist/esm/queries/for_QueryInstanceCache/when_setting_last_result/with_only_readiness_changed.js.map +1 -0
  54. package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/with_readiness_false.d.ts +2 -0
  55. package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/with_readiness_false.d.ts.map +1 -0
  56. package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/with_readiness_false.js +17 -0
  57. package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/with_readiness_false.js.map +1 -0
  58. package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/without_readiness.d.ts +2 -0
  59. package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/without_readiness.d.ts.map +1 -0
  60. package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/without_readiness.js +16 -0
  61. package/dist/esm/queries/for_QueryResult/when_constructing_from_a_server_result/without_readiness.js.map +1 -0
  62. package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/with_readiness_false.d.ts +2 -0
  63. package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/with_readiness_false.d.ts.map +1 -0
  64. package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/with_readiness_false.js +19 -0
  65. package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/with_readiness_false.js.map +1 -0
  66. package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/without_readiness.d.ts +2 -0
  67. package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/without_readiness.d.ts.map +1 -0
  68. package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/without_readiness.js +19 -0
  69. package/dist/esm/queries/for_QueryResultWithState/when_creating_from_query_result/without_readiness.js.map +1 -0
  70. package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_deferred_promise.d.ts +7 -0
  71. package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_deferred_promise.d.ts.map +1 -0
  72. package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_deferred_promise.js +12 -0
  73. package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_deferred_promise.js.map +1 -0
  74. package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_server_sent_event_hub_connection.d.ts +2 -1
  75. package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_server_sent_event_hub_connection.d.ts.map +1 -1
  76. package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_server_sent_event_hub_connection.js +15 -4
  77. package/dist/esm/queries/for_ServerSentEventHubConnection/given/a_server_sent_event_hub_connection.js.map +1 -1
  78. package/dist/esm/queries/for_ServerSentEventHubConnection/when_a_retired_event_source_fires/ignores_connected_and_error_callbacks.d.ts +2 -0
  79. package/dist/esm/queries/for_ServerSentEventHubConnection/when_a_retired_event_source_fires/ignores_connected_and_error_callbacks.d.ts.map +1 -0
  80. package/dist/esm/queries/for_ServerSentEventHubConnection/when_a_retired_event_source_fires/ignores_connected_and_error_callbacks.js +44 -0
  81. package/dist/esm/queries/for_ServerSentEventHubConnection/when_a_retired_event_source_fires/ignores_connected_and_error_callbacks.js.map +1 -0
  82. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_replaced.d.ts +2 -0
  83. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_replaced.d.ts.map +1 -0
  84. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_replaced.js +74 -0
  85. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_replaced.js.map +1 -0
  86. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_unsubscribed.d.ts +2 -0
  87. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_unsubscribed.d.ts.map +1 -0
  88. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_unsubscribed.js +74 -0
  89. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_unsubscribed.js.map +1 -0
  90. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_is_rejected.d.ts +2 -0
  91. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_is_rejected.d.ts.map +1 -0
  92. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_is_rejected.js +59 -0
  93. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_is_rejected.js.map +1 -0
  94. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_returns_non_ok.d.ts +2 -0
  95. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_returns_non_ok.d.ts.map +1 -0
  96. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_returns_non_ok.js +58 -0
  97. package/dist/esm/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_returns_non_ok.js.map +1 -0
  98. package/dist/esm/queries/for_ServerSentEventHubConnection/when_disposing/cleans_up_resources.js +6 -3
  99. package/dist/esm/queries/for_ServerSentEventHubConnection/when_disposing/cleans_up_resources.js.map +1 -1
  100. package/dist/esm/queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.js +23 -6
  101. package/dist/esm/queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.js.map +1 -1
  102. package/dist/esm/queries/for_ServerSentEventHubConnection/when_reconnecting/after_error.js +20 -5
  103. package/dist/esm/queries/for_ServerSentEventHubConnection/when_reconnecting/after_error.js.map +1 -1
  104. package/dist/esm/queries/for_ServerSentEventHubConnection/when_reconnecting/and_an_immediate_open_wins_the_backoff_race.d.ts +2 -0
  105. package/dist/esm/queries/for_ServerSentEventHubConnection/when_reconnecting/and_an_immediate_open_wins_the_backoff_race.d.ts.map +1 -0
  106. package/dist/esm/queries/for_ServerSentEventHubConnection/when_reconnecting/and_an_immediate_open_wins_the_backoff_race.js +20 -0
  107. package/dist/esm/queries/for_ServerSentEventHubConnection/when_reconnecting/and_an_immediate_open_wins_the_backoff_race.js.map +1 -0
  108. package/dist/esm/queries/for_ServerSentEventHubConnection/when_replacing_a_subscription/ignores_messages_from_the_retired_generation.d.ts +2 -0
  109. package/dist/esm/queries/for_ServerSentEventHubConnection/when_replacing_a_subscription/ignores_messages_from_the_retired_generation.d.ts.map +1 -0
  110. package/dist/esm/queries/for_ServerSentEventHubConnection/when_replacing_a_subscription/ignores_messages_from_the_retired_generation.js +68 -0
  111. package/dist/esm/queries/for_ServerSentEventHubConnection/when_replacing_a_subscription/ignores_messages_from_the_retired_generation.js.map +1 -0
  112. package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscribing/sends_subscribe_post.js +38 -13
  113. package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscribing/sends_subscribe_post.js.map +1 -1
  114. package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscription_revisions_are_not_advertised/uses_legacy_protocol.d.ts +2 -0
  115. package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscription_revisions_are_not_advertised/uses_legacy_protocol.d.ts.map +1 -0
  116. package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscription_revisions_are_not_advertised/uses_legacy_protocol.js +54 -0
  117. package/dist/esm/queries/for_ServerSentEventHubConnection/when_subscription_revisions_are_not_advertised/uses_legacy_protocol.js.map +1 -0
  118. package/dist/esm/queries/for_ServerSentEventHubConnection/when_unsubscribing/the_only_query.js +18 -4
  119. package/dist/esm/queries/for_ServerSentEventHubConnection/when_unsubscribing/the_only_query.js.map +1 -1
  120. package/dist/esm/queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.js +22 -5
  121. package/dist/esm/queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.js.map +1 -1
  122. package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/ignores_a_pending_reconnect_and_stale_socket_callbacks.d.ts +2 -0
  123. package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/ignores_a_pending_reconnect_and_stale_socket_callbacks.d.ts.map +1 -0
  124. package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/ignores_a_pending_reconnect_and_stale_socket_callbacks.js +108 -0
  125. package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/ignores_a_pending_reconnect_and_stale_socket_callbacks.js.map +1 -0
  126. package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/replaces_a_closing_socket_safely.d.ts +2 -0
  127. package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/replaces_a_closing_socket_safely.d.ts.map +1 -0
  128. package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/replaces_a_closing_socket_safely.js +33 -0
  129. package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/replaces_a_closing_socket_safely.js.map +1 -0
  130. package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/resubscribes_all_queries.js +26 -4
  131. package/dist/esm/queries/for_WebSocketHubConnection/when_reconnecting/resubscribes_all_queries.js.map +1 -1
  132. package/dist/esm/queries/for_WebSocketHubConnection/when_replacing_a_subscription/ignores_stale_result_unauthorized_and_error.d.ts +2 -0
  133. package/dist/esm/queries/for_WebSocketHubConnection/when_replacing_a_subscription/ignores_stale_result_unauthorized_and_error.d.ts.map +1 -0
  134. package/dist/esm/queries/for_WebSocketHubConnection/when_replacing_a_subscription/ignores_stale_result_unauthorized_and_error.js +62 -0
  135. package/dist/esm/queries/for_WebSocketHubConnection/when_replacing_a_subscription/ignores_stale_result_unauthorized_and_error.js.map +1 -0
  136. package/dist/esm/queries/for_WebSocketHubConnection/when_subscribing/to_a_query.js +18 -5
  137. package/dist/esm/queries/for_WebSocketHubConnection/when_subscribing/to_a_query.js.map +1 -1
  138. package/dist/esm/queries/for_WebSocketHubConnection/when_subscription_revisions_are_supported/upgrades_active_subscriptions_to_strict_mode.d.ts +2 -0
  139. package/dist/esm/queries/for_WebSocketHubConnection/when_subscription_revisions_are_supported/upgrades_active_subscriptions_to_strict_mode.d.ts.map +1 -0
  140. package/dist/esm/queries/for_WebSocketHubConnection/when_subscription_revisions_are_supported/upgrades_active_subscriptions_to_strict_mode.js +56 -0
  141. package/dist/esm/queries/for_WebSocketHubConnection/when_subscription_revisions_are_supported/upgrades_active_subscriptions_to_strict_mode.js.map +1 -0
  142. package/dist/esm/queries/for_WebSocketHubConnection/when_unsubscribing/the_only_query.js +16 -3
  143. package/dist/esm/queries/for_WebSocketHubConnection/when_unsubscribing/the_only_query.js.map +1 -1
  144. package/dist/esm/queries/for_WebSocketHubConnection/when_unsubscribing/with_revision_support_not_advertised.d.ts +2 -0
  145. package/dist/esm/queries/for_WebSocketHubConnection/when_unsubscribing/with_revision_support_not_advertised.d.ts.map +1 -0
  146. package/dist/esm/queries/for_WebSocketHubConnection/when_unsubscribing/with_revision_support_not_advertised.js +33 -0
  147. package/dist/esm/queries/for_WebSocketHubConnection/when_unsubscribing/with_revision_support_not_advertised.js.map +1 -0
  148. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  149. package/package.json +1 -1
  150. package/queries/IQueryResult.ts +10 -0
  151. package/queries/ObservableQueryFor.ts +44 -16
  152. package/queries/QueryInstanceCache.ts +42 -19
  153. package/queries/QueryResult.ts +145 -79
  154. package/queries/QueryResultWithState.ts +32 -9
  155. package/queries/ServerSentEventHubConnection.ts +270 -83
  156. package/queries/WebSocketHubConnection.ts +188 -56
  157. package/queries/for_ObservableQueryFor/when_performing/with_a_not_ready_result.ts +46 -0
  158. package/queries/for_ObservableQueryFor/when_subscribing/with_direct_mode_and_sse_transport.ts +91 -57
  159. package/queries/for_ObservableQueryFor/when_subscribing/with_direct_mode_disabled_and_sse_transport.ts +125 -53
  160. package/queries/for_ObservableQueryFor/when_subscribing/with_web_socket_hub_payload_without_readiness.ts +107 -0
  161. package/queries/for_QueryInstanceCache/when_setting_last_result/with_only_readiness_changed.ts +63 -0
  162. package/queries/for_QueryResult/when_constructing_from_a_server_result/with_readiness_false.ts +25 -0
  163. package/queries/for_QueryResult/when_constructing_from_a_server_result/without_readiness.ts +24 -0
  164. package/queries/for_QueryResultWithState/when_creating_from_query_result/with_readiness_false.ts +28 -0
  165. package/queries/for_QueryResultWithState/when_creating_from_query_result/without_readiness.ts +25 -0
  166. package/queries/for_ServerSentEventHubConnection/given/a_deferred_promise.ts +15 -0
  167. package/queries/for_ServerSentEventHubConnection/given/a_server_sent_event_hub_connection.ts +18 -7
  168. package/queries/for_ServerSentEventHubConnection/when_a_retired_event_source_fires/ignores_connected_and_error_callbacks.ts +59 -0
  169. package/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_replaced.ts +113 -0
  170. package/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_query_is_unsubscribed.ts +109 -0
  171. package/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_is_rejected.ts +81 -0
  172. package/queries/for_ServerSentEventHubConnection/when_connection_changes_while_subscribe_is_in_flight/and_the_stale_request_returns_non_ok.ts +83 -0
  173. package/queries/for_ServerSentEventHubConnection/when_disposing/cleans_up_resources.ts +30 -21
  174. package/queries/for_ServerSentEventHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.ts +56 -32
  175. package/queries/for_ServerSentEventHubConnection/when_reconnecting/after_error.ts +23 -6
  176. package/queries/for_ServerSentEventHubConnection/when_reconnecting/and_an_immediate_open_wins_the_backoff_race.ts +41 -0
  177. package/queries/for_ServerSentEventHubConnection/when_replacing_a_subscription/ignores_messages_from_the_retired_generation.ts +92 -0
  178. package/queries/for_ServerSentEventHubConnection/when_subscribing/sends_subscribe_post.ts +69 -30
  179. package/queries/for_ServerSentEventHubConnection/when_subscription_revisions_are_not_advertised/uses_legacy_protocol.ts +69 -0
  180. package/queries/for_ServerSentEventHubConnection/when_unsubscribing/the_only_query.ts +43 -24
  181. package/queries/for_WebSocketHubConnection/when_receiving_unauthorized/notifies_subscriber_and_removes_subscription.ts +53 -29
  182. package/queries/for_WebSocketHubConnection/when_reconnecting/ignores_a_pending_reconnect_and_stale_socket_callbacks.ts +131 -0
  183. package/queries/for_WebSocketHubConnection/when_reconnecting/replaces_a_closing_socket_safely.ts +39 -0
  184. package/queries/for_WebSocketHubConnection/when_reconnecting/resubscribes_all_queries.ts +72 -36
  185. package/queries/for_WebSocketHubConnection/when_replacing_a_subscription/ignores_stale_result_unauthorized_and_error.ts +88 -0
  186. package/queries/for_WebSocketHubConnection/when_subscribing/to_a_query.ts +54 -27
  187. package/queries/for_WebSocketHubConnection/when_subscription_revisions_are_supported/upgrades_active_subscriptions_to_strict_mode.ts +72 -0
  188. package/queries/for_WebSocketHubConnection/when_unsubscribing/the_only_query.ts +43 -18
  189. package/queries/for_WebSocketHubConnection/when_unsubscribing/with_revision_support_not_advertised.ts +44 -0
@@ -0,0 +1,113 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import sinon from 'sinon';
5
+ import { a_deferred_promise } from '../given/a_deferred_promise';
6
+ import { a_server_sent_event_hub_connection } from '../given/a_server_sent_event_hub_connection';
7
+ import { given } from '../../../given';
8
+ import { HubMessageType } from '../../WebSocketHubConnection';
9
+
10
+ describe(
11
+ 'when a query is replaced while its subscribe request is in flight and the connection changes',
12
+ given(a_server_sent_event_hub_connection, (context) => {
13
+ const queryId = 'q1';
14
+ const replacementRequest = { queryName: 'ReplacementQuery' };
15
+ let clock: sinon.SinonFakeTimers;
16
+ let originalCallback: sinon.SinonStub;
17
+ let replacementCallback: sinon.SinonStub;
18
+
19
+ beforeEach(async () => {
20
+ context.setup();
21
+ clock = sinon.useFakeTimers({ toFake: ['setTimeout'] });
22
+ sinon.stub(console, 'warn');
23
+ const firstSubscribe = new a_deferred_promise<{
24
+ ok: boolean;
25
+ status: number;
26
+ }>();
27
+ context.fetchStub.onFirstCall().returns(firstSubscribe.promise);
28
+ originalCallback = sinon.stub();
29
+ replacementCallback = sinon.stub();
30
+
31
+ context.connection.subscribe(
32
+ queryId,
33
+ { queryName: 'OriginalQuery' },
34
+ originalCallback,
35
+ );
36
+ context.simulateOpen();
37
+ context.simulateMessage({
38
+ type: HubMessageType.Connected,
39
+ payload: 'connection-a',
40
+ supportsSubscriptionRevisions: true,
41
+ });
42
+ context.connection.subscribe(
43
+ queryId,
44
+ replacementRequest,
45
+ replacementCallback,
46
+ );
47
+ context.simulateMessage({
48
+ type: HubMessageType.Connected,
49
+ payload: 'connection-b',
50
+ supportsSubscriptionRevisions: true,
51
+ });
52
+
53
+ firstSubscribe.resolve({ ok: false, status: 404 });
54
+ await Promise.resolve();
55
+ clock.tick(1000);
56
+ await Promise.resolve();
57
+ context.simulateMessage({
58
+ type: HubMessageType.QueryResult,
59
+ queryId,
60
+ revision: getSubscribeBody(2).revision,
61
+ payload: { isSuccess: true },
62
+ });
63
+ });
64
+
65
+ afterEach(() => {
66
+ clock.restore();
67
+ sinon.restore();
68
+ });
69
+
70
+ it('should send only the replacement on connection B', () => {
71
+ const body = getSubscribeBody(2);
72
+ body.connectionId.should.equal('connection-b');
73
+ body.queryId.should.equal(queryId);
74
+ body.request.should.deep.equal(replacementRequest);
75
+ body.revision.should.be.greaterThan(0);
76
+ });
77
+
78
+ it('should not retry the obsolete subscription', () =>
79
+ context.fetchStub.callCount.should.equal(3));
80
+
81
+ it('should notify only the replacement callback', () => {
82
+ originalCallback.called.should.equal(false);
83
+ replacementCallback.calledOnce.should.equal(true);
84
+ });
85
+
86
+ it('should not reconnect', () =>
87
+ (context.policy.schedule as sinon.SinonStub).called.should.be.false);
88
+
89
+ it('should retain one active subscription', () =>
90
+ context.connection.queryCount.should.equal(1));
91
+
92
+ function getSubscribeBody(callIndex: number): {
93
+ connectionId: string;
94
+ queryId: string;
95
+ request: object;
96
+ revision: number;
97
+ } {
98
+ const rawBody = context.fetchStub.getCall(callIndex).args[1].body as string;
99
+ try {
100
+ return JSON.parse(rawBody) as {
101
+ connectionId: string;
102
+ queryId: string;
103
+ request: object;
104
+ revision: number;
105
+ };
106
+ } catch (error) {
107
+ throw new Error('Expected a valid subscribe request body', {
108
+ cause: error,
109
+ });
110
+ }
111
+ }
112
+ }),
113
+ );
@@ -0,0 +1,109 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import sinon from 'sinon';
5
+ import { a_deferred_promise } from '../given/a_deferred_promise';
6
+ import { a_server_sent_event_hub_connection } from '../given/a_server_sent_event_hub_connection';
7
+ import { given } from '../../../given';
8
+ import { HubMessageType } from '../../WebSocketHubConnection';
9
+
10
+ const subscribeUrl = 'http://localhost/.cratis/queries/sse/subscribe';
11
+
12
+ describe(
13
+ 'when a query is unsubscribed while its subscribe request is in flight and the connection changes',
14
+ given(a_server_sent_event_hub_connection, (context) => {
15
+ let clock: sinon.SinonFakeTimers;
16
+
17
+ beforeEach(async () => {
18
+ context.setup();
19
+ clock = sinon.useFakeTimers({ toFake: ['setTimeout'] });
20
+ sinon.stub(console, 'warn');
21
+ const firstSubscribe = new a_deferred_promise<{
22
+ ok: boolean;
23
+ status: number;
24
+ }>();
25
+ context.fetchStub.onFirstCall().returns(firstSubscribe.promise);
26
+
27
+ context.connection.subscribe(
28
+ 'removed-query',
29
+ { queryName: 'RemovedQuery' },
30
+ sinon.stub(),
31
+ );
32
+ context.simulateOpen();
33
+ context.simulateMessage({
34
+ type: HubMessageType.Connected,
35
+ payload: 'connection-a',
36
+ supportsSubscriptionRevisions: true,
37
+ });
38
+ context.connection.subscribe(
39
+ 'active-query',
40
+ { queryName: 'ActiveQuery' },
41
+ sinon.stub(),
42
+ );
43
+ context.connection.unsubscribe('removed-query');
44
+ context.simulateMessage({
45
+ type: HubMessageType.Connected,
46
+ payload: 'connection-b',
47
+ supportsSubscriptionRevisions: true,
48
+ });
49
+
50
+ firstSubscribe.resolve({ ok: false, status: 404 });
51
+ await Promise.resolve();
52
+ clock.tick(1000);
53
+ await Promise.resolve();
54
+ });
55
+
56
+ afterEach(() => {
57
+ clock.restore();
58
+ sinon.restore();
59
+ });
60
+
61
+ it('should not subscribe the removed query on connection B', () => {
62
+ const removedQueryCalls = context.fetchStub
63
+ .getCalls()
64
+ .filter((call) => call.args[0] === subscribeUrl)
65
+ .filter((call) =>
66
+ (call.args[1].body as string).includes('"queryId":"removed-query"'),
67
+ );
68
+ removedQueryCalls.length.should.equal(1);
69
+ const body = parseBody(removedQueryCalls[0].args[1].body as string);
70
+ body.connectionId.should.equal('connection-a');
71
+ body.queryId.should.equal('removed-query');
72
+ body.request.should.deep.equal({ queryName: 'RemovedQuery' });
73
+ body.revision.should.be.greaterThan(0);
74
+ });
75
+
76
+ it('should subscribe the remaining query on connection B', () => {
77
+ const activeQueryBodies = context.fetchStub
78
+ .getCalls()
79
+ .filter((call) => call.args[0] === subscribeUrl)
80
+ .map((call) => parseBody(call.args[1].body as string))
81
+ .filter((body) => body.queryId === 'active-query');
82
+ activeQueryBodies
83
+ .map((body) => body.connectionId)
84
+ .should.deep.equal(['connection-a', 'connection-b']);
85
+ activeQueryBodies[0].revision.should.equal(activeQueryBodies[1].revision);
86
+ });
87
+
88
+ it('should not reconnect', () =>
89
+ (context.policy.schedule as sinon.SinonStub).called.should.be.false);
90
+
91
+ it('should retain only the remaining subscription', () =>
92
+ context.connection.queryCount.should.equal(1));
93
+
94
+ function parseBody(rawBody: string): {
95
+ connectionId: string;
96
+ queryId: string;
97
+ request: { queryName: string };
98
+ revision: number;
99
+ } {
100
+ try {
101
+ return JSON.parse(rawBody) as ReturnType<typeof parseBody>;
102
+ } catch (error) {
103
+ throw new Error('Expected a valid subscribe request body', {
104
+ cause: error,
105
+ });
106
+ }
107
+ }
108
+ }),
109
+ );
@@ -0,0 +1,81 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import sinon from 'sinon';
5
+ import { a_deferred_promise } from '../given/a_deferred_promise';
6
+ import { a_server_sent_event_hub_connection } from '../given/a_server_sent_event_hub_connection';
7
+ import { given } from '../../../given';
8
+ import { HubMessageType } from '../../WebSocketHubConnection';
9
+
10
+ describe(
11
+ 'when the connection changes while a subscribe request is in flight and the stale request is rejected',
12
+ given(a_server_sent_event_hub_connection, (context) => {
13
+ const queryId = 'q1';
14
+ const request = { queryName: 'MyQuery' };
15
+ let clock: sinon.SinonFakeTimers;
16
+
17
+ beforeEach(async () => {
18
+ context.setup();
19
+ clock = sinon.useFakeTimers({ toFake: ['setTimeout'] });
20
+ sinon.stub(console, 'warn');
21
+ const firstSubscribe = new a_deferred_promise<{ ok: boolean }>();
22
+ context.fetchStub.onFirstCall().returns(firstSubscribe.promise);
23
+
24
+ context.connection.subscribe(queryId, request, sinon.stub());
25
+ context.simulateOpen();
26
+ context.simulateMessage({
27
+ type: HubMessageType.Connected,
28
+ payload: 'connection-a',
29
+ supportsSubscriptionRevisions: true,
30
+ });
31
+ context.simulateMessage({
32
+ type: HubMessageType.Connected,
33
+ payload: 'connection-b',
34
+ supportsSubscriptionRevisions: true,
35
+ });
36
+
37
+ firstSubscribe.reject(new Error('Connection A failed'));
38
+ await Promise.resolve();
39
+ await Promise.resolve();
40
+ clock.tick(1000);
41
+ await Promise.resolve();
42
+ });
43
+
44
+ afterEach(() => {
45
+ clock.restore();
46
+ sinon.restore();
47
+ });
48
+
49
+ it('should send the active subscription on connection B', () => {
50
+ const body = parseBody(context.fetchStub.getCall(1).args[1].body as string);
51
+ body.connectionId.should.equal('connection-b');
52
+ body.queryId.should.equal(queryId);
53
+ body.request.should.deep.equal(request);
54
+ body.revision.should.be.greaterThan(0);
55
+ });
56
+
57
+ it('should not retry the obsolete connection A request', () =>
58
+ context.fetchStub.callCount.should.equal(2));
59
+
60
+ it('should not reconnect', () =>
61
+ (context.policy.schedule as sinon.SinonStub).called.should.be.false);
62
+
63
+ it('should retain the active subscription', () =>
64
+ context.connection.queryCount.should.equal(1));
65
+
66
+ function parseBody(rawBody: string): {
67
+ connectionId: string;
68
+ queryId: string;
69
+ request: object;
70
+ revision: number;
71
+ } {
72
+ try {
73
+ return JSON.parse(rawBody) as ReturnType<typeof parseBody>;
74
+ } catch (error) {
75
+ throw new Error('Expected a valid subscribe request body', {
76
+ cause: error,
77
+ });
78
+ }
79
+ }
80
+ }),
81
+ );
@@ -0,0 +1,83 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import sinon from 'sinon';
5
+ import { a_deferred_promise } from '../given/a_deferred_promise';
6
+ import { a_server_sent_event_hub_connection } from '../given/a_server_sent_event_hub_connection';
7
+ import { given } from '../../../given';
8
+ import { HubMessageType } from '../../WebSocketHubConnection';
9
+
10
+ describe(
11
+ 'when the connection changes while a subscribe request is in flight and the stale request returns non-OK',
12
+ given(a_server_sent_event_hub_connection, (context) => {
13
+ const queryId = 'q1';
14
+ const request = { queryName: 'MyQuery' };
15
+ let clock: sinon.SinonFakeTimers;
16
+
17
+ beforeEach(async () => {
18
+ context.setup();
19
+ clock = sinon.useFakeTimers({ toFake: ['setTimeout'] });
20
+ sinon.stub(console, 'warn');
21
+ const firstSubscribe = new a_deferred_promise<{
22
+ ok: boolean;
23
+ status: number;
24
+ }>();
25
+ context.fetchStub.onFirstCall().returns(firstSubscribe.promise);
26
+
27
+ context.connection.subscribe(queryId, request, sinon.stub());
28
+ context.simulateOpen();
29
+ context.simulateMessage({
30
+ type: HubMessageType.Connected,
31
+ payload: 'connection-a',
32
+ supportsSubscriptionRevisions: true,
33
+ });
34
+ context.simulateMessage({
35
+ type: HubMessageType.Connected,
36
+ payload: 'connection-b',
37
+ supportsSubscriptionRevisions: true,
38
+ });
39
+
40
+ firstSubscribe.resolve({ ok: false, status: 404 });
41
+ await Promise.resolve();
42
+ clock.tick(1000);
43
+ await Promise.resolve();
44
+ });
45
+
46
+ afterEach(() => {
47
+ clock.restore();
48
+ sinon.restore();
49
+ });
50
+
51
+ it('should send the active subscription on connection B', () => {
52
+ const body = parseBody(context.fetchStub.getCall(1).args[1].body as string);
53
+ body.connectionId.should.equal('connection-b');
54
+ body.queryId.should.equal(queryId);
55
+ body.request.should.deep.equal(request);
56
+ body.revision.should.be.greaterThan(0);
57
+ });
58
+
59
+ it('should not retry the obsolete connection A request', () =>
60
+ context.fetchStub.callCount.should.equal(2));
61
+
62
+ it('should not reconnect', () =>
63
+ (context.policy.schedule as sinon.SinonStub).called.should.be.false);
64
+
65
+ it('should retain the active subscription', () =>
66
+ context.connection.queryCount.should.equal(1));
67
+
68
+ function parseBody(rawBody: string): {
69
+ connectionId: string;
70
+ queryId: string;
71
+ request: object;
72
+ revision: number;
73
+ } {
74
+ try {
75
+ return JSON.parse(rawBody) as ReturnType<typeof parseBody>;
76
+ } catch (error) {
77
+ throw new Error('Expected a valid subscribe request body', {
78
+ cause: error,
79
+ });
80
+ }
81
+ }
82
+ }),
83
+ );
@@ -6,29 +6,38 @@ import { a_server_sent_event_hub_connection } from '../given/a_server_sent_event
6
6
  import { given } from '../../../given';
7
7
  import { HubMessageType } from '../../WebSocketHubConnection';
8
8
 
9
- describe('when disposing the hub connection', given(a_server_sent_event_hub_connection, context => {
10
- beforeEach(() => {
11
- context.setup();
12
- context.connection.subscribe('q1', { queryName: 'MyQuery' }, sinon.stub());
13
- context.simulateOpen();
14
- context.simulateMessage({ type: HubMessageType.Connected, payload: 'conn-1' });
15
- context.connection.dispose();
16
- });
9
+ describe(
10
+ 'when disposing the hub connection',
11
+ given(a_server_sent_event_hub_connection, (context) => {
12
+ beforeEach(() => {
13
+ context.setup();
14
+ context.connection.subscribe('q1', { queryName: 'MyQuery' }, sinon.stub());
15
+ context.simulateOpen();
16
+ context.simulateMessage({
17
+ type: HubMessageType.Connected,
18
+ payload: 'conn-1',
19
+ });
20
+ context.connection.dispose();
21
+ });
17
22
 
18
- afterEach(() => sinon.restore());
23
+ afterEach(() => sinon.restore());
19
24
 
20
- it('should close the EventSource', () => context.fakeEventSource.close.calledOnce.should.be.true);
21
- it('should cancel the reconnect policy', () => (context.policy.cancel as sinon.SinonStub).calledOnce.should.be.true);
22
- it('should report zero active subscriptions', () => context.connection.queryCount.should.equal(0));
25
+ it('should close the EventSource', () =>
26
+ context.fakeEventSource.close.calledOnce.should.be.true);
27
+ it('should cancel the reconnect policy', () =>
28
+ (context.policy.cancel as sinon.SinonStub).called.should.equal(true));
29
+ it('should report zero active subscriptions', () =>
30
+ context.connection.queryCount.should.equal(0));
23
31
 
24
- describe('when an error event fires after dispose', () => {
25
- beforeEach(() => {
26
- (context.policy.schedule as sinon.SinonStub).reset();
27
- context.simulateError();
28
- });
32
+ describe('when an error event fires after dispose', () => {
33
+ beforeEach(() => {
34
+ (context.policy.schedule as sinon.SinonStub).reset();
35
+ context.simulateError();
36
+ });
29
37
 
30
- it('should not schedule a reconnect', () => {
31
- (context.policy.schedule as sinon.SinonStub).callCount.should.equal(0);
38
+ it('should not schedule a reconnect', () => {
39
+ (context.policy.schedule as sinon.SinonStub).callCount.should.equal(0);
40
+ });
32
41
  });
33
- });
34
- }));
42
+ }),
43
+ );
@@ -7,45 +7,69 @@ import { given } from '../../../given';
7
7
  import { HubMessageType } from '../../WebSocketHubConnection';
8
8
  import { QueryResult } from '../../QueryResult';
9
9
 
10
- describe('when receiving unauthorized for a subscribed query', given(a_server_sent_event_hub_connection, context => {
11
- let callback: sinon.SinonStub;
12
- let receivedResult: QueryResult<unknown> | undefined;
13
- const queryId = 'q-auth-1';
14
- const connectionId = 'conn-123';
10
+ describe(
11
+ 'when receiving unauthorized for a subscribed query',
12
+ given(a_server_sent_event_hub_connection, (context) => {
13
+ let callback: sinon.SinonStub;
14
+ let receivedResult: QueryResult<unknown> | undefined;
15
+ const queryId = 'q-auth-1';
16
+ const connectionId = 'conn-123';
15
17
 
16
- beforeEach(() => {
17
- context.setup();
18
- callback = sinon.stub();
18
+ beforeEach(() => {
19
+ context.setup();
20
+ callback = sinon.stub();
19
21
 
20
- context.connection.subscribe(queryId, { queryName: 'SecureQuery' }, callback);
21
- context.simulateOpen();
22
+ context.connection.subscribe(queryId, { queryName: 'SecureQuery' }, callback);
23
+ context.simulateOpen();
22
24
 
23
- // Server sends Connected message with the connection ID.
24
- context.simulateMessage({ type: HubMessageType.Connected, payload: connectionId });
25
+ // Server sends Connected message with the connection ID.
26
+ context.simulateMessage({
27
+ type: HubMessageType.Connected,
28
+ payload: connectionId,
29
+ supportsSubscriptionRevisions: true,
30
+ });
31
+ const body = getSubscribeBody();
25
32
 
26
- // Server replies with Unauthorized for this subscription.
27
- context.simulateMessage({ type: HubMessageType.Unauthorized, queryId });
33
+ // Server replies with Unauthorized for this exact subscription.
34
+ context.simulateMessage({
35
+ type: HubMessageType.Unauthorized,
36
+ queryId,
37
+ revision: body.revision,
38
+ });
28
39
 
29
- receivedResult = callback.firstCall?.args[0] as QueryResult<unknown> | undefined;
30
- });
40
+ receivedResult = callback.firstCall?.args[0] as
41
+ | QueryResult<unknown>
42
+ | undefined;
43
+ });
31
44
 
32
- afterEach(() => {
33
- sinon.restore();
34
- });
45
+ afterEach(() => {
46
+ sinon.restore();
47
+ });
35
48
 
36
- it('should invoke the subscriber callback', () => {
37
- callback.calledOnce.should.be.true;
38
- });
49
+ function getSubscribeBody(): { revision: number } {
50
+ try {
51
+ return JSON.parse(context.fetchStub.firstCall.args[1].body as string) as {
52
+ revision: number;
53
+ };
54
+ } catch (error) {
55
+ throw new Error('Expected a valid subscribe body', { cause: error });
56
+ }
57
+ }
39
58
 
40
- it('should report isAuthorized as false', () => {
41
- receivedResult!.isAuthorized.should.be.false;
42
- });
59
+ it('should invoke the subscriber callback', () => {
60
+ callback.calledOnce.should.equal(true);
61
+ });
43
62
 
44
- it('should report isSuccess as false', () => {
45
- receivedResult!.isSuccess.should.be.false;
46
- });
63
+ it('should report isAuthorized as false', () => {
64
+ receivedResult!.isAuthorized.should.equal(false);
65
+ });
47
66
 
48
- it('should remove the subscription', () => {
49
- context.connection.queryCount.should.equal(0);
50
- });
51
- }));
67
+ it('should report isSuccess as false', () => {
68
+ receivedResult!.isSuccess.should.equal(false);
69
+ });
70
+
71
+ it('should remove the subscription', () => {
72
+ context.connection.queryCount.should.equal(0);
73
+ });
74
+ }),
75
+ );
@@ -14,7 +14,11 @@ describe('when connection errors', given(a_server_sent_event_hub_connection, con
14
14
  context.setup();
15
15
  context.connection.subscribe(queryId, { queryName: 'MyQuery' }, sinon.stub());
16
16
  context.simulateOpen();
17
- context.simulateMessage({ type: HubMessageType.Connected, payload: 'conn-1' });
17
+ context.simulateMessage({
18
+ type: HubMessageType.Connected,
19
+ payload: 'conn-1',
20
+ supportsSubscriptionRevisions: true,
21
+ });
18
22
  context.simulateError();
19
23
  });
20
24
 
@@ -31,15 +35,14 @@ describe('when connection errors', given(a_server_sent_event_hub_connection, con
31
35
 
32
36
  beforeEach(() => {
33
37
  newEventSourceCreated = false;
34
- // Replace the global EventSource with a stub that records construction
38
+ // Replace the global EventSource with a stub that records construction.
39
+ // SAFETY: This test double supplies the EventSource constructor and static ready-state shape used by the client.
35
40
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
41
  const FakeClass = function (this: any) {
37
42
  newEventSourceCreated = true;
38
43
  return context.fakeEventSource;
39
44
  } as unknown as new (url: string) => EventSource;
40
- (FakeClass as unknown as Record<string, unknown>)['CONNECTING'] = 0;
41
- (FakeClass as unknown as Record<string, unknown>)['OPEN'] = 1;
42
- (FakeClass as unknown as Record<string, unknown>)['CLOSED'] = 2;
45
+ Object.assign(FakeClass, { CONNECTING: 0, OPEN: 1, CLOSED: 2 });
43
46
  (globalThis as Record<string, unknown>)['EventSource'] = FakeClass;
44
47
 
45
48
  const reconnectCallback = (context.policy.schedule as sinon.SinonStub).getCall(0).args[0] as ReconnectCallback;
@@ -57,6 +60,20 @@ describe('when connection errors', given(a_server_sent_event_hub_connection, con
57
60
  context.simulateMessage({ type: HubMessageType.Connected, payload: 'conn-2' });
58
61
  });
59
62
 
60
- it('should re-subscribe all active queries', () => context.fetchStub.calledOnce.should.be.true);
63
+ it('should re-subscribe all active queries', () =>
64
+ context.fetchStub.calledOnce.should.equal(true));
65
+
66
+ it('should reset to legacy mode until the new connection advertises capabilities', () => {
67
+ const rawBody = context.fetchStub.firstCall.args[1].body as string;
68
+ let body: { revision?: number };
69
+ try {
70
+ body = JSON.parse(rawBody) as { revision?: number };
71
+ } catch (error) {
72
+ throw new Error('Expected a valid subscribe request body', {
73
+ cause: error,
74
+ });
75
+ }
76
+ (body.revision === undefined).should.equal(true);
77
+ });
61
78
  });
62
79
  }));
@@ -0,0 +1,41 @@
1
+ // Copyright (c) Cratis. All rights reserved.
2
+ // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
+
4
+ import sinon from 'sinon';
5
+ import { a_server_sent_event_hub_connection } from '../given/a_server_sent_event_hub_connection';
6
+ import { given } from '../../../given';
7
+ import type { ReconnectCallback } from '../../IReconnectPolicy';
8
+
9
+ describe(
10
+ 'when an immediate SSE open wins a pending backoff race',
11
+ given(a_server_sent_event_hub_connection, (context) => {
12
+ beforeEach(() => {
13
+ context.setup();
14
+ sinon.stub(console, 'warn');
15
+ context.connection.subscribe(
16
+ 'query-a',
17
+ { queryName: 'QueryA' },
18
+ sinon.stub(),
19
+ );
20
+ context.simulateError();
21
+
22
+ const delayedReconnect = context.policy.schedule.firstCall
23
+ .args[0] as ReconnectCallback;
24
+ context.connection.subscribe(
25
+ 'query-b',
26
+ { queryName: 'QueryB' },
27
+ sinon.stub(),
28
+ );
29
+ delayedReconnect();
30
+ });
31
+
32
+ afterEach(() => sinon.restore());
33
+
34
+ it('should create only the retired and immediate event sources', () =>
35
+ context.eventSources.length.should.equal(2));
36
+ it('should cancel the pending backoff when the immediate open wins', () =>
37
+ context.policy.cancel.called.should.equal(true));
38
+ it('should leave the immediate source connecting', () =>
39
+ context.eventSources[1].readyState.should.equal(EventSource.CONNECTING));
40
+ }),
41
+ );