@hot-updater/react-native 1.0.0-rc.15 → 1.0.0-rc.17

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 (302) hide show
  1. package/android/src/main/java/com/hotupdater/BundleFileStorageService.kt +491 -388
  2. package/android/src/main/java/com/hotupdater/BundleMetadata.kt +5 -11
  3. package/android/src/main/java/com/hotupdater/FileManagerService.kt +45 -0
  4. package/android/src/main/java/com/hotupdater/HotUpdaterException.kt +290 -12
  5. package/android/src/main/java/com/hotupdater/HotUpdaterImpl.kt +35 -19
  6. package/android/src/main/java/com/hotupdater/InstallIdentityService.kt +37 -0
  7. package/android/src/main/java/com/hotupdater/KeyValueStorageService.kt +86 -0
  8. package/android/src/main/java/com/hotupdater/NetworkState.kt +31 -0
  9. package/android/src/main/java/com/hotupdater/NoBackupStorage.kt +17 -0
  10. package/android/src/main/java/com/hotupdater/OkHttpDownloadService.kt +110 -52
  11. package/android/src/main/java/com/hotupdater/PreviousProcessExit.kt +89 -0
  12. package/android/src/main/java/com/hotupdater/ReactNativeValueConverters.kt +34 -0
  13. package/android/src/newarch/HotUpdaterModule.kt +74 -69
  14. package/android/src/oldarch/HotUpdaterModule.kt +63 -59
  15. package/android/src/oldarch/HotUpdaterSpec.kt +4 -6
  16. package/android/src/test/java/com/hotupdater/BsdiffPatchTest.kt +1 -1
  17. package/android/src/test/java/com/hotupdater/BundleFileStorageServiceTest.kt +446 -61
  18. package/android/src/test/java/com/hotupdater/HotUpdaterExceptionTest.kt +220 -0
  19. package/android/src/test/java/com/hotupdater/HotUpdaterImplTest.kt +19 -27
  20. package/android/src/test/java/com/hotupdater/InstallIdentityServiceTest.kt +71 -0
  21. package/android/src/test/java/com/hotupdater/KeyValueStorageServiceTest.kt +106 -0
  22. package/android/src/test/java/com/hotupdater/NoBackupContext.kt +11 -0
  23. package/android/src/test/java/com/hotupdater/OkHttpDownloadServiceTest.kt +309 -23
  24. package/android/src/test/java/com/hotupdater/PreviousProcessExitTest.kt +57 -0
  25. package/ios/HotUpdater/Internal/BundleFileStorageService.swift +238 -157
  26. package/ios/HotUpdater/Internal/BundleMetadata.swift +3 -53
  27. package/ios/HotUpdater/Internal/FileManagerService.swift +48 -0
  28. package/ios/HotUpdater/Internal/HotUpdater.mm +8 -18
  29. package/ios/HotUpdater/Internal/HotUpdaterImpl.swift +48 -29
  30. package/ios/HotUpdater/Internal/KeyValueStorageService.swift +71 -0
  31. package/ios/HotUpdater/Internal/URLSessionDownloadService.swift +108 -1
  32. package/ios/HotUpdater/Internal/UpdateFailure.swift +390 -0
  33. package/lib/commonjs/appReady.js +111 -0
  34. package/lib/commonjs/appReady.js.map +1 -0
  35. package/lib/commonjs/appReady.spec.js +360 -0
  36. package/lib/commonjs/appReady.spec.js.map +1 -0
  37. package/lib/commonjs/{notifyAppReadyInsights.test-utils.js → appReady.test-utils.js} +4 -3
  38. package/lib/commonjs/appReady.test-utils.js.map +1 -0
  39. package/lib/commonjs/baseURL.js +16 -0
  40. package/lib/commonjs/baseURL.js.map +1 -0
  41. package/lib/commonjs/checkForUpdate.js +104 -56
  42. package/lib/commonjs/checkForUpdate.js.map +1 -1
  43. package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js +337 -74
  44. package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js.map +1 -1
  45. package/lib/commonjs/clientPlugin.js +49 -0
  46. package/lib/commonjs/clientPlugin.js.map +1 -0
  47. package/lib/commonjs/entryImportGraph.spec.js +50 -0
  48. package/lib/commonjs/entryImportGraph.spec.js.map +1 -0
  49. package/lib/commonjs/fetchJSON.js +2 -6
  50. package/lib/commonjs/fetchJSON.js.map +1 -1
  51. package/lib/commonjs/httpClient.js +15 -67
  52. package/lib/commonjs/httpClient.js.map +1 -1
  53. package/lib/commonjs/httpClient.spec.js +26 -9
  54. package/lib/commonjs/httpClient.spec.js.map +1 -1
  55. package/lib/commonjs/index.js +49 -25
  56. package/lib/commonjs/index.js.map +1 -1
  57. package/lib/commonjs/index.spec.js +126 -40
  58. package/lib/commonjs/index.spec.js.map +1 -1
  59. package/lib/commonjs/native.js +67 -48
  60. package/lib/commonjs/native.js.map +1 -1
  61. package/lib/commonjs/native.spec.js +80 -58
  62. package/lib/commonjs/native.spec.js.map +1 -1
  63. package/lib/commonjs/pluginHost.js +208 -0
  64. package/lib/commonjs/pluginHost.js.map +1 -0
  65. package/lib/commonjs/pluginHost.spec.js +292 -0
  66. package/lib/commonjs/pluginHost.spec.js.map +1 -0
  67. package/lib/commonjs/plugins/insights/eventId.js +129 -0
  68. package/lib/commonjs/plugins/insights/eventId.js.map +1 -0
  69. package/lib/commonjs/plugins/insights/eventId.spec.js +47 -0
  70. package/lib/commonjs/plugins/insights/eventId.spec.js.map +1 -0
  71. package/lib/commonjs/plugins/insights/index.js +272 -0
  72. package/lib/commonjs/plugins/insights/index.js.map +1 -0
  73. package/lib/commonjs/plugins/insights/insights.spec.js +640 -0
  74. package/lib/commonjs/plugins/insights/insights.spec.js.map +1 -0
  75. package/lib/commonjs/plugins/insights/sender.js +128 -0
  76. package/lib/commonjs/plugins/insights/sender.js.map +1 -0
  77. package/lib/commonjs/plugins/insights/sender.spec.js +265 -0
  78. package/lib/commonjs/plugins/insights/sender.spec.js.map +1 -0
  79. package/lib/commonjs/plugins/insights/state.js +145 -0
  80. package/lib/commonjs/plugins/insights/state.js.map +1 -0
  81. package/lib/commonjs/releaseCatalogCache.js +13 -2
  82. package/lib/commonjs/releaseCatalogCache.js.map +1 -1
  83. package/lib/commonjs/releaseCatalogCache.spec.js +18 -0
  84. package/lib/commonjs/releaseCatalogCache.spec.js.map +1 -1
  85. package/lib/commonjs/sdkVersion.js +1 -1
  86. package/lib/commonjs/specs/NativeHotUpdater.js.map +1 -1
  87. package/lib/commonjs/updateError.js +132 -0
  88. package/lib/commonjs/updateError.js.map +1 -0
  89. package/lib/commonjs/updateError.spec.js +149 -0
  90. package/lib/commonjs/updateError.spec.js.map +1 -0
  91. package/lib/commonjs/wrap.js +43 -25
  92. package/lib/commonjs/wrap.js.map +1 -1
  93. package/lib/commonjs/wrap.progress.spec.js +195 -0
  94. package/lib/commonjs/wrap.progress.spec.js.map +1 -0
  95. package/lib/commonjs/wrap.spec.js +94 -230
  96. package/lib/commonjs/wrap.spec.js.map +1 -1
  97. package/lib/module/appReady.js +103 -0
  98. package/lib/module/appReady.js.map +1 -0
  99. package/lib/module/appReady.spec.js +359 -0
  100. package/lib/module/appReady.spec.js.map +1 -0
  101. package/lib/module/{notifyAppReadyInsights.test-utils.js → appReady.test-utils.js} +4 -3
  102. package/lib/module/appReady.test-utils.js.map +1 -0
  103. package/lib/module/baseURL.js +11 -0
  104. package/lib/module/baseURL.js.map +1 -0
  105. package/lib/module/checkForUpdate.js +103 -57
  106. package/lib/module/checkForUpdate.js.map +1 -1
  107. package/lib/module/checkForUpdate.releaseCatalog.spec.js +337 -74
  108. package/lib/module/checkForUpdate.releaseCatalog.spec.js.map +1 -1
  109. package/lib/module/clientPlugin.js +44 -0
  110. package/lib/module/clientPlugin.js.map +1 -0
  111. package/lib/module/entryImportGraph.spec.js +50 -0
  112. package/lib/module/entryImportGraph.spec.js.map +1 -0
  113. package/lib/module/fetchJSON.js +2 -6
  114. package/lib/module/fetchJSON.js.map +1 -1
  115. package/lib/module/httpClient.js +14 -66
  116. package/lib/module/httpClient.js.map +1 -1
  117. package/lib/module/httpClient.spec.js +26 -9
  118. package/lib/module/httpClient.spec.js.map +1 -1
  119. package/lib/module/index.js +44 -27
  120. package/lib/module/index.js.map +1 -1
  121. package/lib/module/index.spec.js +127 -41
  122. package/lib/module/index.spec.js.map +1 -1
  123. package/lib/module/native.js +63 -44
  124. package/lib/module/native.js.map +1 -1
  125. package/lib/module/native.spec.js +80 -58
  126. package/lib/module/native.spec.js.map +1 -1
  127. package/lib/module/pluginHost.js +200 -0
  128. package/lib/module/pluginHost.js.map +1 -0
  129. package/lib/module/pluginHost.spec.js +291 -0
  130. package/lib/module/pluginHost.spec.js.map +1 -0
  131. package/lib/module/plugins/insights/eventId.js +122 -0
  132. package/lib/module/plugins/insights/eventId.js.map +1 -0
  133. package/lib/module/plugins/insights/eventId.spec.js +47 -0
  134. package/lib/module/plugins/insights/eventId.spec.js.map +1 -0
  135. package/lib/module/plugins/insights/index.js +268 -0
  136. package/lib/module/plugins/insights/index.js.map +1 -0
  137. package/lib/module/plugins/insights/insights.spec.js +639 -0
  138. package/lib/module/plugins/insights/insights.spec.js.map +1 -0
  139. package/lib/module/plugins/insights/sender.js +123 -0
  140. package/lib/module/plugins/insights/sender.js.map +1 -0
  141. package/lib/module/plugins/insights/sender.spec.js +265 -0
  142. package/lib/module/plugins/insights/sender.spec.js.map +1 -0
  143. package/lib/module/plugins/insights/state.js +139 -0
  144. package/lib/module/plugins/insights/state.js.map +1 -0
  145. package/lib/module/releaseCatalogCache.js +13 -2
  146. package/lib/module/releaseCatalogCache.js.map +1 -1
  147. package/lib/module/releaseCatalogCache.spec.js +18 -0
  148. package/lib/module/releaseCatalogCache.spec.js.map +1 -1
  149. package/lib/module/sdkVersion.js +1 -1
  150. package/lib/module/specs/NativeHotUpdater.js.map +1 -1
  151. package/lib/module/updateError.js +126 -0
  152. package/lib/module/updateError.js.map +1 -0
  153. package/lib/module/updateError.spec.js +149 -0
  154. package/lib/module/updateError.spec.js.map +1 -0
  155. package/lib/module/wrap.js +43 -25
  156. package/lib/module/wrap.js.map +1 -1
  157. package/lib/module/wrap.progress.spec.js +196 -0
  158. package/lib/module/wrap.progress.spec.js.map +1 -0
  159. package/lib/module/wrap.spec.js +93 -229
  160. package/lib/module/wrap.spec.js.map +1 -1
  161. package/lib/typescript/commonjs/appReady.d.ts +23 -0
  162. package/lib/typescript/commonjs/appReady.d.ts.map +1 -0
  163. package/lib/typescript/commonjs/appReady.test-utils.d.ts +9 -0
  164. package/lib/typescript/commonjs/appReady.test-utils.d.ts.map +1 -0
  165. package/lib/typescript/commonjs/baseURL.d.ts +4 -0
  166. package/lib/typescript/commonjs/baseURL.d.ts.map +1 -0
  167. package/lib/typescript/commonjs/checkForUpdate.d.ts +15 -2
  168. package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -1
  169. package/lib/typescript/commonjs/clientPlugin.d.ts +185 -0
  170. package/lib/typescript/commonjs/clientPlugin.d.ts.map +1 -0
  171. package/lib/typescript/commonjs/fetchJSON.d.ts +2 -3
  172. package/lib/typescript/commonjs/fetchJSON.d.ts.map +1 -1
  173. package/lib/typescript/commonjs/httpClient.d.ts +2 -30
  174. package/lib/typescript/commonjs/httpClient.d.ts.map +1 -1
  175. package/lib/typescript/commonjs/index.d.ts +3 -6
  176. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  177. package/lib/typescript/commonjs/native.d.ts +29 -15
  178. package/lib/typescript/commonjs/native.d.ts.map +1 -1
  179. package/lib/typescript/commonjs/pluginHost.d.ts +29 -0
  180. package/lib/typescript/commonjs/pluginHost.d.ts.map +1 -0
  181. package/lib/typescript/commonjs/plugins/insights/eventId.d.ts +18 -0
  182. package/lib/typescript/commonjs/plugins/insights/eventId.d.ts.map +1 -0
  183. package/lib/typescript/commonjs/plugins/insights/index.d.ts +40 -0
  184. package/lib/typescript/commonjs/plugins/insights/index.d.ts.map +1 -0
  185. package/lib/typescript/commonjs/plugins/insights/sender.d.ts +74 -0
  186. package/lib/typescript/commonjs/plugins/insights/sender.d.ts.map +1 -0
  187. package/lib/typescript/commonjs/plugins/insights/state.d.ts +46 -0
  188. package/lib/typescript/commonjs/plugins/insights/state.d.ts.map +1 -0
  189. package/lib/typescript/commonjs/releaseCatalogCache.d.ts +5 -1
  190. package/lib/typescript/commonjs/releaseCatalogCache.d.ts.map +1 -1
  191. package/lib/typescript/commonjs/sdkVersion.d.ts +1 -1
  192. package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts +34 -12
  193. package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts.map +1 -1
  194. package/lib/typescript/commonjs/updateError.d.ts +26 -0
  195. package/lib/typescript/commonjs/updateError.d.ts.map +1 -0
  196. package/lib/typescript/commonjs/wrap.d.ts.map +1 -1
  197. package/lib/typescript/commonjs/wrap.types.d.ts +6 -5
  198. package/lib/typescript/commonjs/wrap.types.d.ts.map +1 -1
  199. package/lib/typescript/module/appReady.d.ts +23 -0
  200. package/lib/typescript/module/appReady.d.ts.map +1 -0
  201. package/lib/typescript/module/appReady.test-utils.d.ts +9 -0
  202. package/lib/typescript/module/appReady.test-utils.d.ts.map +1 -0
  203. package/lib/typescript/module/baseURL.d.ts +4 -0
  204. package/lib/typescript/module/baseURL.d.ts.map +1 -0
  205. package/lib/typescript/module/checkForUpdate.d.ts +15 -2
  206. package/lib/typescript/module/checkForUpdate.d.ts.map +1 -1
  207. package/lib/typescript/module/clientPlugin.d.ts +185 -0
  208. package/lib/typescript/module/clientPlugin.d.ts.map +1 -0
  209. package/lib/typescript/module/fetchJSON.d.ts +2 -3
  210. package/lib/typescript/module/fetchJSON.d.ts.map +1 -1
  211. package/lib/typescript/module/httpClient.d.ts +2 -30
  212. package/lib/typescript/module/httpClient.d.ts.map +1 -1
  213. package/lib/typescript/module/index.d.ts +3 -6
  214. package/lib/typescript/module/index.d.ts.map +1 -1
  215. package/lib/typescript/module/native.d.ts +29 -15
  216. package/lib/typescript/module/native.d.ts.map +1 -1
  217. package/lib/typescript/module/pluginHost.d.ts +29 -0
  218. package/lib/typescript/module/pluginHost.d.ts.map +1 -0
  219. package/lib/typescript/module/plugins/insights/eventId.d.ts +18 -0
  220. package/lib/typescript/module/plugins/insights/eventId.d.ts.map +1 -0
  221. package/lib/typescript/module/plugins/insights/index.d.ts +40 -0
  222. package/lib/typescript/module/plugins/insights/index.d.ts.map +1 -0
  223. package/lib/typescript/module/plugins/insights/sender.d.ts +74 -0
  224. package/lib/typescript/module/plugins/insights/sender.d.ts.map +1 -0
  225. package/lib/typescript/module/plugins/insights/state.d.ts +46 -0
  226. package/lib/typescript/module/plugins/insights/state.d.ts.map +1 -0
  227. package/lib/typescript/module/releaseCatalogCache.d.ts +5 -1
  228. package/lib/typescript/module/releaseCatalogCache.d.ts.map +1 -1
  229. package/lib/typescript/module/sdkVersion.d.ts +1 -1
  230. package/lib/typescript/module/specs/NativeHotUpdater.d.ts +34 -12
  231. package/lib/typescript/module/specs/NativeHotUpdater.d.ts.map +1 -1
  232. package/lib/typescript/module/updateError.d.ts +26 -0
  233. package/lib/typescript/module/updateError.d.ts.map +1 -0
  234. package/lib/typescript/module/wrap.d.ts.map +1 -1
  235. package/lib/typescript/module/wrap.types.d.ts +6 -5
  236. package/lib/typescript/module/wrap.types.d.ts.map +1 -1
  237. package/package.json +14 -2
  238. package/plugins/insights/package.json +8 -0
  239. package/src/appReady.spec.ts +393 -0
  240. package/src/{notifyAppReadyInsights.test-utils.ts → appReady.test-utils.ts} +7 -7
  241. package/src/appReady.ts +149 -0
  242. package/src/baseURL.ts +15 -0
  243. package/src/checkForUpdate.releaseCatalog.spec.ts +370 -76
  244. package/src/checkForUpdate.ts +135 -80
  245. package/src/clientPlugin.ts +231 -0
  246. package/src/entryImportGraph.spec.ts +65 -0
  247. package/src/fetchJSON.ts +3 -10
  248. package/src/httpClient.spec.ts +28 -9
  249. package/src/httpClient.ts +16 -109
  250. package/src/index.spec.ts +129 -36
  251. package/src/index.ts +67 -37
  252. package/src/native.spec.ts +98 -72
  253. package/src/native.ts +93 -77
  254. package/src/pluginHost.spec.ts +297 -0
  255. package/src/pluginHost.ts +262 -0
  256. package/src/plugins/insights/eventId.spec.ts +60 -0
  257. package/src/plugins/insights/eventId.ts +171 -0
  258. package/src/plugins/insights/index.ts +367 -0
  259. package/src/plugins/insights/insights.spec.ts +732 -0
  260. package/src/plugins/insights/sender.spec.ts +287 -0
  261. package/src/plugins/insights/sender.ts +221 -0
  262. package/src/plugins/insights/state.ts +184 -0
  263. package/src/releaseCatalogCache.spec.ts +22 -0
  264. package/src/releaseCatalogCache.ts +19 -4
  265. package/src/sdkVersion.ts +1 -1
  266. package/src/specs/NativeHotUpdater.ts +34 -13
  267. package/src/updateError.spec.ts +144 -0
  268. package/src/updateError.ts +153 -0
  269. package/src/wrap.progress.spec.ts +232 -0
  270. package/src/wrap.spec.ts +100 -283
  271. package/src/wrap.tsx +57 -26
  272. package/src/wrap.types.ts +6 -5
  273. package/lib/commonjs/notifyAppReadyInsights.boundary.spec.js +0 -225
  274. package/lib/commonjs/notifyAppReadyInsights.boundary.spec.js.map +0 -1
  275. package/lib/commonjs/notifyAppReadyInsights.js +0 -188
  276. package/lib/commonjs/notifyAppReadyInsights.js.map +0 -1
  277. package/lib/commonjs/notifyAppReadyInsights.spec.js +0 -378
  278. package/lib/commonjs/notifyAppReadyInsights.spec.js.map +0 -1
  279. package/lib/commonjs/notifyAppReadyInsights.test-utils.js.map +0 -1
  280. package/lib/commonjs/notifyAppReadyInsights.transport.spec.js +0 -124
  281. package/lib/commonjs/notifyAppReadyInsights.transport.spec.js.map +0 -1
  282. package/lib/module/notifyAppReadyInsights.boundary.spec.js +0 -224
  283. package/lib/module/notifyAppReadyInsights.boundary.spec.js.map +0 -1
  284. package/lib/module/notifyAppReadyInsights.js +0 -181
  285. package/lib/module/notifyAppReadyInsights.js.map +0 -1
  286. package/lib/module/notifyAppReadyInsights.spec.js +0 -377
  287. package/lib/module/notifyAppReadyInsights.spec.js.map +0 -1
  288. package/lib/module/notifyAppReadyInsights.test-utils.js.map +0 -1
  289. package/lib/module/notifyAppReadyInsights.transport.spec.js +0 -123
  290. package/lib/module/notifyAppReadyInsights.transport.spec.js.map +0 -1
  291. package/lib/typescript/commonjs/notifyAppReadyInsights.d.ts +0 -25
  292. package/lib/typescript/commonjs/notifyAppReadyInsights.d.ts.map +0 -1
  293. package/lib/typescript/commonjs/notifyAppReadyInsights.test-utils.d.ts +0 -8
  294. package/lib/typescript/commonjs/notifyAppReadyInsights.test-utils.d.ts.map +0 -1
  295. package/lib/typescript/module/notifyAppReadyInsights.d.ts +0 -25
  296. package/lib/typescript/module/notifyAppReadyInsights.d.ts.map +0 -1
  297. package/lib/typescript/module/notifyAppReadyInsights.test-utils.d.ts +0 -8
  298. package/lib/typescript/module/notifyAppReadyInsights.test-utils.d.ts.map +0 -1
  299. package/src/notifyAppReadyInsights.boundary.spec.ts +0 -242
  300. package/src/notifyAppReadyInsights.spec.ts +0 -362
  301. package/src/notifyAppReadyInsights.transport.spec.ts +0 -138
  302. package/src/notifyAppReadyInsights.ts +0 -293
