@hot-updater/react-native 1.0.0-rc.17 → 1.0.0-rc.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 (240) hide show
  1. package/lib/commonjs/checkForUpdate.js +7 -9
  2. package/lib/commonjs/checkForUpdate.js.map +1 -1
  3. package/lib/commonjs/clientPlugin.js +7 -43
  4. package/lib/commonjs/clientPlugin.js.map +1 -1
  5. package/lib/commonjs/httpClient.js +7 -9
  6. package/lib/commonjs/httpClient.js.map +1 -1
  7. package/lib/commonjs/index.js +10 -0
  8. package/lib/commonjs/index.js.map +1 -1
  9. package/lib/commonjs/native.js +4 -4
  10. package/lib/commonjs/native.js.map +1 -1
  11. package/lib/commonjs/pluginHost.js +26 -190
  12. package/lib/commonjs/pluginHost.js.map +1 -1
  13. package/lib/commonjs/releaseCatalogCache.js +7 -59
  14. package/lib/commonjs/releaseCatalogCache.js.map +1 -1
  15. package/lib/commonjs/sdkVersion.js +1 -1
  16. package/lib/module/checkForUpdate.js +1 -3
  17. package/lib/module/checkForUpdate.js.map +1 -1
  18. package/lib/module/clientPlugin.js +1 -41
  19. package/lib/module/clientPlugin.js.map +1 -1
  20. package/lib/module/httpClient.js +1 -3
  21. package/lib/module/httpClient.js.map +1 -1
  22. package/lib/module/index.js +2 -0
  23. package/lib/module/index.js.map +1 -1
  24. package/lib/module/native.js +1 -1
  25. package/lib/module/native.js.map +1 -1
  26. package/lib/module/pluginHost.js +22 -187
  27. package/lib/module/pluginHost.js.map +1 -1
  28. package/lib/module/releaseCatalogCache.js +3 -54
  29. package/lib/module/releaseCatalogCache.js.map +1 -1
  30. package/lib/module/sdkVersion.js +1 -1
  31. package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -1
  32. package/lib/typescript/commonjs/clientPlugin.d.ts +1 -184
  33. package/lib/typescript/commonjs/clientPlugin.d.ts.map +1 -1
  34. package/lib/typescript/commonjs/httpClient.d.ts +1 -2
  35. package/lib/typescript/commonjs/httpClient.d.ts.map +1 -1
  36. package/lib/typescript/commonjs/index.d.ts +1 -0
  37. package/lib/typescript/commonjs/index.d.ts.map +1 -1
  38. package/lib/typescript/commonjs/native.d.ts +1 -1
  39. package/lib/typescript/commonjs/native.d.ts.map +1 -1
  40. package/lib/typescript/commonjs/pluginHost.d.ts +3 -28
  41. package/lib/typescript/commonjs/pluginHost.d.ts.map +1 -1
  42. package/lib/typescript/commonjs/releaseCatalogCache.d.ts +1 -13
  43. package/lib/typescript/commonjs/releaseCatalogCache.d.ts.map +1 -1
  44. package/lib/typescript/commonjs/sdkVersion.d.ts +1 -1
  45. package/lib/typescript/commonjs/types.d.ts +1 -1
  46. package/lib/typescript/commonjs/types.d.ts.map +1 -1
  47. package/lib/typescript/commonjs/wrap.types.d.ts +2 -2
  48. package/lib/typescript/module/checkForUpdate.d.ts.map +1 -1
  49. package/lib/typescript/module/clientPlugin.d.ts +1 -184
  50. package/lib/typescript/module/clientPlugin.d.ts.map +1 -1
  51. package/lib/typescript/module/httpClient.d.ts +1 -2
  52. package/lib/typescript/module/httpClient.d.ts.map +1 -1
  53. package/lib/typescript/module/index.d.ts +1 -0
  54. package/lib/typescript/module/index.d.ts.map +1 -1
  55. package/lib/typescript/module/native.d.ts +1 -1
  56. package/lib/typescript/module/native.d.ts.map +1 -1
  57. package/lib/typescript/module/pluginHost.d.ts +3 -28
  58. package/lib/typescript/module/pluginHost.d.ts.map +1 -1
  59. package/lib/typescript/module/releaseCatalogCache.d.ts +1 -13
  60. package/lib/typescript/module/releaseCatalogCache.d.ts.map +1 -1
  61. package/lib/typescript/module/sdkVersion.d.ts +1 -1
  62. package/lib/typescript/module/types.d.ts +1 -1
  63. package/lib/typescript/module/types.d.ts.map +1 -1
  64. package/lib/typescript/module/wrap.types.d.ts +2 -2
  65. package/package.json +7 -16
  66. package/src/checkForUpdate.ts +4 -6
  67. package/src/clientPlugin.ts +17 -231
  68. package/src/httpClient.ts +4 -4
  69. package/src/index.ts +7 -0
  70. package/src/native.ts +1 -1
  71. package/src/pluginHost.ts +24 -241
  72. package/src/releaseCatalogCache.ts +7 -136
  73. package/src/sdkVersion.ts +1 -1
  74. package/src/types.ts +1 -1
  75. package/src/wrap.types.ts +2 -2
  76. package/android/src/test/java/com/hotupdater/BsdiffPatchTest.kt +0 -46
  77. package/android/src/test/java/com/hotupdater/BundleFileStorageServiceTest.kt +0 -2236
  78. package/android/src/test/java/com/hotupdater/HotUpdaterExceptionTest.kt +0 -220
  79. package/android/src/test/java/com/hotupdater/HotUpdaterImplTest.kt +0 -264
  80. package/android/src/test/java/com/hotupdater/HotUpdaterRecoveryStateTest.kt +0 -97
  81. package/android/src/test/java/com/hotupdater/InstallIdentityServiceTest.kt +0 -71
  82. package/android/src/test/java/com/hotupdater/KeyValueStorageServiceTest.kt +0 -106
  83. package/android/src/test/java/com/hotupdater/NativeConfigUtilsTest.kt +0 -20
  84. package/android/src/test/java/com/hotupdater/NoBackupContext.kt +0 -11
  85. package/android/src/test/java/com/hotupdater/OkHttpDownloadServiceTest.kt +0 -397
  86. package/android/src/test/java/com/hotupdater/PendingCrashRecoveryTest.kt +0 -44
  87. package/android/src/test/java/com/hotupdater/PreviousProcessExitTest.kt +0 -57
  88. package/android/src/test/java/com/hotupdater/RelativePathResolverTest.kt +0 -41
  89. package/android/src/test/java/com/hotupdater/ReleaseCatalogCacheServiceTest.kt +0 -118
  90. package/android/src/test/java/com/hotupdater/TarBrArchiveExtractorTest.kt +0 -206
  91. package/lib/commonjs/appReady.spec.js +0 -360
  92. package/lib/commonjs/appReady.spec.js.map +0 -1
  93. package/lib/commonjs/appReady.test-utils.js +0 -25
  94. package/lib/commonjs/appReady.test-utils.js.map +0 -1
  95. package/lib/commonjs/baseURL.js +0 -16
  96. package/lib/commonjs/baseURL.js.map +0 -1
  97. package/lib/commonjs/catalogCacheNative.spec.js +0 -31
  98. package/lib/commonjs/catalogCacheNative.spec.js.map +0 -1
  99. package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js +0 -936
  100. package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js.map +0 -1
  101. package/lib/commonjs/entryImportGraph.spec.js +0 -50
  102. package/lib/commonjs/entryImportGraph.spec.js.map +0 -1
  103. package/lib/commonjs/httpClient.spec.js +0 -171
  104. package/lib/commonjs/httpClient.spec.js.map +0 -1
  105. package/lib/commonjs/index.spec.js +0 -395
  106. package/lib/commonjs/index.spec.js.map +0 -1
  107. package/lib/commonjs/iosInterop.spec.js +0 -18
  108. package/lib/commonjs/iosInterop.spec.js.map +0 -1
  109. package/lib/commonjs/native.spec.js +0 -910
  110. package/lib/commonjs/native.spec.js.map +0 -1
  111. package/lib/commonjs/pluginHost.spec.js +0 -292
  112. package/lib/commonjs/pluginHost.spec.js.map +0 -1
  113. package/lib/commonjs/plugins/insights/eventId.js +0 -129
  114. package/lib/commonjs/plugins/insights/eventId.js.map +0 -1
  115. package/lib/commonjs/plugins/insights/eventId.spec.js +0 -47
  116. package/lib/commonjs/plugins/insights/eventId.spec.js.map +0 -1
  117. package/lib/commonjs/plugins/insights/index.js +0 -272
  118. package/lib/commonjs/plugins/insights/index.js.map +0 -1
  119. package/lib/commonjs/plugins/insights/insights.spec.js +0 -640
  120. package/lib/commonjs/plugins/insights/insights.spec.js.map +0 -1
  121. package/lib/commonjs/plugins/insights/sender.js +0 -128
  122. package/lib/commonjs/plugins/insights/sender.js.map +0 -1
  123. package/lib/commonjs/plugins/insights/sender.spec.js +0 -265
  124. package/lib/commonjs/plugins/insights/sender.spec.js.map +0 -1
  125. package/lib/commonjs/plugins/insights/state.js +0 -145
  126. package/lib/commonjs/plugins/insights/state.js.map +0 -1
  127. package/lib/commonjs/releaseCatalogCache.spec.js +0 -213
  128. package/lib/commonjs/releaseCatalogCache.spec.js.map +0 -1
  129. package/lib/commonjs/releaseCatalogCacheNativeContract.spec.js +0 -64
  130. package/lib/commonjs/releaseCatalogCacheNativeContract.spec.js.map +0 -1
  131. package/lib/commonjs/store.notification.spec.js +0 -84
  132. package/lib/commonjs/store.notification.spec.js.map +0 -1
  133. package/lib/commonjs/store.spec.js +0 -182
  134. package/lib/commonjs/store.spec.js.map +0 -1
  135. package/lib/commonjs/updateError.spec.js +0 -149
  136. package/lib/commonjs/updateError.spec.js.map +0 -1
  137. package/lib/commonjs/wrap.progress.spec.js +0 -195
  138. package/lib/commonjs/wrap.progress.spec.js.map +0 -1
  139. package/lib/commonjs/wrap.spec.js +0 -232
  140. package/lib/commonjs/wrap.spec.js.map +0 -1
  141. package/lib/module/appReady.spec.js +0 -359
  142. package/lib/module/appReady.spec.js.map +0 -1
  143. package/lib/module/appReady.test-utils.js +0 -19
  144. package/lib/module/appReady.test-utils.js.map +0 -1
  145. package/lib/module/baseURL.js +0 -11
  146. package/lib/module/baseURL.js.map +0 -1
  147. package/lib/module/catalogCacheNative.spec.js +0 -31
  148. package/lib/module/catalogCacheNative.spec.js.map +0 -1
  149. package/lib/module/checkForUpdate.releaseCatalog.spec.js +0 -935
  150. package/lib/module/checkForUpdate.releaseCatalog.spec.js.map +0 -1
  151. package/lib/module/entryImportGraph.spec.js +0 -50
  152. package/lib/module/entryImportGraph.spec.js.map +0 -1
  153. package/lib/module/httpClient.spec.js +0 -171
  154. package/lib/module/httpClient.spec.js.map +0 -1
  155. package/lib/module/index.spec.js +0 -394
  156. package/lib/module/index.spec.js.map +0 -1
  157. package/lib/module/iosInterop.spec.js +0 -18
  158. package/lib/module/iosInterop.spec.js.map +0 -1
  159. package/lib/module/native.spec.js +0 -909
  160. package/lib/module/native.spec.js.map +0 -1
  161. package/lib/module/pluginHost.spec.js +0 -291
  162. package/lib/module/pluginHost.spec.js.map +0 -1
  163. package/lib/module/plugins/insights/eventId.js +0 -122
  164. package/lib/module/plugins/insights/eventId.js.map +0 -1
  165. package/lib/module/plugins/insights/eventId.spec.js +0 -47
  166. package/lib/module/plugins/insights/eventId.spec.js.map +0 -1
  167. package/lib/module/plugins/insights/index.js +0 -268
  168. package/lib/module/plugins/insights/index.js.map +0 -1
  169. package/lib/module/plugins/insights/insights.spec.js +0 -639
  170. package/lib/module/plugins/insights/insights.spec.js.map +0 -1
  171. package/lib/module/plugins/insights/sender.js +0 -123
  172. package/lib/module/plugins/insights/sender.js.map +0 -1
  173. package/lib/module/plugins/insights/sender.spec.js +0 -265
  174. package/lib/module/plugins/insights/sender.spec.js.map +0 -1
  175. package/lib/module/plugins/insights/state.js +0 -139
  176. package/lib/module/plugins/insights/state.js.map +0 -1
  177. package/lib/module/releaseCatalogCache.spec.js +0 -213
  178. package/lib/module/releaseCatalogCache.spec.js.map +0 -1
  179. package/lib/module/releaseCatalogCacheNativeContract.spec.js +0 -64
  180. package/lib/module/releaseCatalogCacheNativeContract.spec.js.map +0 -1
  181. package/lib/module/store.notification.spec.js +0 -85
  182. package/lib/module/store.notification.spec.js.map +0 -1
  183. package/lib/module/store.spec.js +0 -181
  184. package/lib/module/store.spec.js.map +0 -1
  185. package/lib/module/updateError.spec.js +0 -149
  186. package/lib/module/updateError.spec.js.map +0 -1
  187. package/lib/module/wrap.progress.spec.js +0 -196
  188. package/lib/module/wrap.progress.spec.js.map +0 -1
  189. package/lib/module/wrap.spec.js +0 -233
  190. package/lib/module/wrap.spec.js.map +0 -1
  191. package/lib/typescript/commonjs/appReady.test-utils.d.ts +0 -9
  192. package/lib/typescript/commonjs/appReady.test-utils.d.ts.map +0 -1
  193. package/lib/typescript/commonjs/baseURL.d.ts +0 -4
  194. package/lib/typescript/commonjs/baseURL.d.ts.map +0 -1
  195. package/lib/typescript/commonjs/plugins/insights/eventId.d.ts +0 -18
  196. package/lib/typescript/commonjs/plugins/insights/eventId.d.ts.map +0 -1
  197. package/lib/typescript/commonjs/plugins/insights/index.d.ts +0 -40
  198. package/lib/typescript/commonjs/plugins/insights/index.d.ts.map +0 -1
  199. package/lib/typescript/commonjs/plugins/insights/sender.d.ts +0 -74
  200. package/lib/typescript/commonjs/plugins/insights/sender.d.ts.map +0 -1
  201. package/lib/typescript/commonjs/plugins/insights/state.d.ts +0 -46
  202. package/lib/typescript/commonjs/plugins/insights/state.d.ts.map +0 -1
  203. package/lib/typescript/module/appReady.test-utils.d.ts +0 -9
  204. package/lib/typescript/module/appReady.test-utils.d.ts.map +0 -1
  205. package/lib/typescript/module/baseURL.d.ts +0 -4
  206. package/lib/typescript/module/baseURL.d.ts.map +0 -1
  207. package/lib/typescript/module/plugins/insights/eventId.d.ts +0 -18
  208. package/lib/typescript/module/plugins/insights/eventId.d.ts.map +0 -1
  209. package/lib/typescript/module/plugins/insights/index.d.ts +0 -40
  210. package/lib/typescript/module/plugins/insights/index.d.ts.map +0 -1
  211. package/lib/typescript/module/plugins/insights/sender.d.ts +0 -74
  212. package/lib/typescript/module/plugins/insights/sender.d.ts.map +0 -1
  213. package/lib/typescript/module/plugins/insights/state.d.ts +0 -46
  214. package/lib/typescript/module/plugins/insights/state.d.ts.map +0 -1
  215. package/plugins/insights/package.json +0 -8
  216. package/src/appReady.spec.ts +0 -393
  217. package/src/appReady.test-utils.ts +0 -31
  218. package/src/baseURL.ts +0 -15
  219. package/src/catalogCacheNative.spec.ts +0 -63
  220. package/src/checkForUpdate.releaseCatalog.spec.ts +0 -966
  221. package/src/entryImportGraph.spec.ts +0 -65
  222. package/src/httpClient.spec.ts +0 -216
  223. package/src/index.spec.ts +0 -434
  224. package/src/iosInterop.spec.ts +0 -30
  225. package/src/native.spec.ts +0 -978
  226. package/src/pluginHost.spec.ts +0 -297
  227. package/src/plugins/insights/eventId.spec.ts +0 -60
  228. package/src/plugins/insights/eventId.ts +0 -171
  229. package/src/plugins/insights/index.ts +0 -367
  230. package/src/plugins/insights/insights.spec.ts +0 -732
  231. package/src/plugins/insights/sender.spec.ts +0 -287
  232. package/src/plugins/insights/sender.ts +0 -221
  233. package/src/plugins/insights/state.ts +0 -184
  234. package/src/releaseCatalogCache.spec.ts +0 -304
  235. package/src/releaseCatalogCacheNativeContract.spec.ts +0 -80
  236. package/src/store.notification.spec.ts +0 -102
  237. package/src/store.spec.ts +0 -215
  238. package/src/updateError.spec.ts +0 -144
  239. package/src/wrap.progress.spec.ts +0 -232
  240. package/src/wrap.spec.ts +0 -262
@@ -1,640 +0,0 @@
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