@@ -0,0 +1,640 @@
1
+ "use strict";
2
+
3
+ var _core = require("@hot-updater/core");
4
+ var _vitest = require("vitest");
5
+ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
6
+ _vitest.vi.mock("react-native", () => ({
7
+ Platform: {
8
+ OS: "ios"
9
+ }
10
+ }));
11
+ const native = _vitest.vi.hoisted(() => {
12
+ Reflect.set(globalThis, "HotUpdater", {
13
+ SDK_VERSION: "test-sdk-version"
14
+ });
15
+ const storage = new Map();
16
+ return {
17
+ storage,
18
+ getAppVersion: _vitest.vi.fn(() => "1.0.0"),
19
+ getBundleId: _vitest.vi.fn(() => "bundle-a"),
20
+ getChannel: _vitest.vi.fn(() => "production"),
21
+ getCohort: _vitest.vi.fn(() => "123"),
22
+ getFingerprintHash: _vitest.vi.fn(() => "fingerprint-hash"),
23
+ getInstallId: _vitest.vi.fn(() => "install-id"),
24
+ getStorageItem: _vitest.vi.fn(key => storage.get(key) ?? null),
25
+ setStorageItem: _vitest.vi.fn((key, value) => {
26
+ if (value === null) storage.delete(key);else storage.set(key, value);
27
+ })
28
+ };
29
+ });
30
+ _vitest.vi.mock("../../native", () => native);
31
+ const DAY_MS = 86_400_000;
32
+ const MORNING = Date.UTC(2026, 8, 30, 9);
33
+ let responses = [];
34
+ const fetchMock = _vitest.vi.fn(async (_url, _init) => {
35
+ const next = responses.shift() ?? 204;
36
+ return typeof next === "number" ? new Response(null, {
37
+ status: next
38
+ }) : next();
39
+ });
40
+ const sentEvents = () => fetchMock.mock.calls.map(([, init]) => JSON.parse(String(init?.body)));
41
+ const sentTypes = () => sentEvents().map(({
42
+ type
43
+ }) => type);
44
+
45
+ /** A server without Insights mounts no `/events`. */
46
+ const disabledResponse = () => new Response(null, {
47
+ status: 404
48
+ });
49
+
50
+ /** Starts a JavaScript runtime with the plugin; native storage persists across launches. */
51
+ const launch = async (options = {}, beforeInit) => {
52
+ _vitest.vi.resetModules();
53
+ const [{
54
+ configurePlugins,
55
+ emitPluginHook
56
+ }, {
57
+ insights
58
+ }] = await Promise.all([Promise.resolve().then(() => _interopRequireWildcard(require("../../pluginHost"))), Promise.resolve().then(() => _interopRequireWildcard(require("./index")))]);
59
+ const plugin = insights(options);
60
+ beforeInit?.(plugin);
61
+ configurePlugins([plugin], {
62
+ baseURL: "https://updates.example.com/hot-updater",
63
+ requestHeaders: {
64
+ "x-api-key": "client-key"
65
+ }
66
+ });
67
+ const emit = (name, payload) => {
68
+ emitPluginHook(name, () => payload);
69
+ };
70
+ return {
71
+ plugin,
72
+ appReady: result => emit("onAppReady", result),
73
+ updateCheck: result => emit("onUpdateCheck", result),
74
+ downloaded: info => emit("onBundleDownloaded", info),
75
+ updateError: error => emit("onUpdateError", error)
76
+ };
77
+ };
78
+ const unchangedLaunch = (overrides = {}) => ({
79
+ status: "UNCHANGED",
80
+ channel: "production",
81
+ bundleId: "bundle-a",
82
+ releaseId: "release-a",
83
+ previousProcessExit: null,
84
+ ...overrides
85
+ });
86
+ const appliedLaunch = {
87
+ status: "UPDATE_APPLIED",
88
+ channel: "production",
89
+ fromBundleId: "bundle-a",
90
+ fromReleaseId: "release-a",
91
+ toBundleId: "bundle-b",
92
+ toReleaseId: "release-b",
93
+ updateStrategy: "appVersion",
94
+ previousProcessExit: null
95
+ };
96
+ const download = {
97
+ channel: "production",
98
+ fromBundleId: "bundle-a",
99
+ fromReleaseId: "release-a",
100
+ toBundleId: "bundle-b",
101
+ toReleaseId: "release-b",
102
+ updateStrategy: "appVersion",
103
+ delivery: "manifest",
104
+ patchFallback: false
105
+ };
106
+ const downloadFailure = (overrides = {}) => ({
107
+ stage: "download",
108
+ reason: "hash_mismatch",
109
+ targetBundleId: "bundle-b",
110
+ targetReleaseId: "release-b",
111
+ channel: "production",
112
+ bundleId: "bundle-a",
113
+ releaseId: "release-a",
114
+ updateStrategy: "fingerprint",
115
+ cause: new Error("hash mismatch"),
116
+ ...overrides
117
+ });
118
+ const flush = () => _vitest.vi.runAllTimersAsync();
119
+ (0, _vitest.describe)("insights() client plugin", () => {
120
+ (0, _vitest.beforeEach)(() => {
121
+ _vitest.vi.useFakeTimers({
122
+ now: MORNING
123
+ });
124
+ _vitest.vi.spyOn(Math, "random").mockReturnValue(0.5);
125
+ _vitest.vi.stubGlobal("fetch", fetchMock);
126
+ _vitest.vi.stubGlobal("__DEV__", false);
127
+ fetchMock.mockClear();
128
+ responses = [];
129
+ native.storage.clear();
130
+ native.getAppVersion.mockReturnValue("1.0.0");
131
+ });
132
+ (0, _vitest.afterEach)(() => {
133
+ _vitest.vi.useRealTimers();
134
+ _vitest.vi.unstubAllGlobals();
135
+ _vitest.vi.restoreAllMocks();
136
+ });
137
+ (0, _vitest.it)("posts a launch as UNCHANGED with the app's identity", async () => {
138
+ const app = await launch();
139
+ app.appReady(unchangedLaunch());
140
+ await flush();
141
+ (0, _vitest.expect)(fetchMock).toHaveBeenCalledOnce();
142
+ const [url, init] = fetchMock.mock.calls[0];
143
+ (0, _vitest.expect)(url).toBe("https://updates.example.com/hot-updater/events");
144
+ (0, _vitest.expect)(new Headers(init?.headers).get("x-api-key")).toBe("client-key");
145
+ const [event] = sentEvents();
146
+ (0, _vitest.expect)((0, _core.isUUIDv7)(event?.eventId)).toBe(true);
147
+ (0, _vitest.expect)(event).toEqual({
148
+ appVersion: "1.0.0",
149
+ channel: "production",
150
+ cohort: "123",
151
+ eventId: event?.eventId,
152
+ fingerprintHash: "fingerprint-hash",
153
+ fromBundleId: null,
154
+ fromReleaseId: null,
155
+ installId: "install-id",
156
+ platform: "ios",
157
+ sdkVersion: "test-sdk-version",
158
+ toBundleId: "bundle-a",
159
+ toReleaseId: "release-a",
160
+ type: "UNCHANGED",
161
+ updateStrategy: null
162
+ });
163
+ });
164
+ (0, _vitest.describe)("daily launch reports", () => {
165
+ (0, _vitest.it)("sends UNCHANGED at most once per UTC day across launches", async () => {
166
+ (await launch()).appReady(unchangedLaunch());
167
+ await flush();
168
+ _vitest.vi.setSystemTime(Date.UTC(2026, 8, 30, 23, 59));
169
+ (await launch()).appReady(unchangedLaunch());
170
+ await flush();
171
+ (0, _vitest.expect)(fetchMock).toHaveBeenCalledOnce();
172
+ _vitest.vi.setSystemTime(Date.UTC(2026, 9, 1, 0, 1));
173
+ (await launch()).appReady(unchangedLaunch());
174
+ await flush();
175
+ (0, _vitest.expect)(sentTypes()).toEqual(["UNCHANGED", "UNCHANGED"]);
176
+ });
177
+ _vitest.it.each([{
178
+ label: "channel",
179
+ change: {
180
+ channel: "beta"
181
+ }
182
+ }, {
183
+ label: "bundle",
184
+ change: {
185
+ bundleId: "bundle-c"
186
+ }
187
+ }, {
188
+ label: "Release",
189
+ change: {
190
+ releaseId: "release-c"
191
+ }
192
+ }])("reports a launch again the same day when its $label changes", async ({
193
+ change
194
+ }) => {
195
+ (await launch()).appReady(unchangedLaunch());
196
+ await flush();
197
+ (await launch()).appReady(unchangedLaunch(change));
198
+ await flush();
199
+ (0, _vitest.expect)(sentTypes()).toEqual(["UNCHANGED", "UNCHANGED"]);
200
+ });
201
+ (0, _vitest.it)("reports a launch again the same day when the app version or user changes", async () => {
202
+ (await launch()).appReady(unchangedLaunch());
203
+ await flush();
204
+ native.getAppVersion.mockReturnValue("1.0.1");
205
+ (await launch()).appReady(unchangedLaunch());
206
+ await flush();
207
+ const app = await launch();
208
+ app.plugin.setUser({
209
+ userId: "user-1"
210
+ });
211
+ app.appReady(unchangedLaunch());
212
+ await flush();
213
+ (0, _vitest.expect)(sentEvents().map(({
214
+ appVersion,
215
+ userId
216
+ }) => [appVersion, userId])).toEqual([["1.0.0", undefined], ["1.0.1", undefined], ["1.0.1", "user-1"]]);
217
+ });
218
+ (0, _vitest.it)("counts a delivered apply as the day's report of its bundle", async () => {
219
+ (await launch()).appReady(appliedLaunch);
220
+ await flush();
221
+ (await launch()).appReady(unchangedLaunch({
222
+ bundleId: "bundle-b",
223
+ releaseId: "release-b"
224
+ }));
225
+ await flush();
226
+ (0, _vitest.expect)(sentTypes()).toEqual(["UPDATE_APPLIED"]);
227
+ });
228
+ (0, _vitest.it)("reports the next launch after a delivered download or failure", async () => {
229
+ const first = await launch();
230
+ first.appReady(unchangedLaunch());
231
+ await flush();
232
+ first.downloaded(download);
233
+ await flush();
234
+ const second = await launch();
235
+ second.appReady(unchangedLaunch());
236
+ await flush();
237
+ second.updateError(downloadFailure());
238
+ await flush();
239
+ (await launch()).appReady(unchangedLaunch());
240
+ await flush();
241
+ (0, _vitest.expect)(sentTypes()).toEqual(["UNCHANGED", "UPDATE_DOWNLOADED", "UNCHANGED", "UPDATE_FAILED", "UNCHANGED"]);
242
+ });
243
+ (0, _vitest.it)("reports the launch again when the server did not store it", async () => {
244
+ responses = [400];
245
+ _vitest.vi.spyOn(console, "warn").mockImplementation(() => {});
246
+ (await launch()).appReady(unchangedLaunch());
247
+ await flush();
248
+ (await launch()).appReady(unchangedLaunch());
249
+ await flush();
250
+ (0, _vitest.expect)(sentTypes()).toEqual(["UNCHANGED", "UNCHANGED"]);
251
+ });
252
+ (0, _vitest.it)("always sends downloads, applies, and recoveries", async () => {
253
+ const first = await launch();
254
+ first.appReady(unchangedLaunch());
255
+ first.downloaded(download);
256
+ await flush();
257
+ (await launch()).appReady(appliedLaunch);
258
+ (await launch()).appReady({
259
+ ...appliedLaunch,
260
+ status: "RECOVERED",
261
+ fromBundleId: "bundle-b",
262
+ toBundleId: "bundle-a"
263
+ });
264
+ await flush();
265
+ (0, _vitest.expect)(sentTypes()).toEqual(["UNCHANGED", "UPDATE_DOWNLOADED", "UPDATE_APPLIED", "RECOVERED"]);
266
+ });
267
+ (0, _vitest.it)("sends one report when the launch and a no-update check both report", async () => {
268
+ const app = await launch();
269
+ app.appReady(unchangedLaunch());
270
+ app.updateCheck({
271
+ status: "UNCHANGED",
272
+ channel: "production",
273
+ bundleId: "bundle-a",
274
+ releaseId: "release-a",
275
+ previousReleaseId: "release-a"
276
+ });
277
+ await flush();
278
+ (0, _vitest.expect)(sentTypes()).toEqual(["UNCHANGED"]);
279
+ });
280
+ (0, _vitest.it)("reports a same-bundle Release adoption with the Release it replaced", async () => {
281
+ const app = await launch();
282
+ app.appReady(unchangedLaunch());
283
+ await flush();
284
+ app.updateCheck({
285
+ status: "UNCHANGED",
286
+ channel: "production",
287
+ bundleId: "bundle-a",
288
+ releaseId: "release-a2",
289
+ previousReleaseId: "release-a"
290
+ });
291
+ await flush();
292
+ (0, _vitest.expect)(sentEvents()[1]).toMatchObject({
293
+ fromReleaseId: "release-a",
294
+ toBundleId: "bundle-a",
295
+ toReleaseId: "release-a2",
296
+ type: "UNCHANGED"
297
+ });
298
+ });
299
+ (0, _vitest.it)("sends no launch report after a download in the same runtime", async () => {
300
+ const app = await launch();
301
+ app.downloaded(download);
302
+ app.downloaded(download);
303
+ app.updateCheck({
304
+ status: "UNCHANGED",
305
+ channel: "production",
306
+ bundleId: "bundle-b",
307
+ releaseId: "release-b",
308
+ previousReleaseId: "release-b"
309
+ });
310
+ await flush();
311
+ (0, _vitest.expect)(sentTypes()).toEqual(["UPDATE_DOWNLOADED"]);
312
+ });
313
+ });
314
+ (0, _vitest.describe)("when the server runs without Insights", () => {
315
+ (0, _vitest.it)("sends nothing more in this runtime after a 404", async () => {
316
+ responses = [disabledResponse];
317
+ const app = await launch();
318
+ app.appReady(unchangedLaunch());
319
+ await flush();
320
+ app.downloaded(download);
321
+ await flush();
322
+ _vitest.vi.setSystemTime(MORNING + 2 * DAY_MS);
323
+ app.updateError(downloadFailure());
324
+ await flush();
325
+ (0, _vitest.expect)(sentTypes()).toEqual(["UNCHANGED"]);
326
+ });
327
+ (0, _vitest.it)("pauses later launches for 24 hours, then probes again", async () => {
328
+ responses = [disabledResponse];
329
+ (await launch()).appReady(unchangedLaunch());
330
+ await flush();
331
+ _vitest.vi.setSystemTime(MORNING + DAY_MS - 1);
332
+ (await launch()).appReady(appliedLaunch);
333
+ await flush();
334
+ (0, _vitest.expect)(fetchMock).toHaveBeenCalledOnce();
335
+ _vitest.vi.setSystemTime(MORNING + DAY_MS);
336
+ (await launch()).appReady(appliedLaunch);
337
+ await flush();
338
+ (0, _vitest.expect)(sentTypes()).toEqual(["UNCHANGED", "UPDATE_APPLIED"]);
339
+
340
+ // The probe was stored, so Insights is on again.
341
+ (await launch()).appReady({
342
+ ...appliedLaunch,
343
+ toBundleId: "bundle-c"
344
+ });
345
+ await flush();
346
+ (0, _vitest.expect)(sentTypes()).toEqual(["UNCHANGED", "UPDATE_APPLIED", "UPDATE_APPLIED"]);
347
+ });
348
+ (0, _vitest.it)("ends a pause that starts after now, from a clock that went back", async () => {
349
+ native.storage.set("plugins/insights/pausedAt", String(MORNING + 60 * 60 * 1000));
350
+ (await launch()).appReady(unchangedLaunch());
351
+ await flush();
352
+ (0, _vitest.expect)(sentTypes()).toEqual(["UNCHANGED"]);
353
+ });
354
+ });
355
+ (0, _vitest.describe)("update failures", () => {
356
+ (0, _vitest.it)("reports a failure once per UTC day per stage, reason, and target", async () => {
357
+ const app = await launch();
358
+ app.updateError(downloadFailure({
359
+ httpStatus: undefined
360
+ }));
361
+ app.updateError(downloadFailure());
362
+ await flush();
363
+ (await launch()).updateError(downloadFailure());
364
+ await flush();
365
+ (0, _vitest.expect)(fetchMock).toHaveBeenCalledOnce();
366
+ const [event] = sentEvents();
367
+ (0, _vitest.expect)(event).toMatchObject({
368
+ fromBundleId: "bundle-a",
369
+ fromReleaseId: "release-a",
370
+ metadata: {
371
+ failure: {
372
+ reason: "hash_mismatch",
373
+ stage: "download"
374
+ }
375
+ },
376
+ toBundleId: "bundle-b",
377
+ toReleaseId: "release-b",
378
+ type: "UPDATE_FAILED",
379
+ updateStrategy: "fingerprint"
380
+ });
381
+ (0, _vitest.expect)(Object.keys(event?.metadata?.failure ?? {}).sort()).toEqual(["reason", "stage"]);
382
+ // A UUIDv7 led by the UTC day, the same on every device for one failure.
383
+ (0, _vitest.expect)((0, _core.isUUIDv7)(event?.eventId)).toBe(true);
384
+ (0, _vitest.expect)(parseInt(event.eventId.replace(/-/g, "").slice(0, 12), 16)).toBe(Date.UTC(2026, 8, 30));
385
+ (await launch()).updateError(downloadFailure({
386
+ reason: "signature"
387
+ }));
388
+ _vitest.vi.setSystemTime(MORNING + DAY_MS);
389
+ (await launch()).updateError(downloadFailure());
390
+ await flush();
391
+ const ids = sentEvents().map(({
392
+ eventId
393
+ }) => eventId);
394
+ (0, _vitest.expect)(sentEvents().map(({
395
+ metadata
396
+ }) => metadata?.failure?.reason)).toEqual(["hash_mismatch", "signature", "hash_mismatch"]);
397
+ (0, _vitest.expect)(new Set(ids).size).toBe(3);
398
+ });
399
+ (0, _vitest.it)("gives a failure that was not delivered the same id when it happens again", async () => {
400
+ responses = [500, 500, 500];
401
+ _vitest.vi.spyOn(console, "warn").mockImplementation(() => {});
402
+ (await launch()).updateError(downloadFailure());
403
+ await flush();
404
+ (await launch()).updateError(downloadFailure());
405
+ await flush();
406
+ const ids = sentEvents().map(({
407
+ eventId
408
+ }) => eventId);
409
+ (0, _vitest.expect)(ids).toHaveLength(4);
410
+ (0, _vitest.expect)(new Set(ids).size).toBe(1);
411
+ });
412
+ (0, _vitest.it)("skips check failures while offline and reports the others against the running bundle", async () => {
413
+ const app = await launch();
414
+ const checkFailure = {
415
+ stage: "check",
416
+ channel: "production",
417
+ bundleId: "bundle-a",
418
+ releaseId: "release-a",
419
+ updateStrategy: "appVersion",
420
+ cause: new Error("check failed")
421
+ };
422
+ app.updateError({
423
+ ...checkFailure,
424
+ reason: "network"
425
+ });
426
+ app.updateError({
427
+ ...checkFailure,
428
+ reason: "http",
429
+ httpStatus: 503
430
+ });
431
+ await flush();
432
+ (0, _vitest.expect)(sentEvents()).toEqual([_vitest.expect.objectContaining({
433
+ fromBundleId: "bundle-a",
434
+ metadata: {
435
+ failure: {
436
+ httpStatus: 503,
437
+ reason: "http",
438
+ stage: "check"
439
+ }
440
+ },
441
+ toBundleId: "bundle-a",
442
+ toReleaseId: null,
443
+ type: "UPDATE_FAILED"
444
+ })]);
445
+ });
446
+ (0, _vitest.it)("drops a failure an older server refuses, without retrying, warning, or pausing", async () => {
447
+ responses = [400];
448
+ const warn = _vitest.vi.spyOn(console, "warn").mockImplementation(() => {});
449
+ const app = await launch();
450
+ app.updateError(downloadFailure());
451
+ await flush();
452
+ app.updateError(downloadFailure());
453
+ app.appReady(unchangedLaunch());
454
+ await flush();
455
+ (0, _vitest.expect)(sentTypes()).toEqual(["UPDATE_FAILED", "UNCHANGED"]);
456
+ (0, _vitest.expect)(warn).not.toHaveBeenCalled();
457
+ });
458
+ });
459
+ (0, _vitest.describe)("event details", () => {
460
+ (0, _vitest.it)("says how a download arrived, and when a patch fell back", async () => {
461
+ const app = await launch();
462
+ app.downloaded({
463
+ ...download,
464
+ delivery: "patch",
465
+ patchFallback: false
466
+ });
467
+ app.downloaded({
468
+ ...download,
469
+ toBundleId: "bundle-c",
470
+ delivery: "archive",
471
+ patchFallback: true
472
+ });
473
+ await flush();
474
+ (0, _vitest.expect)(sentEvents().map(({
475
+ metadata
476
+ }) => metadata)).toEqual([{
477
+ delivery: "patch"
478
+ }, {
479
+ delivery: "archive",
480
+ patchFallback: true
481
+ }]);
482
+ });
483
+ (0, _vitest.it)("says why the previous process exited on a recovery only", async () => {
484
+ const app = await launch();
485
+ app.appReady({
486
+ ...appliedLaunch,
487
+ status: "RECOVERED",
488
+ fromBundleId: "bundle-b",
489
+ toBundleId: "bundle-a",
490
+ previousProcessExit: "CRASH"
491
+ });
492
+ await flush();
493
+ (await launch()).appReady({
494
+ ...appliedLaunch,
495
+ toBundleId: "bundle-c",
496
+ previousProcessExit: "USER_REQUESTED"
497
+ });
498
+ await flush();
499
+ (0, _vitest.expect)(sentEvents().map(({
500
+ type,
501
+ metadata
502
+ }) => [type, metadata])).toEqual([["RECOVERED", {
503
+ previousProcessExit: "CRASH"
504
+ }], ["UPDATE_APPLIED", undefined]]);
505
+ });
506
+ (0, _vitest.it)("sends every failure detail it has", async () => {
507
+ const app = await launch();
508
+ app.updateError(downloadFailure({
509
+ reason: "http",
510
+ resource: "archive",
511
+ httpStatus: 403,
512
+ originCode: "ExpiredToken",
513
+ previousProcessExit: "ANR"
514
+ }));
515
+ app.updateError(downloadFailure({
516
+ reason: "network",
517
+ resource: "file",
518
+ transport: "tls"
519
+ }));
520
+ await flush();
521
+ (0, _vitest.expect)(sentEvents().map(({
522
+ metadata
523
+ }) => metadata?.failure)).toEqual([{
524
+ stage: "download",
525
+ reason: "http",
526
+ resource: "archive",
527
+ httpStatus: 403,
528
+ originCode: "ExpiredToken",
529
+ previousProcessExit: "ANR"
530
+ }, {
531
+ stage: "download",
532
+ reason: "network",
533
+ resource: "file",
534
+ transport: "tls"
535
+ }]);
536
+ });
537
+ });
538
+ (0, _vitest.describe)("a success for a failed target", () => {
539
+ (0, _vitest.it)("drops a queued failure for the target a download then staged", async () => {
540
+ responses = [503];
541
+ const app = await launch();
542
+ app.appReady(unchangedLaunch());
543
+ app.updateError(downloadFailure());
544
+ app.downloaded(download);
545
+ await flush();
546
+ (0, _vitest.expect)(sentTypes()).toEqual(["UNCHANGED", "UNCHANGED", "UPDATE_DOWNLOADED"]);
547
+ });
548
+ (0, _vitest.it)("drops a failure waiting out a backoff once its target applies", async () => {
549
+ responses = [503];
550
+ const app = await launch();
551
+ app.updateError(downloadFailure());
552
+ await Promise.resolve();
553
+ await _vitest.vi.advanceTimersByTimeAsync(0);
554
+ app.appReady(appliedLaunch);
555
+ await flush();
556
+ (0, _vitest.expect)(sentTypes()).toEqual(["UPDATE_FAILED", "UPDATE_APPLIED"]);
557
+ });
558
+ (0, _vitest.it)("keeps a failure for another target", async () => {
559
+ const app = await launch();
560
+ app.updateError(downloadFailure({
561
+ targetBundleId: "bundle-c"
562
+ }));
563
+ app.downloaded(download);
564
+ await flush();
565
+ (0, _vitest.expect)(sentTypes()).toEqual(["UPDATE_FAILED", "UPDATE_DOWNLOADED"]);
566
+ });
567
+ });
568
+ (0, _vitest.describe)("user", () => {
569
+ (0, _vitest.it)("attaches a user set before init and keeps it across launches", async () => {
570
+ (await launch({}, plugin => plugin.setUser({
571
+ userId: 42
572
+ }))).appReady(unchangedLaunch());
573
+ await flush();
574
+ (await launch()).appReady(appliedLaunch);
575
+ await flush();
576
+ const app = await launch();
577
+ app.plugin.setUser(null);
578
+ app.appReady(unchangedLaunch({
579
+ bundleId: "bundle-c"
580
+ }));
581
+ await flush();
582
+ (0, _vitest.expect)(sentEvents().map(({
583
+ userId
584
+ }) => userId)).toEqual(["42", "42", undefined]);
585
+ (0, _vitest.expect)(sentEvents().every(event => !("username" in event))).toBe(true);
586
+ });
587
+ (0, _vitest.it)("takes only a user id", () => {
588
+ const user = {
589
+ userId: "user-1"
590
+ };
591
+ // @ts-expect-error Insights keeps no username.
592
+ const withName = {
593
+ userId: "user-1",
594
+ username: "Alex"
595
+ };
596
+ (0, _vitest.expect)([user, withName]).toHaveLength(2);
597
+ });
598
+ });
599
+ _vitest.it.each([{
600
+ debug: undefined,
601
+ sends: false
602
+ }, {
603
+ debug: true,
604
+ sends: true
605
+ }])("sends from a debug build only with debug: true ($debug)", async ({
606
+ debug,
607
+ sends
608
+ }) => {
609
+ _vitest.vi.stubGlobal("__DEV__", true);
610
+ const app = await launch(debug === undefined ? {} : {
611
+ debug
612
+ });
613
+ app.appReady(unchangedLaunch());
614
+ await flush();
615
+ (0, _vitest.expect)(fetchMock).toHaveBeenCalledTimes(sends ? 1 : 0);
616
+ });
617
+ (0, _vitest.it)("reports a failed install id read as a plugin error, not an update failure", async () => {
618
+ native.getInstallId.mockImplementationOnce(() => {
619
+ throw new Error("native install id unavailable");
620
+ });
621
+ const warn = _vitest.vi.spyOn(console, "warn").mockImplementation(() => {});
622
+ const app = await launch();
623
+ app.appReady(unchangedLaunch());
624
+ await flush();
625
+ (0, _vitest.expect)(fetchMock).not.toHaveBeenCalled();
626
+ (0, _vitest.expect)(warn).toHaveBeenCalledWith('[HotUpdater] Plugin "insights" failed in onAppReady', _vitest.expect.objectContaining({
627
+ message: "native install id unavailable"
628
+ }));
629
+ });
630
+ (0, _vitest.it)("skips a report without a native app version", async () => {
631
+ native.getAppVersion.mockReturnValue(null);
632
+ const warn = _vitest.vi.spyOn(console, "warn").mockImplementation(() => {});
633
+ const app = await launch();
634
+ app.appReady(unchangedLaunch());
635
+ await flush();
636
+ (0, _vitest.expect)(fetchMock).not.toHaveBeenCalled();
637
+ (0, _vitest.expect)(warn).toHaveBeenCalledWith("[HotUpdater] Insights needs the native app version; the UNCHANGED event was not sent.");
638
+ });
639
+ });
640
+ //# sourceMappingURL=insights.spec.js.map